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

homfinder.cpp

00001 #include "homfinder.H"
00002 using namespace std;
00003 
00004 HomFinder::HomFinder(){
00005 }
00006 
00007 HomFinder::HomFinder(GradedAlgebra<F_2> *thesource, GradedAlgebra<F_2> *thetarget){
00008   source= thesource;
00009   target= thetarget;
00010 }
00011 
00013 void HomFinder::read_solutions_from(ifstream& file)
00014 {
00015   long n;
00016   AffineHomomorphism<F_2> phi(source, target);
00017   
00018   solutions.clear();
00019   file >> n;
00020   //  cout << n << " homomorphisms to read" << endl;
00021   solution_count= n;
00022   
00023   while(n>0){
00024     file >> phi;
00025     solutions.push_back(phi);
00026     n--;
00027   }
00028   
00029 } 
00030 
00031 
00032 
00034 void HomFinder::write_solutions_to(ofstream& file)
00035 {
00036   list< AffineHomomorphism<F_2> >::const_iterator ith;
00037   AffineHomomorphism<F_2> phi(source, target);
00038   
00039   file << solution_count << " ";
00040   
00041   for(ith= solutions.begin();
00042       ith!= solutions.end();
00043       ith++){
00044     phi= *ith;
00045     file << phi;
00046   }
00047 }
00048 
00049 
00050 ZZ HomFinder::populate_GL(long n){
00051   ZZ total, browse, bit, count;
00052   long i;
00053   Matrix<F_2> M(n, n);
00054   
00055   GL.clear();
00056   count= 0;
00057   
00058   // set total= 2^(n*n)
00059   total= 1;
00060   for(i=1; i <= n*n; i++)
00061     total*= 2;
00062 
00063   for(browse= 0; browse < total; browse++){
00064 
00065     bit= 1;
00066     for(i=0; i< n*n; i++){
00067       if( (browse & bit) != 0 )
00068         M[i]=1;
00069       else
00070         M[i]=0;
00071       bit *= 2;
00072     }
00073 
00074     if(M.is_invertible()){
00075       count++;  
00076       GL.push_back(M);
00077     }
00078 
00079   }
00080 
00081   //  cout << count << " matrices to consider" << endl;
00082   return count;
00083 }
00084 
00085 ZZ HomFinder::filter_GL()
00086 {
00087   list< Matrix<F_2> >::iterator M, N;
00088   Matrix<F_2> mat;
00089   ZZ count=0;
00090   AffineHomomorphism<F_2> phi(&basic_source, target);
00091   
00092 
00093   for(M= GL.begin(); M!= GL.end();){
00094     
00095     set_hom_from_matrix(phi, basic_variables, *M);
00096 
00097     if(phi.is_well_defined()){
00098       M++;
00099       count++;
00100     }
00101     else
00102       M= GL.erase(M);
00103     
00104   }// matrix M
00105 
00106   //now perform the second reduction
00107   long m=1;
00108   
00109    for(M= GL.begin(); M!= GL.end(); m++, M++)
00110      for(N=M, N++; N!=GL.end();){
00111        mat= *N * M->inverse();
00112        phi.make_identity(target);
00113        set_hom_from_matrix(phi, target_basic_variables, mat);
00114        if( phi.is_well_defined() ){
00115 //       cout << "wooooooot ! killing a matrix !" << endl;
00116 //       cout << "automorphism was: " << phi << endl;
00117          //cout << "it was a clone of matrix # " << m << endl;
00118          N= GL.erase(N);
00119          count--;
00120        }
00121        else
00122          N++;
00123      } 
00124    if(verbose)
00125      cout << "*** Step 1:" << endl
00126           << count << " possible choices, after reduction"
00127           << endl;
00128   return count;
00129 }
00130 
00131 
00132 
00133 void HomFinder::init(){
00134   long n=0;
00135   long d, i;  
00136   Tuple< Polynomial<F_2> > pows;
00137 
00138   
00139   // populate higher_variables, basic_variables,
00140   // monomials, polvars, and compute n
00141   for(i=1; i <= source->variables_in_use(); i++){
00142     d= source->hom_degrees.find(i)->second;
00143     if( d > 1){
00144       higher_variables.push_back(i);
00145       if( !source->relations.variable_shows_up(i) )
00146         polvars.push_back(i);
00147     }
00148     else{
00149       basic_variables.push_back(i);
00150       n++;
00151     }
00152     
00153     if( monomials.count( d ) == 0){
00154       target->list_monomials(d, pows);      
00155       monomials[d]= pows;
00156     }
00157     
00158   }
00159 
00160   //as the name says...
00161   populate_GL(n);
00162   //now the same with target_basic_variables
00163   for(i=1; i <= target->variables_in_use(); i++){
00164     d= target->hom_degrees.find(i)->second;
00165     if( d == 1)
00166       target_basic_variables.push_back(i);
00167   }
00168 
00169 
00170   list< long >::iterator hvar;
00171 
00172   //populates basic_source
00173   basic_source= *source;
00174   basic_source.relations.generators.clear(); 
00175   list< Polynomial<F_2> >::const_iterator it;
00176   bool add;  
00177   for(it= source->relations.generators.begin();
00178       it!= source->relations.generators.end();
00179       it++){
00180     add= true;
00181     for(hvar= higher_variables.begin();
00182         hvar!= higher_variables.end();
00183         hvar++)
00184       if( it->involves_variable(*hvar) ){
00185         add= false;
00186         break;
00187       }
00188     if( add )
00189       basic_source.add_relation( *it );
00190     else
00191       higher_relations.push_back( *it );
00192   }
00193 
00194   // keep only the compatible matrices
00195   filter_GL();
00196   //sort the highest_relation according to their weight
00197   sort();
00198 }
00199 
00200 
00201 
00202 void HomFinder::set_hom_from_matrix(AffineHomomorphism<F_2>& phi,
00203                                     const list< long >& basics,
00204                                     const Matrix<F_2>& M)
00205 {
00206   long n= M.nlines();
00207   long i,j;
00208   list< long >::const_iterator bvars;
00209   Polynomial<F_2> P= target->one();//alphabet...
00210 
00211   for(bvars= basics.begin(), j=0;
00212       bvars!= basics.end();
00213       bvars++, j++){
00214     P.sets_to_zero();
00215     for(i=0; i<n; i++)
00216       if( M(i,j)==1 )
00217         P+= monomials[1][i];
00218     phi.set_image(*bvars, P);
00219   }
00220 }
00221 
00222 
00223 void HomFinder::set_f_from_matrix(const Matrix<F_2>& M){
00224   long n= M.nlines();
00225   long i,j;
00226   list< long >::iterator bvars;
00227   Polynomial<F_2> P= target->one();//alphabet...
00228 
00229   for(bvars= basic_variables.begin(), j=0;
00230       bvars!= basic_variables.end();
00231       bvars++, j++){
00232     P.sets_to_zero();
00233     for(i=0; i<n; i++)
00234       if( M(i,j)==1 )
00235         P+= monomials[1][i];
00236     f.set_image(*bvars, P);
00237   }
00238 }
00239 
00240 
00241 void HomFinder::start(){
00242   list< Matrix<F_2> >::iterator M;
00243   ZZ code;
00244   long m=0;
00245 
00246   f.target= target;
00247   f.source= source;
00248   
00249   solution_count= 0;
00250   
00251 
00252   for(M= GL.begin(); M!= GL.end(); M++){
00253     m++;
00254   
00255     set_f_from_matrix(*M);
00256     
00257     //    cout << f << endl;
00258     
00259     branch(f, higher_relations.begin(), 0);
00260     
00261 
00262 
00263 
00264   }// matrix M
00265 
00266 }//done!
00267 
00268 
00269 void HomFinder::set_f_from_integer(ZZ code){
00270   ZZ bit=1;
00271   list< long >::iterator hvars;
00272   long deg, i;
00273   Polynomial<F_2> P=target->one(); //for the alphabet !
00274 
00275 
00276   for(hvars= higher_variables.begin();
00277       hvars!= higher_variables.end();
00278       hvars++){
00279     P.sets_to_zero();
00280     deg= source->hom_degrees.find( *hvars )->second;
00281     for(i=0; i< monomials[deg].size(); i++){
00282       if( (code & bit) != 0 )
00283         P+= monomials[deg][i];
00284       bit*=2;
00285     }
00286     f.set_image(*hvars, P);
00287   }// for hvars
00288 }
00289 
00290 // receives:  phi: *source -> *target
00291 // a morphism, well-defined so far.
00292 
00293 void HomFinder::branch(const AffineHomomorphism<F_2>& phi,
00294                        list< Polynomial<F_2> >::iterator next,
00295                        long depth){
00296 
00297   list< long > newvars;
00298   long i;
00299   AffineHomomorphism<F_2> local_phi= phi;
00300   string tab;
00301   // a tabulation, for display purposes
00302   for(i=0; i<depth; i++)
00303     tab+="    "; 
00304 
00305 
00306 
00307   if( next == higher_relations.end() ){
00308     //cout << "homomorphism found ! " <<endl;
00309     
00310     solutions.push_back(phi);
00311     solution_count++;
00312     cout << "homomorphism found, total "
00313          << solution_count << endl;
00314            
00315     return;
00316   }
00317   // else, 
00318 
00319   // DEBUGGING PURPOSES
00320   /* char stop;
00321      cout << tab << "depth " << depth << endl
00322      << tab << "next equation: " << *next << endl
00323      << phi;
00324      cin >> stop;
00325   */
00326 
00327 
00328 
00329 
00330 
00331   list< Polynomial<F_2> >::iterator next_next= next;
00332   next_next++;
00333 
00334   //we look at *next and see what variables it involves
00335   for(i=1; i<= source->variables_in_use(); i++)
00336     if( next->involves_variable(i) && !phi.has_image_set(i) )
00337       newvars.push_back(i);
00338  
00339   // compute "possibilities"
00340   list< long >::iterator nv;
00341   ZZ poss;
00342   ZZ dim=0;
00343   long d;
00344   for(nv= newvars.begin();
00345       nv!= newvars.end();
00346       nv++){
00347     d= source->hom_degrees.find(*nv)->second;
00348     dim+= monomials[d].size();
00349   }
00350   // now set possibilities = 2^dim 
00351   poss=1;
00352   
00353   for(i=0; i< dim; i++){
00354     poss*=2;
00355   }
00356 
00357   //now try them all !
00358   ZZ code;
00359   ZZ bit;
00360   long deg;
00361   Polynomial<F_2> P=target->one(); //for the alphabet !
00362 
00363   for(code=0; code < poss; code++){
00364 
00365     bit= 1;
00366 
00367     for(nv= newvars.begin();
00368         nv!= newvars.end();
00369         nv++){
00370       P.sets_to_zero();
00371       deg= source->hom_degrees.find( *nv )->second;
00372       for(i=0; i< monomials[deg].size(); i++){
00373         if( (code & bit) != 0 )
00374           P+= monomials[deg][i];
00375         bit*=2;
00376       }
00377       local_phi.set_image(*nv, P);
00378     }// for nv
00379     // now local_phi is set.
00380     if( target->reduced_form( local_phi.of(*next) ).is_zero() ){
00381       cout << tab << "(depth " << depth
00382            << " code " << code << " out of "
00383            << poss <<") match found" << endl;
00384       
00385       branch(local_phi, next_next, depth + 1);
00386     }
00387   }//for code
00388 
00389   return;
00390 }
00391 
00392 
00393 
00394 
00395 
00396 // void HomFinder::old_define_polynomial_variables()
00397 // {
00398 //   list< AffineHomomorphism<F_2> >::iterator it;
00399 //   list< AffineHomomorphism<F_2> > old_solutions;
00400 //   list< long > polvars;
00401 //   list< long >::iterator itpol;
00402 //   long i, d, kept=0;
00403 //   ZZ dim, poss, code, bit, precise_poss, precise_code, precise_bit;
00404 //   GradedAlgebra<F_2> alg;
00405 //   map< long, Tuple< Polynomial<F_2> > > choices;
00406 //   map< long, Tuple< Polynomial<F_2> > > precise_choices;
00407 //   AffineHomomorphism<F_2> hom;
00408 //   Tuple< Polynomial<F_2> > pows;
00409 //   Polynomial<F_2> P= target->one(), Q;
00410   
00411 //   //first we copy the solutions
00412 //   old_solutions.clear();
00413 //   old_solutions.splice( old_solutions.begin(), solutions );
00414 //   //we look for the polynomial variables
00415 //   polvars.clear();
00416 //   it= old_solutions.begin();
00417 
00418 //   for(i=1; i<= source->variables_in_use(); i++)
00419 //     if( !it->has_image_set(i) )
00420 //       polvars.push_back(i);
00421 //   //ok now we compute the possible values
00422 //   precise_choices.clear();
00423 //   dim= 0;
00424   
00425 //   for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00426       
00427 //       d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00428 //       if( precise_choices.count( d ) == 0 ){
00429 //      target->list_monomials(d, pows);      
00430 //      precise_choices[d]= pows;
00431 //       }
00432 //       dim+= precise_choices[d].size();
00433 //   }
00434 //   //set poss= 2**dim
00435 //   precise_poss= 1;
00436 //   while( dim > 0){
00437 //     precise_poss*= 2;
00438 //     dim--;
00439 //   }
00440    
00441 //   cout << "total possibilities: " << precise_poss << endl;
00442 
00443 //   //ok! now we go through the solutions one by one and
00444 //   //see each time what possibilities we have for the values
00445 //   //of the polynomial variables *up to the ideal image* of
00446 //   //the other variables. Much fewer possibilities to check;
00447 //   //and when we find one that works, we check *all* possibilities.
00448  
00449 //   for(it= old_solutions.begin();
00450 //       it!= old_solutions.end();
00451 //       it++){
00452 
00453 //     hom= *it;
00454 
00455 //     //let's create an algebra that's a quotient of target
00456 //     //by the image generated by the image of *it
00457 //     alg= *target;
00458 
00459 
00460 //     for(i=1; i<= source->variables_in_use(); i++)
00461 //       if( it->has_image_set(i) )
00462 //      alg.add_relation( it->of_generator(i) );
00463     
00464 //     alg.fix_alphabets();
00465 //     alg.find_grobner_basis();
00466     
00467 //     // now let's see what the possible choices are
00468 //     choices.clear();
00469 //     dim= 0;
00470     
00471 //     for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00472       
00473 //       d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00474 //       if( choices.count( d ) == 0 ){
00475 //      alg.list_monomials(d, pows);      
00476 //      choices[d]= pows;
00477 //       }
00478 //       dim+= choices[d].size();
00479 //     }
00480 //     //set poss= 2**dim
00481 //     poss= 1;
00482 //     while( dim > 0){
00483 //       poss*= 2;
00484 //       dim--;
00485 //     }
00486     
00487 //     //now try them!
00488     
00489 //     for(code= 0; code < poss; code++){
00490       
00491 //       bit= 1;    
00492 //       for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00493 //      d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00494 //      P.sets_to_zero();
00495         
00496 //      for(i=0; i < choices[d].size(); i++){
00497 //        if( (code & bit) > 0 )
00498 //          P+= choices[d][i];
00499 //        bit*= 2;
00500 //      }
00501         
00502 //      //now P is set
00503 //      it->set_image(*itpol, P);
00504                 
00505 //       }//for itpol
00506 //       // now *it is fully defined !
00507 //       if( it->is_finite() ){
00508 //      //ok we've got one
00509 //      cout << "found one!" << endl;
00510 //      //we start again, but with the 'precise' version
00511 //      for(precise_code= 0; precise_code < precise_poss; precise_code++){
00512           
00513 //        cout << "precise code: " << precise_code << endl;
00514 
00515 //        precise_bit= 1;    
00516 //        for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00517 //          d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00518 //          P.sets_to_zero();
00519             
00520 //          for(i=0; i < precise_choices[d].size(); i++){
00521 //            if( (precise_code & precise_bit) > 0 )
00522 //              P+= precise_choices[d][i];
00523 //            precise_bit*= 2;
00524 //          }
00525         
00526 //          //now P is set
00527 //          //is P equal to our previous choice for
00528 //          //it->image_of(*itpol) modulo ... ?
00529 //          Q= P + it->of_generator(*itpol);
00530 //          if( !alg.reduced_form(Q).is_zero() ) //if not
00531 //            break;                             //we break
00532 //          else
00533 //            hom.set_image(*itpol, P);
00534 //        }//for itpol
00535 //        if( itpol == polvars.end() ){ //if we did not break
00536 //          kept++;
00537 //          // it->compute_kernel();
00538 //          solutions.push_back(hom);
00539 //          cout << "found a precise solution" << endl
00540 //               << "precise code " << precise_code
00541 //               << " out of " << precise_poss
00542 //               << " kept " << kept << endl;
00543 //        }//if we did not break
00544 //      }//for precise code
00545 //       }//if we had something finite
00546       
00547 //     }//for code
00548 //   }//for it
00549   
00550 //   cout << "kept: " << kept << endl;
00551 //   solution_count= kept;
00552   
00553 // }
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 void HomFinder::define_polynomial_variables()
00563 {
00564   list< AffineHomomorphism<F_2> >::iterator it;
00565   list< AffineHomomorphism<F_2> > old_solutions;
00566   //list< long > polvars; //now made global
00567   list< long >::iterator itpol;
00568   long i, d, kept=0;
00569   ZZ dim, poss, code, bit;
00570   GradedAlgebra<F_2> alg;
00571   map< long, Tuple< Polynomial<F_2> > > choices;
00572   Tuple< Polynomial<F_2> > pows;
00573   Polynomial<F_2> P= target->one();
00574 
00575   old_solutions.clear();
00576   old_solutions.splice( old_solutions.begin(), solutions );
00577   
00578   for(it= old_solutions.begin();
00579       it!= old_solutions.end();
00580       it++){
00581     
00582 
00583     //let's find out which variables are "polynomial"
00584     //also, create an algebra that's a quotient of target
00585     //by the image generated by the image of *it
00586     
00587     alg= *target;
00588 
00589                         
00590     for(i=1; i<= source->variables_in_use(); i++)
00591       if( it->has_image_set(i) )
00592         alg.add_relation( it->of_generator(i) );
00593     
00594     alg.fix_alphabets();
00595     alg.find_grobner_basis();
00596     
00597     // now let's see what the possible choices are
00598     choices.clear();
00599     dim= 0;
00600     
00601     for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00602       
00603       d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00604       if( choices.count( d ) == 0){
00605         alg.list_monomials(d, pows);      
00606         choices[d]= pows;
00607       }
00608       dim+= choices[d].size();
00609       
00610             
00611     }
00612     //set poss= 2**dim
00613     poss= 1;
00614     while( dim > 0){
00615       poss*= 2;
00616       dim--;
00617     }
00618     
00619     //now try them!
00620     
00621     for(code= 0; code < poss; code++){
00622       bit= 1;    
00623       for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00624         d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00625         P.sets_to_zero();
00626         
00627         for(i=0; i < choices[d].size(); i++){
00628           if( (code & bit) > 0 )
00629             P+= choices[d][i];
00630           bit*= 2;
00631         }
00632         
00633         //now P is set
00634         it->set_image(*itpol, P);
00635         
00636         
00637       }//for itpol
00638       // now *it is fully defined !
00639       if( it->is_finite() ){
00640         kept++;
00641         //it->compute_kernel();
00642         solutions.push_back(*it);
00643       }
00644       
00645     }//for code
00646   }//for it
00647 
00648   if(verbose)
00649     cout << kept << " possibilities kept after Steps 1,2,3 and Test 1"
00650          << endl;
00651   solution_count= kept;
00652   
00653 }
00654 
00655 void HomFinder::define_polynomial_variables_brutally()
00656 {
00657   list< AffineHomomorphism<F_2> >::iterator it;
00658   list< AffineHomomorphism<F_2> > old_solutions;
00659   //list< long > polvars; //now made global
00660   list< long >::iterator itpol;
00661   long i, d, kept=0;
00662   ZZ dim, poss, code, bit;
00663   GradedAlgebra<F_2> alg;
00664   map< long, Tuple< Polynomial<F_2> > > choices;
00665   Tuple< Polynomial<F_2> > pows;
00666   Polynomial<F_2> P= target->one();
00667 
00668   old_solutions.clear();
00669   old_solutions.splice( old_solutions.begin(), solutions );
00670 
00671   alg= *target;
00672   alg.fix_alphabets();
00673   
00674   for(it= old_solutions.begin();
00675       it!= old_solutions.end();
00676       it++){
00677     
00678 
00679     // now let's see what the possible choices are
00680     choices.clear();
00681     dim= 0;
00682     
00683     for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00684       
00685       d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00686       if( choices.count( d ) == 0){
00687         alg.list_monomials(d, pows);      
00688         choices[d]= pows;
00689       }
00690       dim+= choices[d].size();
00691       
00692             
00693     }
00694     //set poss= 2**dim
00695     poss= 1;
00696     while( dim > 0){
00697       poss*= 2;
00698       dim--;
00699     }
00700     
00701     //now try them!
00702     
00703     for(code= 0; code < poss; code++){
00704       bit= 1;    
00705       for(itpol= polvars.begin(); itpol!= polvars.end(); itpol++){
00706         d= source->hom_degrees.find( *itpol )->second;//d= degree of variable *itpol
00707         P.sets_to_zero();
00708         
00709         for(i=0; i < choices[d].size(); i++){
00710           if( (code & bit) > 0 )
00711             P+= choices[d][i];
00712           bit*= 2;
00713         }
00714         
00715         //now P is set
00716         it->set_image(*itpol, P);
00717         
00718         
00719       }//for itpol
00720       // now *it is fully defined !
00721       if( it->is_finite() ){
00722         kept++;
00723         //it->compute_kernel();
00724         solutions.push_back(*it);
00725       }
00726       
00727     }//for code
00728   }//for it
00729 
00730   if(verbose)
00731     cout << kept << " possibilities kept after Steps 1 & 2 "
00732          << " (all choices for polynomial variables included) and Test 1"
00733          << endl;
00734   solution_count= kept;
00735   
00736 }
00737 
00738 
00739 
00740 void HomFinder::identify()
00741 {
00742   list< AffineHomomorphism<F_2> >::iterator it, itp;
00743   long cit=0, citp=0;
00744       
00745   for(it= solutions.begin();
00746       it!= solutions.end();
00747       it++){
00748     
00749     cit++;
00750     citp= 0;
00751     
00752     for(itp= it, itp++;
00753         itp!= solutions.end();){
00754       
00755       citp++;
00756       if(very_verbose)
00757         cout << "comparing " << cit << " and " << citp << endl;
00758       
00759         
00760       // are f and g essentially the same ?
00761       
00762       
00763       if( it->is_essentially_contained_in(*itp) &&
00764           itp->is_essentially_contained_in(*it) &&
00765           it->factors_through(itp->kernel) &&
00766           itp->factors_through(it->kernel) )
00767         {
00768           itp= solutions.erase( itp );
00769           solution_count--;
00770         }
00771       else
00772         itp++;
00773     }//for itp 
00774   }//for it
00775   
00776 }
00777 
00778 
00779 long HomFinder::weight(const Polynomial<F_2>& relation, const AffineHomomorphism<F_2>& phi)
00780 {
00781   list< long >::iterator it;
00782   list< long > newvars;
00783   
00784   newvars.clear();
00785     
00786   for(it= higher_variables.begin(); it!= higher_variables.end(); it++)
00787     if( relation.involves_variable(*it) && !phi.has_image_set(*it) )
00788       newvars.push_back(*it);
00789 
00790   // compute "possibilities"
00791   list< long >::iterator nv;
00792   long dim=0;
00793   long d;
00794   for(nv= newvars.begin();
00795       nv!= newvars.end();
00796       nv++){
00797     d= source->hom_degrees.find(*nv)->second;
00798     dim+= monomials[d].size();
00799   }
00800 
00801   return dim;
00802 }
00803 
00804 void HomFinder::sort()
00805 {
00806   long minimal_weight, w;
00807   list< Polynomial<F_2> >::iterator it, itmini;
00808   list< Polynomial<F_2> > old_gens;
00809   AffineHomomorphism<F_2> phi(source, target);
00810   Polynomial<F_2> zeropol= target->one();
00811   list< long >::iterator hvars;
00812   
00813   old_gens.splice(old_gens.begin(), higher_relations );
00814   zeropol.sets_to_zero();
00815     
00816   while( !old_gens.empty() ){
00817     minimal_weight= -1;
00818     // find the relation of minimal weight
00819     for(it= old_gens.begin();
00820         it!= old_gens.end();
00821         it++){
00822       w= weight(*it, phi);
00823       if( minimal_weight < 0 || minimal_weight > w){
00824         minimal_weight= w;
00825         itmini= it;
00826       }
00827     }
00828 
00829     //    cout << "minimum: " << minimal_weight << " for relation "
00830     // << *itmini << endl;
00831         
00832     higher_relations.push_back( *itmini );
00833     //update phi
00834     for(hvars= higher_variables.begin();
00835         hvars!= higher_variables.end();
00836         hvars++)
00837       if( itmini->involves_variable(*hvars) )
00838         phi.set_image(*hvars, zeropol);
00839     //done
00840     old_gens.erase(itmini);
00841         
00842   }//while nonempty
00843   
00844    
00845 }
00846 
00847 // TO DO: REMOVE SOME GROBNER BASIS COMPUTATIONS !!!!!
00848 void HomFinder::test_steenrod(){
00849   list< AffineHomomorphism<F_2> >::iterator it;
00850   list< Polynomial<F_2> >::iterator itker;
00851   long n=0;
00852   UnstableAlgebra test;
00853   UnstableAlgebra *ptr;
00854 
00855   ptr= (UnstableAlgebra *) source;
00856 
00857   for(it= solutions.begin(); it!=solutions.end();){
00858 
00859     test= *ptr;
00860     test.fix_alphabets();
00861 
00862     n++;
00863     if(verbose)
00864       cout << "testing homomorphism number " << n << endl;
00865 
00866     for(itker= it->kernel.generators.begin(); 
00867         itker!= it->kernel.generators.end();
00868         itker++){
00869       //      cout << *itker << endl;
00870       test.find_grobner_basis();
00871       if( !test.reduced_form( *itker ).is_zero() )
00872         test.add_relation( *itker );
00873       }
00874     
00875 
00876     test.find_grobner_basis();
00877     if( test.is_saturated() ){
00878       if(verbose)
00879         cout << "steenrod test passed" << endl;
00880       it++;
00881     }
00882     else
00883       {      
00884         if(verbose)
00885           cout << "rejected" << endl;
00886         it= solutions.erase( it );
00887         solution_count--;
00888       }
00889 
00890   }//for it
00891 
00892 }
00893 
00894 
00895 void HomFinder::restrict_to_elemab(ifstream& res_file) {
00896   //check which kernels are compatible with restrictions
00897   list< AffineHomomorphism<F_2> >::iterator it;
00898   list< Polynomial<F_2> >::iterator ker;
00899   long nb_elemab, rank, i;
00900   Tuple< AbstractHomomorphism<F_2> > res;
00901   Polynomial<F_2> P;
00902   
00903   res_file >> nb_elemab;
00904   res.resize(nb_elemab);
00905   for(i=0; i< nb_elemab; i++){
00906     res_file >> rank;//unused so far !!
00907     res_file >> res[i];
00908   }
00909   
00910   for(it= solutions.begin();
00911       it!= solutions.end();){
00912 
00913     if(verbose) 
00914       cout << "trying one solution..." << endl;
00915 
00916         //we try each elemab
00917     for(i=0; i< nb_elemab; i++){
00918       if(very_verbose)
00919         cout << "trying subgroup number " << i << endl;
00920           
00921       for(ker= it->kernel.generators.begin();
00922           ker!= it->kernel.generators.end();
00923           ker++){
00924             
00925         P= res[i].of( *ker );
00926             
00927         if(!P.is_zero()){
00928           if(verbose)
00929             cout << "impossible !" << endl
00930                  << *ker << " restricts to " << P << endl;
00931           break; // out of for ker
00932         }
00933             
00934       }//for ker
00935       if( ker != it->kernel.generators.end() )//did we break ?
00936         break; // out of for i
00937     }//for i
00938     if(i<nb_elemab){ // contradiction found ?
00939       it= solutions.erase(it);
00940       solution_count--;
00941     }
00942     else
00943       it++;
00944   }//for it
00945       
00946  
00947 }
00948 
00949 
00950 void HomFinder::get_equivalence_class(const list< AffineHomomorphism<F_2> >& homs,
00951                                       const AffineHomomorphism<F_2>& f){
00952   list< AffineHomomorphism<F_2> >::const_iterator it;
00953 
00954   solution_count= 0;
00955   solutions.clear();
00956   
00957   for(it= homs.begin();
00958       it!= homs.end();
00959       it++){
00960         
00961     if( it->is_essentially_contained_in(f) &&
00962         f.is_essentially_contained_in(*it) &&
00963         it->factors_through(f.kernel) &&
00964         f.factors_through(it->kernel) ) {
00965 
00966       solutions.push_back(*it);
00967       solution_count++;
00968     }
00969 
00970   }//for it
00971 
00972 //   if(verbose)
00973 //     cout << "there were " << solution_count
00974 //       << " homomorphisms in the equivalence class"
00975 //       << endl;
00976 }
00977 
00978 
00979 
00980 bool HomFinder::polvars_are_involved_in(const AffineHomomorphism<F_2>& f){
00981   list< long >::iterator itpol;
00982 
00983   for(itpol= polvars.begin();
00984       itpol!= polvars.end();
00985       itpol++)
00986     if(f.kernel.variable_shows_up( *itpol ))
00987       return true;
00988   return false;
00989 }
00990 
00991 long HomFinder::extend(AffineHomomorphism<F_2>& f){
00992   long ans=0;  
00993 
00994   // construct B/<f(A)>
00995   GradedAlgebra<F_2> quotient= *target;
00996   long i;
00997   for(i=1; i<= source->variables_in_use(); i++)
00998     quotient.add_relation(f.of_generator(i));
00999 
01000   quotient.fix_alphabets();
01001   quotient.find_grobner_basis();
01002   //done
01003   
01004   //now add the missing variables to A
01005   Tuple< Polynomial<F_2> > Bvars= target->get_variables();
01006   map< long, Polynomial<F_2> > newvars;
01007 
01008   for(i=1; i<= quotient.variables_in_use(); i++)
01009     if( !quotient.reduced_form(Bvars[i]).is_zero() ){
01010       ans++;
01011       source->new_variable(quotient.nameof(i), quotient.hom_degrees[i]);
01012       newvars[ source->variables_in_use() ]= Bvars[i];
01013     }
01014   //CAREFUL ! at this point the steenrod operations are not defined
01015   //for the new elements just added in A !!
01016 
01017   // now extend f
01018   map< long, Polynomial<F_2> >::iterator it_new;
01019 
01020   for(it_new= newvars.begin();
01021       it_new != newvars.end();
01022       it_new++)
01023     f.set_image( it_new->first, it_new->second );
01024   
01025   return ans;
01026 }
01027 
01028 long HomFinder::extend_all(){
01029   long ans=0;  
01030   AffineHomomorphism<F_2> f= *solutions.begin();
01031 
01032   // construct B/<f(A)>
01033   GradedAlgebra<F_2> quotient= *target;
01034   long i;
01035   for(i=1; i<= source->variables_in_use(); i++)
01036     quotient.add_relation(f.of_generator(i));
01037 
01038   quotient.fix_alphabets();
01039   quotient.find_grobner_basis();
01040   //done
01041   
01042   //now add the missing variables to A
01043   Tuple< Polynomial<F_2> > Bvars= target->get_variables();
01044   map< long, Polynomial<F_2> > newvars;
01045 
01046   for(i=1; i<= quotient.variables_in_use(); i++)
01047     if( !quotient.reduced_form(Bvars[i]).is_zero() ){
01048       ans++;
01049       source->new_variable(quotient.nameof(i), quotient.hom_degrees[i]);
01050       newvars[ source->variables_in_use() ]= Bvars[i];
01051     }
01052   //CAREFUL ! at this point the steenrod operations are not defined
01053   //for the new elements just added in A !!
01054 
01055   // now extend all the solutions
01056   list< AffineHomomorphism<F_2> >::iterator it;
01057   map< long, Polynomial<F_2> >::iterator it_new;
01058 
01059   for(it= solutions.begin();
01060       it != solutions.end();
01061       it++){
01062 
01063     for(it_new= newvars.begin();
01064         it_new != newvars.end();
01065         it_new++)
01066       it->set_image( it_new->first, it_new->second );
01067     if( ans > 0 )
01068       it->compute_kernel(); //this is new in extend_all(), compared to
01069                             //extend()
01070   }
01071   
01072   return ans;
01073 }
01074 
01075 
01076 
01077 bool HomFinder::polynomial_test(){
01078   bool ans;
01079   long n;
01080   list< AffineHomomorphism<F_2> >::iterator it;
01081   Polynomial<F_2> zero= source->one();
01082   zero.sets_to_zero();
01083   list< Polynomial<F_2> >::iterator debug;
01084 
01085   for(it= solutions.begin();
01086       it != solutions.end();
01087       it++){
01088 
01089     n= extend( *it );
01090     it->compute_kernel();
01091     ans= polvars_are_involved_in( *it );
01092     // we put A back into its original state, whether the test has
01093     // failed or not, just to be clean
01094     while(n > 0){
01095       source->kill_top_variable(zero);
01096       n--;
01097     }
01098     //ok done
01099     if( ans )
01100       return false;
01101     // else, we restore *it also, so it's all ready to proceed
01102     it->remove_extra_data();
01103   }//for it
01104 
01105   return true;
01106 }
01107 
01108 
01109 void HomFinder::compute_all_kernels(){
01110   list< AffineHomomorphism<F_2> >::iterator it;
01111 
01112   for(it= solutions.begin();
01113       it != solutions.end();
01114       it++){
01115     it->compute_kernel();
01116   }
01117 }

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