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
00013
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()){
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
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()){
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
00151
00152 it= P.begin();
00153 G.splice(G.end(), P);
00154 h= division_remainder(h, G);
00155 P.splice(P.begin(), G, it, G.end() );
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 }
00192
00193 }
00194
00195
00196 }
00197
00198
00199
00200
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);
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
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 );
00280 h= division_remainder(Spoly, 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 }
00300 }
00301
00302
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
00341 I= Polynomial<K>( PowProd(0) );
00342 I.alphabet= generators.begin()->alphabet;
00343
00344
00345
00346
00347
00348
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
00359
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();
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
00376 h= division_remainder_with_coefficients(Spoly, generators, U);
00377
00378
00379 }
00380
00381 if( !h.is_zero() ){
00382
00383 generators.push_back(h);
00384
00385 itprime= generators.end();
00386 itprime--;
00387 for(it= generators.begin(); it != itprime; it++)
00388 couples.push( make_pair( &(*it), &(*itprime) ) ) ;
00389
00390
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 }
00404
00405
00406 if( m==0 ) {
00407 M.get_data_from_tuple_list(coeffs);
00408 M*= I*(-1);
00409 return;
00410 }
00411
00412 coeffs.begin()->resize(n+m);
00413
00414 M.get_data_from_tuple_list( coeffs );
00415 M*= I*(-1);
00416
00417
00418 Matrix< Polynomial<K> > N;
00419 N= M;
00420 i=m-1;
00421 while(i>0){
00422 M*= N;
00423 i--;
00424 }
00425
00426 M.resize(n+m, n);
00427
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 }
00489
00490 }
00491 }
00492
00493 for(it= generators.begin(); it!= generators.end(); it++){
00494 c= it->lc();
00495 c= 1/c;
00496 *it *= c;
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 }
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