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

affinealgebras.H

00001 #ifndef _AFFINEALGEBRAS_H_
00002 #define _AFFINEALGEBRAS_H_
00003 
00004 #include <fstream>
00005 #include <iostream>
00006 #include "algebras.H"
00007 #include <string>
00008 #include "alphabet.H"
00009 using namespace std;
00010 
00011 
00012 
00014 
00024 template <class K>
00025 class AffineAlgebra : public SimpleAlphabet {
00026 public:
00027 
00028   // data ///////////////////////////////////////
00030 
00032   bool verbose;
00033   bool very_verbose;
00034 
00036   Ideal<K> relations;
00037 
00038 
00041   AffineAlgebra<K>(){
00042     verbose= false;
00043     very_verbose= false;
00044   }
00045 
00046   // little things /////////////////////////////////////////////////
00048 
00050 
00054   Polynomial<K> new_variable(const string& name){
00055     Polynomial<K> ans;
00056 
00057     SimpleAlphabet::new_variable(name);
00058     ans= Polynomial<K>( PowProd( var_in_use )  );
00059     ans.alphabet= this;
00060 
00061     return ans;
00062   }
00064   Polynomial<K> one() const {
00065     Polynomial<K> ans;
00066 
00067     ans= Polynomial<K>( PowProd(0) );
00068     ans.alphabet= (Alphabet *) this;
00069 
00070     return ans;
00071 
00072   }
00073  
00075   Tuple< Polynomial<K> > get_variables() const 
00076   {
00077     Tuple< Polynomial<K> > ans;
00078     
00079     ans.resize(this->var_in_use + 1);
00080     for(long i=0; i<= this->var_in_use; i++){
00081       ans[i]= Polynomial<K>( PowProd(i) );
00082       ans[i].alphabet= (Alphabet *) this;
00083     }
00084     return ans;
00085   }
00086 
00088   void add_relation(const Polynomial<K>& rel){
00089     if( !rel.is_zero() )
00090       relations.generators.push_back( rel );
00091   }
00093   long count_relations() const {
00094     long ans=0;
00095     typename list< Polynomial<K> >::const_iterator it;
00096 
00097     for(it= relations.generators.begin();
00098         it!= relations.generators.end();
00099         it++)
00100       ans++;
00101 
00102     return ans;
00103   }
00105 
00113   virtual void fix_alphabets(){
00114     typename list< Polynomial<K> >::iterator it;
00115 
00116     for(it= relations.generators.begin();
00117         it != relations.generators.end();
00118         it++)
00119       it->alphabet= this;
00120   }
00121 
00123   // things to do with grobner basis ////////////////////////////////
00125 
00126 
00128   void find_grobner_basis(){
00129     relations.grobnerize();
00130     // relations.minimalize();
00131   }
00133   void reduce_grobner_basis(){
00134     relations.reduce();
00135   }
00137   Polynomial<K> reduced_form(const Polynomial<K>& f) const {
00138     return division_remainder(f, relations.generators);
00139   }
00140 
00142   // return some info on the algebra //////////////////////////////
00144 
00146 
00150   bool is_finite_dimensional() const {
00151     typename list< Polynomial<K> >::const_iterator it;
00152     PowProd pow;
00153     long i, j;
00154 
00155     for(i=1; i<= var_in_use; i++){
00156       
00157       // is there a relation whose lp() is a power of variable i ?
00158       for(it= relations.generators.begin();
00159           it!= relations.generators.end();
00160           it++){
00161         
00162         
00163         pow= it->lp();
00164         
00165         if( pow.nvars() == i ){
00166           for(j=1; j < i; j++)
00167             if( pow.power_of(j) != 0 )
00168               break; // out of for j loop
00169           if (j == i ) // all went okay ?
00170             break; // out of for it loop
00171         }
00172       }
00173       if( it == relations.generators.end() ) // could not find one ?
00174         return false;
00175     }
00176     
00177     return true;
00178   }
00180   bool is_polynomial_variable(const Polynomial<K>& P) const {
00181     Polynomial<K> Q;
00182     long var;
00183 
00184     var= P.lp().nvars();
00185     Q= Polynomial<K>( PowProd(var) );
00186     Q+= P*(-1);
00187 
00188     if(!Q.is_zero())
00189       return false;
00190 
00191     if( relations.variable_shows_up( var ) )
00192       return false;
00193 
00194     return true;
00195   }
00196 
00197 
00198   // simple modifications to the algebra ////////////////////////////
00200 
00202 
00208   virtual void swap_variables_order(long i, long j, list< Polynomial<K> >& polys){
00209     typename list< Polynomial<K> >::iterator it;
00210     string dummy;
00211 
00212     for(it= relations.generators.begin(); 
00213         it!= relations.generators.end(); 
00214         it++)
00215       it->swap_variables(i,j);
00216   
00217     for(it= polys.begin(); 
00218         it!= polys.end(); 
00219         it++)
00220       it->swap_variables(i,j);
00221 
00222 
00223     dummy= names[i];
00224     names[i]= names[j];
00225     names[j]= dummy;
00226 
00227 
00228   }
00229 
00230 virtual  void swap_variables_order(long i, long j){
00231     list< Polynomial<K> > empty_list;
00232 
00233     this->swap_variables_order(i,j,empty_list);
00234   }
00235 
00236 
00238   void tensor_with(const AffineAlgebra<K>& that)
00239   {
00240     long i, n;
00241     typename list< Polynomial<K> >::const_iterator it;
00242     Polynomial<K> P;
00243     
00244     
00245     n= this->var_in_use;
00246     
00247     for(i=1; i<= that.variables_in_use(); i++)
00248       new_variable( that.nameof(i) );
00249     
00250     for(it= that.relations.generators.begin();
00251         it!= that.relations.generators.end();
00252         it++){
00253       P= *it;
00254       P.shift_variables(n);
00255       add_relation(P);
00256     }
00257     
00258     fix_alphabets();
00259   }
00260   
00261 
00262 
00263 
00264 
00265   // methods to look for redundancies and find a simpler presentation
00267 
00268 
00270 
00276   bool top_variable_redundant(Polynomial<K>& result){
00277     typename list< Polynomial<K> >::iterator it;
00278     PowProd top_var;
00279     K c;
00280     // does the varianle show up at all?
00281     if( !relations.variable_shows_up(var_in_use) )
00282       return false;
00283 
00284     // otherwise, we need LEX
00285     if(PowProd::current_order() != LEX){
00286       cerr << "Error: killing variables requires LEX order" << endl;
00287       return false;
00288     }
00289 
00290     find_grobner_basis();
00291 
00292     top_var= PowProd( var_in_use );
00293     
00294 
00295     for(it= relations.generators.begin(); 
00296         it!= relations.generators.end() && !(it->lp()==top_var); 
00297         it++);
00298 
00299     if( it== relations.generators.end() )
00300       return false;
00301     //else...
00302     c= it->lc();
00303     result= *it;
00304     result.add_term(top_var, -c);
00305     c= -1/c;
00306     result*= c;
00307     return true;
00308 
00309   }
00310 
00312 
00321   bool variable_redundant(long var, Polynomial<K>& result) const {
00322     int old_order;
00323     long old_priority;    
00324     PowProd pow;
00325     typename list< Polynomial<K> >::iterator it;
00326     Ideal<K> test;
00327     bool ans;
00328     K c;
00329 
00330     test= relations;
00331 
00332     old_order= Polynomial<K>::get_order_override();
00333     old_priority= Polynomial<K>::get_variable_priority();
00334     Polynomial<K>::set_order_override(DEGLEXSV);
00335     Polynomial<K>::set_variable_priority(var);
00336 
00337     //    find_grobner_basis();
00338     test.grobnerize();
00339 
00340     pow= PowProd( var );
00341     for(it= test.generators.begin(); 
00342         it!= test.generators.end() && !(it->lp()==pow); 
00343         it++);
00344 
00345     if( it== test.generators.end() )
00346       ans= false;
00347     else{
00348       c= it->coeff_of(pow);
00349       result= *it;
00350       result.add_term(pow, -c);
00351       c= -1/c;
00352       result*= c;
00353       ans= true;
00354     }
00355 
00356     Polynomial<K>::set_order_override(old_order);
00357     Polynomial<K>::set_variable_priority(old_priority);
00358     return ans;
00359   }
00360 
00362 
00365   virtual void kill_top_variable(const Polynomial<K>& replacement, list< Polynomial<K> >& polys){
00366     typename list< Polynomial<K> >::iterator it;
00367 
00368     it= relations.generators.begin();
00369     while(it!= relations.generators.end()){
00370       it->substitute_variable(var_in_use,replacement);
00371       if( !it->is_zero() )
00372         it++;
00373       else
00374         it= relations.generators.erase(it);
00375     }
00376 
00377     for(it= polys.begin(); it!= polys.end(); it++)
00378       it->substitute_variable(var_in_use,replacement);
00379 
00380     names.erase(var_in_use);
00381     var_in_use--;
00382 
00383   }
00384 
00385   void kill_top_variable(const Polynomial<K> replacement){
00386     list< Polynomial<K> > empty_list;
00387 
00388     this->kill_top_variable(replacement, empty_list);
00389   }
00390 
00392   void kill_variable(long var, const Polynomial<K>& replacement,list< Polynomial<K> >& polys){
00393 
00394     polys.push_front(replacement);
00395     this->swap_variables_order(var, var_in_use, polys);
00396     this->kill_top_variable( *polys.begin(), polys);
00397     polys.erase( polys.begin() );
00398   }
00399 
00400   void kill_variable(long var, const Polynomial<K>& replacement){
00401     list< Polynomial<K> > empty_list;
00402 
00403     kill_variable(var, replacement, empty_list);
00404   }
00405 
00407 
00411   void cut_down_variables(list< Polynomial<K> >& polys){
00412     long leftvar;
00413     Polynomial<K> relation;
00414     typename list< Polynomial<K> >::iterator it;
00415 
00416 
00417     for(leftvar= 1; 
00418         leftvar <= var_in_use && !relations.variable_shows_up(leftvar);
00419         leftvar++);
00420 
00421     while( leftvar <= var_in_use ){
00422       if(very_verbose)
00423         cout << "trying to kill variable " << names[leftvar] << "..." << endl;
00424 
00425       if( variable_redundant(leftvar, relation) ){
00426         if(verbose){
00427           cout << "Redundancy found! variable  "
00428                << names[leftvar] << " = " 
00429                << relation << endl;
00430         }
00431         this->kill_variable(leftvar, relation, polys);
00432       }
00433       else{
00434 
00435         for(leftvar++; 
00436         leftvar <= var_in_use && !relations.variable_shows_up(leftvar);
00437         leftvar++);
00438       }
00439 
00440     }// end of WHILE
00441   }
00442   
00443   void cut_down_variables(){
00444     list< Polynomial<K> > empty_list;
00445 
00446     cut_down_variables(empty_list);
00447   }
00448 
00450 
00478   AbstractHomomorphism<K> find_redundancies(){
00479     bool grobner_done;
00480     long nb_relations, current_relation, var;
00481     list< Polynomial<K> > structure_constants;
00482     Polynomial<K> rel;
00483     typename list< Polynomial<K> >::iterator it;
00484     AbstractHomomorphism<K> ans, temphom;
00485     
00486 
00487     if(verbose)
00488       cout << "{\\bf Now reducing variables and relations}"
00489            << endl << endl;
00490 
00491     grobner_done= false;
00492     ans.make_identity(this->var_in_use);
00493     
00494     
00495     nb_relations= 0;
00496     current_relation= 1;
00497     structure_constants= relations.generators;
00498     relations.generators.clear();
00499     
00500     for(it= structure_constants.begin(); 
00501         it!= structure_constants.end();){
00502       
00503       if( (var= it->has_lonely_variable(rel)) > 0 ){
00504         if(very_verbose)
00505           cout << "relation " << current_relation
00506                << " yields a variable redundancy: $"
00507                << this->nameof(var) << " = " << rel 
00508                << "$" << endl << endl;
00509         it= structure_constants.erase(it);
00510         kill_variable(var, rel, structure_constants);
00511         grobner_done= false;
00512         // now write the corresponding homomorphism
00513         rel.swap_variables(var, this->var_in_use + 1); // rel itself must be updated !!
00514         temphom.make_identity(this->var_in_use + 1);
00515         temphom.set_image(this->var_in_use + 1, Polynomial<K>( PowProd(var) ) );
00516         temphom.set_image(var, rel);
00517         ans= temphom * ans;
00518       }
00519       else{
00520         
00521         if( !grobner_done ){
00522           find_grobner_basis();
00523           reduce_grobner_basis();
00524           grobner_done= true;
00525         }
00526         rel= reduced_form( *it );
00527         if( !rel.is_zero() ){
00528           nb_relations++;
00529           if(very_verbose)
00530             cout << "adding relation " << current_relation
00531                  << " (total " << nb_relations << " relations added): "
00532                  << "$" << rel << "$" << endl << endl;
00533           add_relation(rel);
00534           grobner_done= false;
00535           it++;
00536         }
00537         else{
00538           if(very_verbose)
00539             cout << "relation " << current_relation << " redundant"
00540                  << endl << endl;
00541           it= structure_constants.erase(it);
00542         }
00543       }
00544       current_relation++;
00545     }
00546     //cut_down_variables();
00547     if(verbose)
00548       cout << "{\\bf Final presentation: } " 
00549            << var_in_use << " variables kept, " 
00550            << nb_relations << " relations kept" 
00551            << endl << endl;
00552     
00553     relations.generators= structure_constants;
00554     return ans;
00555   }
00556   
00558 
00564   AbstractHomomorphism<K> find_unitary_redundancies(){
00565     bool grobner_done;
00566     long nb_relations, current_relation, var;
00567     list< Polynomial<K> > structure_constants;
00568     Polynomial<K> rel;
00569     typename list< Polynomial<K> >::iterator it;
00570     AbstractHomomorphism<K> ans, temphom;
00571     
00572     grobner_done= false;
00573     
00574     
00575     nb_relations= 0;
00576     current_relation= 1;
00577     structure_constants= relations.generators;
00578     relations.generators.clear();
00579     
00580     for(it= structure_constants.begin(); 
00581         it!= structure_constants.end();){
00582       
00583       if( (var= it->has_unitary_variable(rel)) > 0 ){
00584         if(verbose)
00585           cout << "relation " << current_relation
00586                << " yields a variable redundancy: $"
00587                << this->nameof(var) << " = " << rel 
00588                << "$" << endl << endl;
00589         it= structure_constants.erase(it);
00590         kill_variable(var, rel, structure_constants);
00591         grobner_done= false;
00592         // now write the corresponding homomorphism
00593         rel.swap_variables(var, this->var_in_use + 1); // rel itself must be updated !!
00594         temphom.make_identity(this->var_in_use + 1);
00595         temphom.set_image(this->var_in_use + 1, Polynomial<K>( PowProd(var) ) );
00596         temphom.set_image(var, rel);
00597         ans= temphom * ans;
00598       }
00599       else{
00600         
00601         if( !grobner_done ){
00602           find_grobner_basis();
00603           reduce_grobner_basis();
00604           grobner_done= true;
00605         }
00606         rel= reduced_form( *it );
00607         if( !rel.is_zero() ){
00608           nb_relations++;
00609           if(very_verbose)
00610             cout << "adding relation " << current_relation
00611                  << " (total " << nb_relations << " relations added): "
00612                  << "$" << rel << "$" << endl << endl;
00613           add_relation(rel);
00614           grobner_done= false;
00615           it++;
00616         }
00617         else{
00618           if(very_verbose)
00619             cout << "relation " << current_relation << " redundant"
00620                  << endl << endl;
00621           it= structure_constants.erase(it);
00622         }
00623       }
00624       current_relation++;
00625     }
00626     //cut_down_variables();
00627     if(verbose)
00628       cout << "{\\bf Final presentation: } " 
00629            << var_in_use << " variables kept, " 
00630            << nb_relations << " relations kept" 
00631            << endl << endl;
00632     
00633     relations.generators= structure_constants;
00634     return;
00635   }
00636   
00637 
00638 
00639 
00640   // friend printing ////////////////////////////////////////////
00642 
00643   friend ostream& operator<<(ostream& os, const AffineAlgebra<K>& R){
00644     typename map<long, string>::const_iterator it_gen;
00645     typename list< Polynomial<K> >::const_iterator it_rel;
00646 
00647     os << "generators:" << endl;
00648     for(it_gen= R.names.begin(); it_gen!= R.names.end(); it_gen++)
00649       os << it_gen->second << " ";
00650 
00651     os << endl << "relations:" << endl;
00652     for(it_rel=R.relations.generators.begin(); 
00653         it_rel!= R.relations.generators.end(); it_rel++)
00654       os << *it_rel << endl;
00655 
00656     return os;
00657   }
00658 
00659 friend ofstream& operator<<(ofstream& file, AffineAlgebra<K>& x){
00660   long n;
00661   n= x.count_relations();
00662   file << n << " ";
00663 
00664 
00665  typename list< Polynomial<K> >::iterator it;
00666  for(it= x.relations.generators.begin();
00667      it!= x.relations.generators.end();
00668      it++)
00669    file << *it;
00670 
00671 
00672 
00673  file << x.var_in_use << " ";
00674  for(long i=1; i <= x.var_in_use; i++)
00675    file << x.nameof(i) << " ";
00676 
00677  return file;
00678 }
00679 
00680 friend void operator>>(ifstream& file, AffineAlgebra<K>& x){
00681   long n, nv;
00682   Polynomial<K> P;
00683 
00684   // first delete everything !
00685   x.relations.generators.clear();
00686   nv= x.var_in_use;
00687   Polynomial<K> zero;
00688   zero.sets_to_zero();
00689   for(long i=1; i <= nv; i++)
00690     x.kill_top_variable(zero);
00691 
00692   // read the relations
00693   file >> n;
00694   P.alphabet= &x;
00695   while(n > 0){
00696     file >> P;
00697     x.add_relation(P);
00698     n--;
00699   }
00700   //read the variables
00701   file >> nv;
00702   string name;
00703   while(nv > 0){
00704     file >> name;
00705     x.new_variable(name);
00706     nv--;
00707   }
00708 
00709 
00710 
00711 }
00712 
00713 
00714 
00715 };
00716 
00717 
00718 
00719 
00720 
00721 
00722 #endif
00723 
00724 
00725 
00726 
00727 
00728 
00729 

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