Main Page | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

grobner.H

00001 #ifndef _GROBNER_H_
00002 #define _GROBNER_H_
00003 
00004 #include "polynomials.H"
00005 #include "matrix.H"
00006 #include <list>
00007 #include <stack>
00008 #include <utility>
00009 
00011 /*
00012  * In one variable for example, this is the remainder in the Euclidean
00013  * long division (of f by the one element in the list).
00014  */
00015 template <class K>
00016 Polynomial<K> division_remainder(const Polynomial<K>& f, const list< Polynomial<K> >& F){
00017   Polynomial<K> h,r,temp;
00018   K c;
00019   PowProd a,b;
00020   typename list< Polynomial<K> >::const_iterator it;
00021   
00022   h= f;
00023   
00024   while( !h.is_zero() ){
00025 
00026     a=h.lp(); 
00027     for(it= F.begin(); it != F.end(); it++){
00028       b= it->lp();
00029       if(b.divides(a))
00030         break;
00031     }
00032     if(it != F.end()){ // lp(h) was divisible by some lp(f_i) ?
00033 
00034       c= h.coeff_of(a);
00035       c/= it->coeff_of(b);
00036       c *= -1;
00037       a /= b;
00038       temp= Polynomial<K>( a );
00039       temp *= c;
00040       temp *= (*it);
00041       h += temp;
00042     }     
00043     else{
00044 
00045       temp= h.lt();      
00046       r += temp;
00047       temp *= -1;
00048       h += temp;
00049     }
00050     
00051   }
00052   r.alphabet= (Alphabet *) f.alphabet;
00053   return r;
00054 }
00056 
00062 template <class K>
00063 Polynomial<K> division_remainder_with_coefficients(const Polynomial<K>& f, 
00064                                                    const list< Polynomial<K> >& F,
00065                                                    Tuple< Polynomial<K> >& U){
00066   Polynomial<K> h,r,temp;
00067   K c;
00068   PowProd a,b;
00069   typename list< Polynomial<K> >::const_iterator it;
00070   long i;
00071   
00072   h= f;
00073   //find the right size for U, and set it to 0
00074   for(it= F.begin(), i=0; it != F.end(); it++, i++);
00075   U.resize(i);
00076   for(i=0; i< U.size(); i++){
00077     U[i].sets_to_zero();
00078     U[i].alphabet= (Alphabet *) f.alphabet;
00079   }
00080   
00081   while( !h.is_zero() ){
00082 
00083     a=h.lp(); 
00084     for(it= F.begin(), i=0; it != F.end(); it++, i++){
00085       b= it->lp();
00086       if(b.divides(a))
00087         break;
00088     }
00089     if(it != F.end()){ // lp(h) was divisible by some lp(f_i) ?
00090 
00091       c= h.coeff_of(a);
00092       c/= it->coeff_of(b);
00093       a /= b;
00094       temp= Polynomial<K>( a ) * c;
00095       U[i] += temp;
00096       temp *= (*it) * (-1);
00097       h += temp;
00098     }     
00099     else{
00100 
00101       temp= h.lt();      
00102       r += temp;
00103       temp *= -1;
00104       h += temp;
00105     }
00106     
00107   }
00108   r.alphabet= (Alphabet *) f.alphabet;
00109   return r;
00110 }
00111 
00112 
00114 
00121 template <class K>
00122 class Ideal {
00123 private:
00124   list< Polynomial<K> > G, R, P;
00125   list< pair< Polynomial<K>*, Polynomial<K>* > > B;
00126   
00127   void filter_B(Polynomial<K> *ptr)
00128   {
00129     typename list< pair< Polynomial<K>*, Polynomial<K>* > >::iterator it;
00130     
00131     for(it= B.begin(); it!= B.end();)
00132       if( (it->first == ptr) || (it->second == ptr) )
00133         it= B.erase(it);
00134       else
00135         it++;
00136     
00137   }
00138   
00139   void reduce_all()
00140   {
00141     Polynomial<K> h;
00142     typename list< Polynomial<K> >::iterator it;
00143     
00144       
00145     while( !R.empty() ){
00146 
00147       h= R.front();
00148       R.pop_front();
00149       if( !P.empty() ){ 
00150         // P empty only happens the 1st time this method is called
00151         //(from grobnerize()). In this case G is empty also.
00152         it= P.begin();
00153         G.splice(G.end(), P); // G= G union P; P emptied
00154         h= division_remainder(h, G);
00155         P.splice(P.begin(), G, it, G.end() ); // G and P back to normal
00156       }
00157       
00158 
00159       if( !h.is_zero() ){
00160 
00161                 
00162 
00163         for(it= G.begin(); it!= G.end();){
00164          
00165           if( h.lp().divides( it->lp() ) ){
00166             filter_B( &(*it) );
00167             R.push_back( *it );
00168             it= G.erase(it);
00169           }
00170           else
00171             it++;
00172         }
00173         
00174 
00175         for(it= P.begin(); it!= P.end();){
00176           
00177           
00178           if( h.lp().divides( it->lp() ) ){
00179             R.push_back( *it );
00180             it= P.erase(it);
00181           }
00182           else
00183             it++;
00184         }
00185         
00186 
00187 
00188         P.push_back(h);
00189         
00190         
00191       }//if h not zero
00192       
00193     }//while
00194     
00195       
00196   }//reduce_all
00197 /*
00198  * This adds to B all the pairs of the form
00199  * (g, p) with g in G union P    (g != p)
00200  *             p in P 
00201  * 
00202  */
00203   void populate_B()
00204   {
00205     typename list< Polynomial<K> >::iterator itG, itP, book;
00206     
00207     
00208     for(itG= G.begin(); itG!= G.end(); itG++)
00209       for(itP= P.begin(); itP!= P.end(); itP++)
00210         B.push_back( make_pair( &(*itG), &(*itP) ) );
00211     
00212     for(itG= P.begin(); itG!= P.end(); itG++)
00213       for(itP= itG, itP++; itP!= P.end(); itP++)
00214         B.push_back( make_pair( &(*itG), &(*itP) ) );
00215           
00216   }
00217   
00218 
00219   void new_basis()
00220   {
00221     list< Polynomial<K> > H;
00222     typename list< Polynomial<K> >::iterator itG, itH;
00223     Polynomial<K> poly;
00224     
00225   
00226     populate_B();
00227     G.splice(G.end(), P);// G= G union P; P emptied
00228     H= G;
00229     
00230     for(itG= G.begin(), itH= H.begin(); itG!= G.end(); itG++){
00231       itH= H.erase(itH);
00232       poly= division_remainder( *itG, H);
00233       H.push_front(*itG);
00234       *itG= poly;
00235     }
00236 
00237       
00238   }
00239   
00240   
00241 
00242 public:
00244   list< Polynomial<K> > generators;
00246 
00255   void grobnerize()
00256   {
00257     pair< Polynomial<K>*, Polynomial<K>* > fg;
00258     Polynomial<K> Spoly, h;
00259     typename list< Polynomial<K> >::iterator it;
00260     
00261 
00262     //init
00263     R.clear();
00264     R.splice( R.begin(), generators );
00265     P.clear();
00266     G.clear();
00267     B.clear();
00268     reduce_all();
00269     new_basis();
00270     
00271     while( !B.empty() ){
00272 
00273       fg=B.front();
00274       B.pop_front();
00275       
00276       if( fg.first->lp().prime_to( fg.second->lp() ) )
00277         h.sets_to_zero();
00278       else{
00279         Spoly= S_polynomial( *fg.first , *fg.second ); //computes S(f,g)
00280         h= division_remainder(Spoly, G); //S(f,g) -> h by G
00281       }
00282       
00283       if( !h.is_zero() ){
00284         P.clear();
00285         P.push_back( h );
00286         R.clear();
00287         
00288         for(it= G.begin(); it!= G.end();)
00289           if(h.lp().divides( it->lp() ) ) {
00290             R.push_back( *it );
00291             filter_B( &(*it) );
00292             it= G.erase(it);
00293           }
00294           else
00295             it++;
00296           
00297         reduce_all();
00298         new_basis();
00299       }// if h non zero
00300     }//main while loop
00301     
00302     //finally:
00303     generators.splice( generators.begin(), G);
00304     
00305   }
00306   
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00315 
00328   void grobnerize_with_coefficients(Matrix< Polynomial<K> >& M){
00329     stack< pair< Polynomial<K>*, Polynomial<K>* > > couples;
00330     pair< Polynomial<K>*, Polynomial<K>* > fg;
00331     pair< Polynomial<K>, Polynomial<K> > S_coeffs;
00332     Polynomial<K> Spoly, h, I;
00333     typename list< Polynomial<K> >::iterator it, itprime;
00334     Tuple< Polynomial<K> > U, tuple;
00335     list< Tuple< Polynomial<K> > > coeffs;
00336     long i, j, n, m;
00337     
00338     if(generators.begin() == generators.end())
00339       return;
00340     //I= one
00341     I= Polynomial<K>( PowProd(0) );
00342     I.alphabet= generators.begin()->alphabet;
00343     
00344     //write the beginning of the matrix, as a list of tuples
00345     //we write it as -identity, and at the very end we will
00346     //multiply everything by -1 again. This is because of
00347     //division_remainder_with_coefficients which returns 
00348     //the opposite of the coeffs we need.
00349     n= 0;
00350     for(it= generators.begin(); it!= generators.end(); it++){
00351       n++;
00352       tuple= Tuple< Polynomial<K> >(n);
00353       tuple[n-1]= I*(-1);
00354       coeffs.push_back( tuple );
00355     }
00356 
00357     m= 0;
00358     // populates the stack with the addresses of all pairs
00359     // of polynomials from the list
00360     
00361     for(it= generators.begin(); it !=generators.end(); it++)
00362       for(itprime= it, itprime++; itprime != generators.end(); itprime++)
00363         couples.push(   make_pair( &(*it) , &(*itprime) )     );
00364     
00365     
00366     while( !couples.empty() ){
00367       
00368       fg= couples.top(); // take (f,g) from the stack
00369       couples.pop();
00370 
00371       if( fg.first->lp().prime_to( fg.second->lp() ) )
00372         h.sets_to_zero();
00373       else{
00374         Spoly= S_polynomial_with_coefficients( *fg.first , *fg.second, S_coeffs ); 
00375         //computes S(f,g)
00376         h= division_remainder_with_coefficients(Spoly, generators, U); 
00377         //S(f,g) -> h by F, so S(f,g)=h + sum U[i]F[i]
00378         //so h = S(f,g) - sum U[i]*F[i], hence all the (-1) signs
00379       }
00380       
00381       if( !h.is_zero() ){
00382         //add it
00383         generators.push_back(h);
00384         //updates the stack of couples
00385         itprime= generators.end();
00386         itprime--; //itprime points at the last element, ie h
00387         for(it= generators.begin(); it != itprime; it++)
00388           couples.push(  make_pair(  &(*it), &(*itprime)  )  )  ;
00389         //build -(coords of h). In the end we will multiply by (-1)
00390         //set i and j...
00391         for(i=0, it=generators.begin(); it!= generators.end(); i++, it++)
00392           if( &(*it) == fg.first )
00393             break;
00394         for(j=0, it=generators.begin(); it!= generators.end(); j++, it++)
00395           if( &(*it) == fg.second )
00396             break;
00397         U[i]+= S_coeffs.first * (-1);
00398         U[j]+= S_coeffs.second * (-1);
00399         coeffs.push_back( U );
00400         m++;
00401       }
00402       
00403     }// end of while loop
00404     
00405   
00406     if( m==0 ) { //nothing added?
00407       M.get_data_from_tuple_list(coeffs);
00408       M*= I*(-1);
00409       return;
00410     }
00411     //else M would not be square
00412     coeffs.begin()->resize(n+m); //this remedies it!
00413     //M will be square of size n + m now:
00414     M.get_data_from_tuple_list( coeffs );
00415     M*= I*(-1); //finally ! signs corrected !
00416     //now compute M**m, it will have m columns of 0
00417     //on the right
00418     Matrix< Polynomial<K> > N;
00419     N= M;
00420     i=m-1;
00421     while(i>0){
00422       M*= N;
00423       i--;
00424     }
00425     //get rid of the columns of 0
00426     M.resize(n+m, n);
00427     //tada !!
00428   }
00429   
00431 
00444   void syzygy(Matrix< Polynomial<K> >& M) const {
00445     typename list< Polynomial<K> >::const_iterator it, itprime;
00446     list< Tuple< Polynomial<K> > > answer;
00447     Tuple< Polynomial<K> > tuple;
00448     pair< Polynomial<K>, Polynomial<K> > S_coeffs;
00449     Polynomial<K> S;
00450     long i, j;
00451 
00452     for(it= generators.begin(), i=0; it!=generators.end(); it++, i++)
00453       for(itprime= it, itprime++, j=i+1; 
00454           itprime!= generators.end(); 
00455           itprime++, j++){
00456         S= S_polynomial_with_coefficients(*it, *itprime, S_coeffs);
00457         division_remainder_with_coefficients(S, generators, tuple);
00458         tuple[i] += S_coeffs.first * (-1);
00459         tuple[j] += S_coeffs.second * (-1);
00460         answer.push_back(tuple);
00461       }
00462 
00463     M.get_data_from_tuple_list(answer);
00464   }
00465 
00466 
00467 
00468 
00470   void minimalize(){
00471     typename list< Polynomial<K> >::iterator it, itprime;
00472     PowProd a,b;
00473     K c;
00474     
00475     for(it= generators.begin(); it!= generators.end(); it++){
00476       itprime= generators.begin();
00477       while(itprime != generators.end()){
00478         
00479         if(it == itprime)
00480           itprime++;
00481         else{
00482           a=it->lp();
00483           b=itprime->lp();
00484           if(a.divides(b))
00485             itprime= generators.erase(itprime);
00486           else
00487             itprime++;
00488         }//end of else
00489         
00490       }//end of while
00491     }//end of for
00492     
00493     for(it= generators.begin(); it!= generators.end(); it++){
00494       c= it->lc();
00495       c= 1/c;
00496       *it *= c; // we divide *it by its leading coefficient
00497     }
00498 
00499   }
00500 
00502   void reduce(){
00503     typename list< Polynomial<K> >::iterator it;
00504     Polynomial<K> f;
00505     
00506     it= generators.begin();
00507     while( it != generators.end() ){
00508       f= *it;
00509       it= generators.erase(it);
00510       f= division_remainder(f,generators);
00511       generators.push_front(f);
00512     }//end of while
00513   }
00515   bool variable_shows_up(long i) const {
00516     typename list< Polynomial<K> >::const_iterator it;
00517 
00518     for(it= generators.begin(); it!= generators.end(); it++)
00519       if( it->involves_variable(i) )
00520         return true;
00521 
00522     return false;
00523   }
00524 
00525 
00526   friend ostream& operator<<(ostream& os, const Ideal<K>& J){
00527     typename list< Polynomial<K> >::const_iterator it;
00528 
00529     for(it= J.generators.begin(); it != J.generators.end(); it++)
00530       os << *it << endl;
00531     return os;
00532   }
00533 
00534 
00535 };
00536 
00537 #endif

Generated on Wed Jun 18 17:22:40 2008 for Pierre Guillot by  doxygen 1.3.9.1