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

multigrobner.H

00001 #ifndef _MULTIGROBNER_H_
00002 #define _MULTIGROBNER_H_
00003 
00004 #include "multipoly.H"
00005 #include "matrix.H"
00006 #include <list>
00007 #include <stack>
00008 #include <utility>
00009 
00011 
00017 template <class K>
00018 multiPolynomial<K> division_remainder_with_coefficients(const multiPolynomial<K>& f, 
00019                                                         const list< multiPolynomial<K> >& F,
00020                                                         Matrix< Polynomial<K> >& U){
00021   multiPolynomial<K> h,r;
00022   Polynomial<K> temp;
00023   K c;
00024   multiPolynomial<K> a,b;
00025   typename list< multiPolynomial<K> >::const_iterator it;
00026   long i;
00027 
00028   //setup
00029   h= f;
00030   r= f;
00031   r.sets_to_zero(); //for the alphabet...
00032   //find the right size for U, and set it to 0
00033   for(it= F.begin(), i=0; it != F.end(); it++, i++);
00034   U.resize(1,i);
00035   for(i=0; i< U.size(); i++){
00036     U[i].sets_to_zero();
00037     U[i].alphabet= (Alphabet *) f[0].alphabet;
00038   }
00039 
00040   temp.alphabet= (Alphabet *) f[0].alphabet;
00041   //good, now let us start
00042   while( !h.is_zero() ){
00043 
00044     a=h.lm(); 
00045     for(it= F.begin(), i=0; it != F.end(); it++, i++){
00046       b= it->lm();
00047       if(b.divides(a))
00048         break;
00049     }
00050     if(it != F.end()){ // lp(h) was divisible by some lp(f_i) ?
00051 
00052       c= h.coeff_of(a);
00053       c/= it->coeff_of(b);
00054       temp= a / b;
00055       temp*= c;
00056       //temp= Polynomial<K>( a ) * c;
00057 
00058       U[i] += temp;
00059       h += (*it) * temp * (-1);
00060     }     
00061     else{
00062       r += a * h.coeff_of(a);
00063       h += a * h.coeff_of(a)*(-1);
00064     }
00065     
00066   }
00067 
00068   //  cout << "U= " << U << endl;
00069 
00070   return r;
00071 }
00072 
00073 template <class K>
00074 multiPolynomial<K> division_remainder(const multiPolynomial<K>& f, 
00075                                       const list< multiPolynomial<K> >& F){
00076   multiPolynomial<K> h,r;
00077   Polynomial<K> temp;
00078   K c;
00079   multiPolynomial<K> a,b;
00080   typename list< multiPolynomial<K> >::const_iterator it;
00081   long i;
00082 
00083   //setup
00084   h= f;
00085   r= f;
00086   r.sets_to_zero(); //for the alphabet...
00087   temp.alphabet= (Alphabet *) f[0].alphabet;
00088   //good, now let us start
00089   while( !h.is_zero() ){
00090 
00091     a=h.lm(); 
00092     for(it= F.begin(), i=0; it != F.end(); it++, i++){
00093       b= it->lm();
00094       if(b.divides(a))
00095         break;
00096     }
00097     if(it != F.end()){ // lp(h) was divisible by some lp(f_i) ?
00098 
00099       c= h.coeff_of(a);
00100       c/= it->coeff_of(b);
00101       temp= a / b;
00102       temp*= c;
00103       //temp= Polynomial<K>( a ) * c;
00104 
00105       h += (*it) * temp * (-1);
00106     }     
00107     else{
00108       r += a * h.coeff_of(a);
00109       h += a * h.coeff_of(a)*(-1);
00110     }
00111     
00112   }
00113 
00114   return r;
00115 }
00116 
00117 
00118 
00120 
00127 template <class K>
00128 class multiIdeal {
00129 private:
00131 
00140   list< Matrix< Polynomial<K> > > coeffs;
00141 
00142   void insert(const multiPolynomial<K>& mP, 
00143               const Matrix< Polynomial<K> >&coords){
00144     long i;
00145     typename list< Matrix< Polynomial<K> > >::iterator it;
00146     Matrix< Polynomial<K> > M, temp;
00147     
00148     //the following is a matrix multiplication really, 
00149     //except that one of the matrices presents itself 
00150     //as a list of lines
00151     M= (*coeffs.begin()) * coords[0];
00152 
00153     for(it= coeffs.begin(), it++, i=1; i< coords.size(); it++, i++){
00154       M += *it * coords[i];
00155     }
00156 
00157     coeffs.push_back(M);
00158     generators.push_back(mP);
00159   }
00160 
00162   long simplify(){
00163     long n= coeffs.begin()->ncols();
00164     typename list< multiPolynomial<K> >::iterator it, itprime, gen_begin;
00165     typename list< Matrix< Polynomial<K> > >::iterator itcoeff, c_begin;
00166     long ans= 0;
00167 
00168     gen_begin= generators.begin();
00169     c_begin= coeffs.begin();
00170     while(n > 0){
00171       gen_begin++;
00172       c_begin++;
00173       n--;
00174     }
00175     //good -- we have moved gen_begin and c_begin
00176     //to the beginning of the generators added by
00177     //grobnerize_with_coefficients. The first generators
00178     //we prefer to keep.
00179     for(it= gen_begin, itcoeff= c_begin;
00180         it!= generators.end();){
00181 
00182       for(itprime= generators.begin();
00183           itprime!= generators.end();
00184           itprime++)
00185         if( (itprime != it) && itprime->lm().divides( it->lm() ) )
00186           break;
00187       
00188       if( itprime != generators.end() ){ // found one ?
00189         it= generators.erase( it );
00190         itcoeff= coeffs.erase( itcoeff );
00191         ans++;
00192       }
00193       else{
00194         it++;
00195         itcoeff++;
00196       }
00197     }//for it
00198     return ans;
00199   }//simplfy
00200 
00201 
00202 
00203 
00204 public:
00206   list< multiPolynomial<K> > generators;
00207 
00208 
00209 
00210 
00211 
00213 
00224   void grobnerize_with_coefficients(Matrix< Polynomial<K> >& M){
00225     list< pair< multiPolynomial<K>*, multiPolynomial<K>* > > couples;
00226     pair< multiPolynomial<K>*, multiPolynomial<K>* > fg;
00227     pair< Polynomial<K>, Polynomial<K> > S_coeffs;
00228     multiPolynomial<K> Spoly, h;
00229     Polynomial<K> I;
00230     typename list< multiPolynomial<K> >::iterator it, itprime;
00231     Matrix< Polynomial<K> > U, tuple;
00232     //n= nb of original generators, 
00233     //m= nb of generators added
00234     long i, j, n, m;
00235     long S_count= 0;
00236     
00237 
00238 
00239     if(generators.begin() == generators.end())
00240       return;
00241     //I= one
00242     I= Polynomial<K>( PowProd(0) );
00243     I.alphabet= generators.begin()->coords[0].alphabet;
00244     
00245     //write the beginning of the matrix, as a list of 1-line
00246     //matrices. It starts with the identity.
00247 
00248     n= 0;
00249     tuple.resize(1, generators.size() );
00250     for(i=0; i< (long) generators.size(); i++){
00251       tuple[i].sets_to_zero();
00252       tuple[i].alphabet= I.alphabet;
00253     }
00254     for(it= generators.begin(); it!= generators.end(); it++){
00255       tuple[n]= I;
00256       if(n>0)
00257         tuple[n-1].sets_to_zero();
00258       n++;      
00259       coeffs.push_back( tuple );
00260     }
00261     //n is now set; set m to zero
00262     m= 0;
00263     // populates the stack with the addresses of all pairs
00264     // of polynomials from the list
00265     
00266     for(it= generators.begin(); it !=generators.end(); it++)
00267       for(itprime= it, itprime++; itprime != generators.end(); itprime++)
00268         couples.push_back(   make_pair( &(*it) , &(*itprime) )     );
00269     
00270     
00271     while( !couples.empty() ){
00272       S_count++;
00273       
00274       // we pick the couples alternatively from the beginning 
00275       // and the end of the list -- this in order to avoid
00276       // the worst-case scenario when one of the two choices
00277       // gives rise to an exponentially growing computation.
00278       // On one example this has reduced a computation time
00279       // from 15 minutes to 5 seconds.
00280 
00281       if(S_count % 2 == 0){
00282         fg= couples.front(); // take (f,g) from the stack
00283         couples.pop_front();
00284       }
00285       else{
00286         fg= couples.back();
00287         couples.pop_back();
00288       }
00289 
00290 
00291       Spoly= S_polynomial_with_coefficients( *fg.first , *fg.second, S_coeffs ); 
00292       //computes S(f,g)
00293       
00294 
00295       if( S_count % 1000 == 0 )
00296         cout << S_count << " S polynomials computed, " 
00297              << 100*(S_count)*2/((n+m)*(n+m)) 
00298              << "% done"  << endl;
00299       
00300       h= division_remainder_with_coefficients(Spoly, generators, U); 
00301       //S(f,g) -> h by F, so S(f,g)=h + sum U[i]F[i]
00302       //so h = S(f,g) - sum U[i]*F[i], hence we now multiply by -1:
00303       U*= I*(-1);
00304 
00305       
00306       if( !h.is_zero() ){
00307         
00308         //build (coords of h)
00309         //set i and j...
00310         for(i=0, it=generators.begin(); it!= generators.end(); i++, it++)
00311           if( &(*it) == fg.first )
00312             break;
00313         for(j=0, it=generators.begin(); it!= generators.end(); j++, it++)
00314           if( &(*it) == fg.second )
00315             break;
00316         U[i]+= S_coeffs.first;
00317         U[j]+= S_coeffs.second;
00318         //add it
00319         //generators.push_back(h); //old !
00320         insert(h, U); 
00321         //add one to m
00322         m++;
00323 
00324         //updates the stack of couples
00325         itprime= generators.end();
00326         itprime--; //itprime points at the last element, ie h
00327         for(it= generators.begin(); it != itprime; it++)
00328           couples.push_back(  make_pair(  &(*it), &(*itprime)  )  )  ;
00329         
00330       }
00331       
00332     }// end of while loop
00333     
00334     cout << m << " polynomials added" << endl;  
00335 
00336     cout << simplify() << " removed" << endl;
00337 
00338     M.get_data_from_matrix_list(coeffs);
00339     coeffs.clear();
00340 //     if( m==0 ) { //nothing added?
00341 //       M.get_data_from_matrix_list(coeffs);
00342 //       return;
00343 //     }
00344 //     //else M would not be square
00345 //     coeffs.begin()->resize(1,n+m); //this remedies it!
00346 //     //M will be square of size n + m now:
00347 //     M.get_data_from_matrix_list( coeffs );
00348 //     //now compute M**m, it will have m columns of 0
00349 //     //on the right
00350 //     Matrix< Polynomial<K> > N;
00351 //     N= M;
00352 //     i=m-1;
00353 //     while(i>0){
00354 //       M*= N;
00355 //       i--;
00356 //     }
00357 //     //get rid of the columns of 0
00358 //     M.resize(n+m, n);
00359 //     //tada !!
00360   }
00361   
00363 
00376   void syzygy(Matrix< Polynomial<K> >& M) const {
00377     typename list< multiPolynomial<K> >::const_iterator it, itprime;
00378     list< Matrix< Polynomial<K> > > answer;
00379     Matrix< Polynomial<K> > tuple;
00380     pair< Polynomial<K>, Polynomial<K> > S_coeffs;
00381     multiPolynomial<K> S;
00382     long i, j;
00383 
00384     for(it= generators.begin(), i=0; it!=generators.end(); it++, i++)
00385       for(itprime= it, itprime++, j=i+1; 
00386           itprime!= generators.end(); 
00387           itprime++, j++){
00388         S= S_polynomial_with_coefficients(*it, *itprime, S_coeffs);
00389         division_remainder_with_coefficients(S, generators, tuple);
00390         tuple[i] += S_coeffs.first * (-1);
00391         tuple[j] += S_coeffs.second * (-1);
00392         answer.push_back(tuple);
00393       }
00394 
00395     M.get_data_from_matrix_list(answer);
00396   }
00399   //   everything below is commented out -- a bunch of methods
00400   // from the Ideal class which I may or may not adapt to the
00401   // multiIdeal case.
00404   
00405 
00406 //   /// turns a minimal grobner basis into a reduced + minimal grobner basis
00407 //   void reduce(){
00408 //     typename list< Polynomial<K> >::iterator it;
00409 //     Polynomial<K> f;
00410     
00411 //     it= generators.begin();
00412 //     while( it != generators.end() ){
00413 //       f= *it;
00414 //       it= generators.erase(it);
00415 //       f= division_remainder(f,generators);
00416 //       generators.push_front(f);
00417 //     }//end of while
00418 //   }
00419 //   /// checks if a variable shows up among the ideal generators
00420 //   bool variable_shows_up(long i) const {
00421 //     typename list< Polynomial<K> >::const_iterator it;
00422 
00423 //     for(it= generators.begin(); it!= generators.end(); it++)
00424 //       if( it->involves_variable(i) )
00425 //      return true;
00426 
00427 //     return false;
00428 //   }
00429 
00430 
00431 //   friend ostream& operator<<(ostream& os, const Ideal<K>& J){
00432 //     typename list< Polynomial<K> >::const_iterator it;
00433 
00434 //     for(it= J.generators.begin(); it != J.generators.end(); it++)
00435 //       os << *it << endl;
00436 //     return os;
00437 //   }
00438 
00439 
00440 };
00441 
00442 #endif

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