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

derive.cpp

00001 #include "derive.H"
00002 using namespace std;
00003 
00004 
00005 void DerivationAnalyzer::setup(GradedAlgebra<F_2> *thesource){
00006   long i, n;
00007   list< Polynomial<F_2> > pols, total;
00008   list< Polynomial<F_2> >::iterator it;
00009 
00010   source= thesource;
00011 
00012   n= 1;
00013   //write the generators for *source as a module
00014   //over the subalgebra of squares
00015   for(i=1; i<= source->variables_in_use(); i++){
00016     write_gens( pols, i, 1, source->variables_in_use() );
00017     for(it= pols.begin(); it!= pols.end(); it++, n++)
00018       index_of[ it->lp() ]= n; 
00019     total.splice( total.end(), pols);
00020   }
00021   //turns the list into a tuple
00022   mod_gens.resize(n);
00023   mod_gens[0]= source->one();
00024   for(i= 1, it= total.begin(); i< n; i++, it++)
00025     mod_gens[i]= *it;
00026 
00027   d.resize(n);
00028   d[0].resize(n);
00029   d[0].set_alphabet( source );
00030   d[0].sets_to_zero();
00031 
00032   cout << "generators: " << mod_gens << endl;
00033   //now construct the subalgebra of squares
00034   //together with the inclusion homomorphism
00035   Tuple< Polynomial<F_2> > x= source->get_variables();
00036   sq_inclusion.source= &squares;
00037   sq_inclusion.target= source;
00038   cs_inclusion.source= &constants;
00039   cs_inclusion.target= source;
00040   for(i=1; i<= source->variables_in_use(); i++){
00041     squares.new_variable("s" + source->nameof(i), 
00042                          2*source->hom_degrees[i] );
00043     constants.new_variable("s" + source->nameof(i),
00044                            2*source->hom_degrees[i] );
00045     sq_inclusion.set_image(i, x[i]*x[i] );
00046     cs_inclusion.set_image(i, x[i]*x[i] );
00047   }
00048 
00049   cs_inclusion.populate_associated_algebra();
00050 
00051   //  cout << squares << endl;
00052   //cout << sq_inclusion << endl;
00053 
00054 }
00055 
00056 void DerivationAnalyzer::write_gens(list< Polynomial<F_2> >& result, 
00057                 long ext, long first, long last) {
00058   list< Polynomial<F_2> > temp1, temp2;
00059   list< Polynomial<F_2> >::iterator it;
00060 
00061 
00062   // trivial cases: ext too small or too large
00063   if( (ext < 1) ){
00064     result.clear();
00065     result.push_front( source->one() );
00066     return;
00067   }
00068   
00069   if( (ext > last - first + 1) ){
00070     result.clear();
00071     return;
00072   }
00073     
00074   // else...
00075   // use recursion:
00076   write_gens(result, ext, first + 1, last);
00077   write_gens(temp2, ext - 1, first + 1, last);
00078   // now add the 'first' variable to the terms
00079   // in temp2
00080   for(it= temp2.begin(); it != temp2.end(); it++)
00081     result.push_back( *it * Polynomial<F_2>(PowProd( first )) );
00082   return;
00083 
00084 }
00085 
00086 multiPolynomial<F_2> DerivationAnalyzer::coords_of(PowProd P)
00087 
00088 {
00089   PowProd tail(0);
00090   PowProd half;
00091   long i;
00092   multiPolynomial<F_2> ans;
00093   Polynomial<F_2> poly;
00094 
00095   for(i= 1; i<= P.nvars(); i++)
00096     if( P.power_of(i) % 2 != 0 )        // odd ?
00097       tail*= PowProd(i);
00098 
00099   P /= tail;
00100   half.powers.resize( P.powers.size() );
00101   for(i=0; i< P.powers.size(); i++)
00102     half.powers[i]= P.powers[i] / 2;
00103 
00104 
00105 
00106   //now simply format the answer
00107   ans.resize( mod_gens.size() );
00108   ans.set_alphabet( &squares );
00109   poly= Polynomial<F_2>( half );
00110   poly.alphabet= &squares;
00111   ans[ index_of[tail] ]= poly;
00112   return ans;
00113 }
00114 
00115 multiPolynomial<F_2> DerivationAnalyzer::coords_of(const Polynomial<F_2>& P) {
00116   map< PowProd, F_2 >::const_iterator it;
00117   multiPolynomial<F_2> ans;
00118 
00119   ans.resize( mod_gens.size() );
00120   ans.set_alphabet( &squares );
00121 
00122   for(it= P.coeffs.begin();
00123       it != P.coeffs.end();
00124       it++)
00125     ans+= this->coords_of( it->first );
00126   
00127   return ans;
00128 }
00129 
00130 void DerivationAnalyzer::constant_subalgebra(string prefix, 
00131                                              long offset){
00132   multiIdeal<F_2> module;
00133   long i, j;
00134   Matrix< Polynomial<F_2> > M, T;
00135   Polynomial<F_2> P, Q, replacement;
00136   list< Polynomial<F_2> >::iterator it;
00137   list< Polynomial<F_2> > solutions;
00138   list< Polynomial<F_2> > homo_solutions;
00139   ostringstream autoname;
00140 
00141   //add the d(generators) to the multiIdeal
00142   for(i=1; i< d.size(); i++) {
00143     module.generators.push_back( d[i] );
00144     //the syzygy methods below have an oddity:
00145     //they do not treat 0 elements well, in fact
00146     //they are ignored (or things amount to this).
00147     //we need to add manually the corresponding
00148     //solutions:
00149     if( d[i].is_zero() ) {
00150       solutions.push_back( mod_gens[i] );
00151     }
00152     //also note that d[0]= 0, but one() is
00153     //automatically part of the algebra of
00154     //solutions
00155   }
00156   //done, now add the relations of *source
00157   
00158   for(it= source->relations.generators.begin();
00159       it != source->relations.generators.end();
00160       it++)
00161     for(i= 0; i< mod_gens.size(); i++){
00162       module.generators.push_back( this->coords_of(mod_gens[i]*(*it) ) );
00163     }
00164 
00165   cout << "computing the kernel of the derivation..." << endl;
00166 
00167   //  module.grobnerize();
00168   //cout << "done !" << endl;
00169   
00170   module.grobnerize_with_coefficients(T);
00171 
00172   cout << "for information: T has "
00173        << T.nlines() << " lines " << endl;
00174 
00175   module.syzygy(M);
00176   cout << "performing large matrix multiplication... (" 
00177        << M.nlines() << " lines)" << endl;
00178   M*= T;
00179   //now resize M to keep the first columns
00180   M.resize( M.nlines(), mod_gens.size()-1 );
00181 
00182 
00183   //now forming the algebra of constants
00184   cout << "finding a minimal presentation" << endl;
00185 
00186   Q.alphabet= source;
00187   
00188 
00189   cout << "nb of generators: " << M.nlines() << endl;
00190 
00191   for(i=0; i< M.nlines(); i++){
00192     
00193     Q.sets_to_zero();
00194     for(j=1; j < mod_gens.size(); j++)
00195       Q+= sq_inclusion.of(M(i, j-1)) * mod_gens[j];
00196     //Q is computed, now reduce it
00197     Q= source->reduced_form(Q);
00198     solutions.push_back(Q);
00199   }
00200 
00201   //split_and_sort_relations...
00202   i= 0;
00203 
00204   while( !solutions.empty() ) {
00205     i++;
00206 
00207     for(it= solutions.begin();
00208         it!= solutions.end();) {
00209       Q= source->hom_part_of( *it, i);
00210       if( !Q.is_zero() ) {
00211         homo_solutions.push_back( Q );
00212         *it += Q;
00213         //cout << "  added " << Q << endl;
00214       }      
00215       if( it->is_zero() )
00216         it= solutions.erase( it );
00217       else
00218         it++;
00219     }
00220 
00221   }
00222 
00223   i= 0;
00224 
00225   for( it= homo_solutions.begin();
00226        it != homo_solutions.end();
00227        it++) {
00228 
00229     if( !cs_inclusion.maps_onto(*it) ){
00230         
00231       cout << "adding " << *it << endl;
00232     
00233       //we need to find a name for the variable
00234       autoname.str("");
00235       i++;
00236       autoname << prefix << "_" << offset + i;
00237       constants.new_variable( autoname.str(),
00238                               source->hom_degree_of(*it) );
00239       cs_inclusion.set_image( constants.variables_in_use(), *it);
00240       cs_inclusion.populate_associated_algebra();
00241     }
00242       
00243   }
00244  
00245   constants.relations= cs_inclusion.kernel;
00246   //cout << constants << endl << cs_inclusion << endl;
00247 
00248   
00249 
00250 }
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 // MilnorAnalyzer code /////////////////////////
00275 
00276 void MilnorAnalyzer::start(UnstableAlgebra *theA) {
00277   long i, k;
00278   Polynomial<F_2> P, R;
00279   char letter= 'a';
00280   ostringstream autoname;
00281   Tuple< Polynomial<F_2> > x;
00282 
00283   A= theA;
00284 
00285   //the first thing to do is compute the kernel
00286   //of Sq^1, which is different from the other
00287   //derivations for technical reasons.
00288   cout << "dealing with Sq^1" << endl;
00289   k= 0;
00290   //get things ready; in particular this
00291   //makes a copy of A into *source, and
00292   //'inclusion' is from *source to A
00293   setup_for_Sq1();
00294   //now compute the kernel
00295   autoname << letter;
00296   constant_subalgebra(autoname.str(), 0);
00297   //'inclusion' must be from 'constants' to A,
00298   // both as the final answer and within done():
00299   inclusion *= cs_inclusion;
00300   inclusion.populate_associated_algebra();
00301 
00302   //now the higher milnor derivations
00303 
00304   while( !done() ) {
00305     k++;
00306     letter++;
00307     cout << endl 
00308          << "dealing with Q_" << k << "..." << endl;
00309     //the following swaps things around:
00310     //constants is copied to *source(== alg),
00311     //squares is updated... also, 'inclusion'
00312     //is again from *source to A :
00313     re_setup(k);
00314     //now compute the kernel    
00315     autoname.str("");
00316     autoname << letter;
00317     constant_subalgebra(autoname.str(), 0);
00318     inclusion *= cs_inclusion;
00319     inclusion.populate_associated_algebra();
00320   }
00321 
00322   cout << "wooooot !! done !!" << endl;
00323 
00324 }
00325 
00326 
00327 void MilnorAnalyzer::setup_for_Sq1(){
00328   long i, n;
00329   list< Polynomial<F_2> > pols, total;
00330   list< Polynomial<F_2> >::iterator it;
00331   Tuple< Polynomial<F_2> > x;
00332   Polynomial<F_2> P, R;
00333   
00334   //first we make a copy of *source
00335   //and we setup 'inclusion' to be the inclusion
00336   //of this copy into *A
00337   x= A->get_variables();
00338   inclusion.source= &alg;
00339   inclusion.target= A;
00340   for(i=1; i<= A->variables_in_use(); i++) {
00341     alg.new_variable(A->nameof(i),
00342                      A->hom_degrees[i]);
00343     inclusion.set_image(i, x[i]); 
00344   }
00345   alg.relations= A->relations;
00346   alg.fix_alphabets();
00347   //or, we could have done something like
00348   //alg= (cast) A;
00349   //and inclusion.make_identity() or
00350   //whatever (there would be details anyway)
00351   source= &alg;//done
00352   //note that A still points at the original
00353   //unstable algebra
00354   //now see what variables in *source satisfy
00355   //sq^1 = 0, and put them at the beginning
00356   n_cs_vars= 0;
00357   for(i=1; i<= source->variables_in_use(); i++) {
00358     P= A->Sq(1, x[i]);
00359     if( A->reduced_form(P).is_zero() ) {
00360       n_cs_vars++;
00361       alg.swap_variables_order(i, n_cs_vars);
00362       inclusion.swap(i, n_cs_vars);
00363     }
00364   }//the following will be useful:
00365   inclusion.populate_associated_algebra();
00366   //ok, done
00367   //now add to squares and constants 
00368   //the variables for which sq^1=0 and
00369   //the squares of the others
00370   x= source->get_variables();
00371   sq_inclusion.source= &squares;
00372   sq_inclusion.target= source;
00373   cs_inclusion.source= &constants;
00374   cs_inclusion.target= source;
00375   for(i=1; i<= n_cs_vars; i++) { //those with sq1=0
00376     squares.new_variable(source->nameof(i), 
00377                          source->hom_degrees[i] );
00378     constants.new_variable(source->nameof(i),
00379                            source->hom_degrees[i] );
00380     sq_inclusion.set_image(i, x[i] );
00381     cs_inclusion.set_image(i, x[i] );
00382 
00383   }//now the others:
00384   for(i= n_cs_vars+1; i<=source->variables_in_use(); i++){
00385       squares.new_variable("s" + source->nameof(i), 
00386                            2*source->hom_degrees[i] );
00387       constants.new_variable("s" + source->nameof(i),
00388                              2*source->hom_degrees[i] );
00389       sq_inclusion.set_image(i, x[i]*x[i] );
00390       cs_inclusion.set_image(i, x[i]*x[i] );
00391   }
00392   //cs_inclusion is supposed to have its associated
00393   //algebra already computed:
00394   cs_inclusion.populate_associated_algebra();
00395   //now we setup newvar_squared: for sq1 the name
00396   //'newvar' is not appropriate, btw! in this context
00397   //the "new" variables are those with sq1 != 0.
00398   //the purpose of newvar_squared, anyway, remains
00399   //to express the square of variable i in terms
00400   //of elements in the algebra 'squares': here for
00401   //sq1 it is just the identity, by definition.
00402   newvar_squared.clear();
00403   x= squares.get_variables();
00404   for(i= n_cs_vars+1; i<= squares.variables_in_use(); i++)
00405     newvar_squared.set_image(i, x[i]);
00406   //good, now write the generators for *source as a module
00407   //over the subalgebra of squares
00408   n= 1;
00409   for(i=1;
00410       i<= source->variables_in_use() - n_cs_vars; 
00411       i++){
00412     write_gens( pols, i, n_cs_vars+1, 
00413                 source->variables_in_use() );
00414     for(it= pols.begin(); it!= pols.end(); it++, n++)
00415       index_of[ it->lp() ]= n; 
00416     total.splice( total.end(), pols);
00417   }
00418   //turns the list into a tuple
00419   mod_gens.resize(n);
00420   mod_gens[0]= source->one();
00421   for(i= 1, it= total.begin(); i< n; i++, it++)
00422     mod_gens[i]= *it;
00423   cout << "initial generators: " << mod_gens << endl;
00424   //finally set d= Sq^1
00425   d.resize(n);
00426   d[0].resize(n);
00427   d[0].set_alphabet( source );
00428   d[0].sets_to_zero();
00429   for(i=1; i< mod_gens.size(); i++) {
00430     P= A->Sq(1, inclusion.of(mod_gens[i]));
00431     inclusion.maps_onto(P, R);
00432     //this has worked since
00433     //inclusion.populate_associated_algebra()
00434     //has been called
00435     d[i]= this->coords_of(R);
00436   }
00437   //that's all !
00438 
00439 
00440 }
00441 
00442 
00443 //get ready for Q_k
00444 void MilnorAnalyzer::re_setup(long k) {
00445   long i;
00446   Tuple< Polynomial<F_2> > x;
00447   Polynomial<F_2> P, R;
00448   GradedAlgebra<F_2> empty;
00449 
00450 
00451   //first thing first: see what variables in
00452   // 'constants' satisfy Q_k(var)==0 and move
00453   //them to the beginning
00454   n_cs_vars= 0;
00455 
00456   for(i= n_cs_vars + 1; 
00457       i <= constants.variables_in_use(); i++){
00458     P= A->Q(k, inclusion.of_generator(i) );
00459     if( A->reduced_form(P).is_zero() ) {
00460       // cout << "simplifying!! works ?????" 
00461       //           << " P= " << P << " k= " << k
00462       //           << endl;
00463       n_cs_vars++;
00464       constants.swap_variables_order(i, n_cs_vars); 
00465       cs_inclusion.swap(i, n_cs_vars);
00466       inclusion.swap(i, n_cs_vars);
00467     }
00468   }
00469   //swapping the variables unfortunately
00470   //destroys the grobner basis in the algebra
00471   //associated to cs_inclusion. It is unavoidable...
00472   cs_inclusion.populate_associated_algebra(); //see (*)
00473   inclusion.populate_associated_algebra();    //see (**)
00474 
00475   //good now add them to 'squares'
00476   squares= empty;
00477   for(i= 1; i <= n_cs_vars; i++) 
00478     squares.new_variable( constants.nameof(i),
00479                           constants.hom_degrees[i] );
00480   cout << "n_cs_vars= " << n_cs_vars << endl;
00481   cout << "new algebra of squares: "
00482        << squares << endl;
00483 
00484   //now we populate newvar_squared.
00485   newvar_squared.clear();
00486   x= constants.get_variables();
00487 
00488   for(i= squares.variables_in_use() + 1;
00489       i <= constants.variables_in_use();
00490       i++) {
00491 
00492     P= cs_inclusion.of( x[i]*x[i] );
00493     cs_inclusion.maps_onto(P, R); // (*)
00494     //now R maps onto P but it is reduced
00495     //in the associated algebra to cs_inclusion
00496     //and therefore it is really in the image of
00497     //squares inside constants
00498     R.alphabet= &squares;
00499     newvar_squared.set_image(i, R);
00500   }
00501   //constants becomes the main algebra
00502   alg= constants;
00503   alg.fix_alphabets();
00504   source= &alg;
00505   //temporarily, we view 'inclusion' as
00506   //defined on *source:
00507   inclusion.source= source;
00508   //the subalgebra of squares is a subalgebra
00509   //of the newly created alg
00510   sq_inclusion.target= source;
00511   sq_inclusion.clear();
00512   x= source->get_variables();
00513 
00514   for(i=1; i<= squares.variables_in_use(); i++)
00515     sq_inclusion.set_image(i, x[i]);
00516   
00517   //set the constants= the squares, for the moment
00518   constants= squares;
00519   constants.fix_alphabets();
00520   cs_inclusion= sq_inclusion;
00521   cs_inclusion.source= &constants;
00522   cs_inclusion.fix_alphabets();
00523   cs_inclusion.populate_associated_algebra(); //again...
00524   // all the swapping around is done !!
00525   //now rewrite the generators
00526   index_of.clear();
00527   mod_gens.resize(0);
00528 
00529   long n;
00530   list< Polynomial<F_2> > pols, total;
00531   list< Polynomial<F_2> >::iterator it;
00532 
00533   n= 1;
00534   //write the generators for *source as a module
00535   //over the subalgebra of squares
00536   for(i=1;
00537       i<= source->variables_in_use() - n_cs_vars; 
00538       i++){
00539     write_gens( pols, i, n_cs_vars + 1, source->variables_in_use() );
00540     for(it= pols.begin(); it!= pols.end(); it++, n++)
00541       index_of[ it->lp() ]= n; 
00542     total.splice( total.end(), pols);
00543   }
00544   //turns the list into a tuple
00545   mod_gens.resize(n);
00546   mod_gens[0]= source->one();
00547   for(i= 1, it= total.begin(); i< n; i++, it++)
00548     mod_gens[i]= *it;
00549 
00550   cout << "generators: " << mod_gens << endl;
00551   //finally setup d=Q_k:
00552   d.resize(n);
00553   d[0].resize(n);
00554   d[0].set_alphabet( source );
00555   d[0].sets_to_zero();
00556   for(i=1; i< mod_gens.size(); i++) {
00557     P= A->Q(k, inclusion.of( mod_gens[i] ));
00558     inclusion.maps_onto(P, R); // (**)
00559     d[i]= this->coords_of(R);
00560   }
00561   //that's all !
00562 }
00563 
00564 
00565 
00566 multiPolynomial<F_2> MilnorAnalyzer::coords_of(PowProd P) {
00567   PowProd tail(0);
00568   PowProd half, begin;
00569   long i;
00570   multiPolynomial<F_2> ans;
00571   Polynomial<F_2> poly;
00572 
00573 
00574   begin= P;
00575 
00576   if( P.nvars() > n_cs_vars ) { // P involves 'new' variables ?
00577 
00578     for(i= n_cs_vars - 1; i >= 0; i--)
00579       if( begin.powers[i] != 0 )
00580         break;
00581     begin.powers.resize(i+1);
00582     
00583   }
00584 
00585 
00586   P/= begin;
00587 
00588  
00589   
00590   for(i= 1; i<= P.nvars(); i++)
00591     if( P.power_of(i) % 2 != 0 )        // odd ?
00592       tail*= PowProd(i);
00593   
00594  
00595   P /= tail;
00596 
00597   half.powers.resize( P.powers.size() );
00598   for(i=0; i< P.powers.size(); i++)
00599     half.powers[i]= P.powers[i] / 2;
00600 
00601   poly= newvar_squared.of( Polynomial<F_2>(half) );
00602   poly*= Polynomial<F_2>( begin );
00603   
00604   //  half*= begin;
00605 
00606   //now simply format the answer
00607   ans.resize( mod_gens.size() );
00608   ans.set_alphabet( &squares );
00609 
00610   poly.alphabet= &squares;
00611   ans[ index_of[tail] ]= poly;
00612   return ans;
00613 }
00614 
00615 multiPolynomial<F_2> MilnorAnalyzer::coords_of(const Polynomial<F_2>& P) {
00616 
00617   return DerivationAnalyzer::coords_of(P);
00618 }
00619 
00620 bool MilnorAnalyzer::done() {
00621   
00622   constants.even_subalgebra(ans, ans_inclusion);
00623   ans_inclusion= inclusion * ans_inclusion;
00624   ans_inclusion.populate_associated_algebra();
00625 
00626   if( A->has_closure_of( ans_inclusion ) ) {
00627       ans.relations= ans_inclusion.kernel;
00628       return true;
00629     }
00630   else
00631     return false;
00632 }
00633 

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