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

gradedalgebras.H

00001 #ifndef _GRADEDALGEBRAS_H_
00002 #define _GRADEDALGEBRAS_H_
00003 
00004 
00005 #include "algebras.H"
00006 #include <set>
00007 using namespace std;
00008 
00010 
00013 template <class K>
00014 class GradedAlgebra : public AffineAlgebra<K> {
00015 public:
00017 
00018   map<long, long> hom_degrees;
00019 
00020   // first we need to do the usual work of rewriting the**************************
00021   // methods related to the variables ********************************************
00022 
00023   Polynomial<K> new_variable(const string& name, long degree){
00024     Polynomial<K> ans;    
00025 
00026     ans= AffineAlgebra<K>::new_variable(name);
00027     hom_degrees[this->var_in_use]= degree;
00028 
00029     return ans;
00030   }
00031  
00032   virtual void swap_variables_order(long i, long j,list< Polynomial<K> >& polys){
00033     long dummy;
00034 
00035     AffineAlgebra<K>::swap_variables_order(i,j,polys);
00036     dummy= hom_degrees[i];
00037     hom_degrees[i]= hom_degrees[j];
00038     hom_degrees[j]= dummy;
00039   }
00040 
00041   // code below is the same as for affinealgebra !!
00042   // however, since we redefine a method with the
00043   // same name (but different arguments), the
00044   // compiler would be confused if we did not rewrite
00045   // this one as well.
00046   virtual void swap_variables_order(long i, long j){
00047     list< Polynomial<K> > empty_list;
00048     
00049     this->swap_variables_order(i,j,empty_list);
00050   }
00051 
00052 
00053   virtual void kill_top_variable(const Polynomial<K>& replacement,list< Polynomial<K> >& polys){
00054     AffineAlgebra<K>::kill_top_variable(replacement,polys);
00055     hom_degrees.erase(this->var_in_use + 1);
00056   }
00057 
00058 
00059   virtual void kill_top_variable(const Polynomial<K>& replacement){
00060     list< Polynomial<K> > empty_list;
00061 
00062     this->kill_top_variable(replacement,empty_list);
00063   }
00064 
00065   // more interesting things related to the grading ********************
00066   // *******************************************************************
00067 
00069 
00075   long hom_degree_of(const Polynomial<K>& x) const {
00076     PowProd pow= x.lp();
00077     long ans=0;
00078 
00079 
00080     for(long i= 1; i <= pow.nvars(); i++){
00081       ans+= pow.power_of(i)*hom_degrees.find(i)->second;
00082     }
00083     return ans;
00084 
00085   }
00086   
00087   bool is_homogeneous(const Polynomial<K> x) const {
00088     typename map<PowProd, K>::const_iterator it;
00089     long deg;
00090     
00091     it= x.coeffs.begin();
00092     if( it == x.coeffs.end() ) // zero poly?
00093       return true;
00094     deg= hom_degree_of(it->first);
00095     
00096     for(it++; it!= x.coeffs.end(); it++){
00097       if( deg != hom_degree_of(it->first) )
00098         return false;
00099     }
00100     
00101     return true;
00102     
00103   }
00104   
00105   Polynomial<K> hom_part_of(const Polynomial<K>& x, long n) const {
00106     Polynomial<K> ans;
00107     typename map<PowProd, K>::const_iterator it;
00108 
00109     for(it= x.coeffs.begin(); it != x.coeffs.end(); it++){
00110       if( hom_degree_of(it->first) == n )
00111         ans.add_term(it->first, it->second);
00112     }
00113 
00114     ans.alphabet= (Alphabet*) this;
00115     return ans;
00116   }
00117 
00118   void add_relation(const Polynomial<K>& rel) {
00119     typename map<PowProd, K>::const_iterator it;
00120     Polynomial<K> add;
00121     Polynomial<K> buf= rel;
00122     long deg;
00123 
00124     it= buf.coeffs.begin();
00125     while( it != buf.coeffs.end() ) {
00126       deg= hom_degree_of(it->first);
00127       add= hom_part_of(buf, deg);
00128       this->relations.generators.push_back(add);
00129       buf+= add*(-1);
00130       it= buf.coeffs.begin();
00131     }
00132 
00133   }
00134 
00136 
00141   void split_and_sort_relations(){
00142     long i;
00143     Polynomial<K> P;
00144     typename list< Polynomial<K> >::iterator total_it;
00145     list< Polynomial<K> > total_relations;
00146     
00147     if(this->verbose)
00148       cout << endl 
00149            << "{\\bf Now splitting into homogeneous parts}" 
00150            << endl << endl;
00151 
00152 
00153     i= 0;
00154     total_relations.splice(total_relations.begin(), this->relations.generators);
00155 
00156     while( !total_relations.empty() ){
00157       i++;
00158 
00159       if(this->very_verbose)
00160         cout << "adding the relations in degree " << i 
00161              << endl << endl;
00162 
00163       for(total_it= total_relations.begin();
00164           total_it != total_relations.end();){
00165         P= hom_part_of(*total_it, i);
00166         if( !P.is_zero() ){
00167           if( this->very_verbose)
00168             cout << "adding $" << P << " = 0$" 
00169                  << endl << endl;
00170           this->relations.generators.push_back(P);
00171           *total_it += P*(-1);
00172         }
00173         if( total_it->is_zero() )
00174           total_it= total_relations.erase(total_it);
00175         else
00176           total_it++;
00177       }
00178     }// end of WHILE
00179 
00180   }
00181 
00182   //returns info on the algebra *********************************
00183   //*************************************************************
00185 
00193   void even_subalgebra(GradedAlgebra<K>& ans,
00194                        AffineHomomorphism<K>& inclusion) const {
00195     GradedAlgebra<K> empty;
00196     Tuple< Polynomial<K> > gens;
00197     list< Polynomial<K> > odds;
00198     typename list< Polynomial<K> >::iterator it, itp;
00199     long i;
00200     ostringstream autoname;
00201 
00202     //setup
00203     ans= empty;
00204     inclusion.clear();
00205     inclusion.source= &ans;
00206     inclusion.target= this;
00207 
00208     //sorts even and odd generators
00209     gens= this->get_variables();
00210     for(i= 1; i< gens.size(); i++)
00211       if( hom_degree_of( gens[i] ) % 2 == 0 ) { 
00212         ans.new_variable( this->nameof(i),
00213                           hom_degree_of( gens[i] ) );
00214         inclusion.set_image(ans.variables_in_use(), gens[i]);
00215       }
00216       else
00217         odds.push_back( gens[i] );
00218     //add the squares
00219 
00220     for(it= odds.begin(); it!= odds.end(); it++) {
00221       autoname.str("");
00222       autoname << "S" << *it;
00223       ans.new_variable( autoname.str(), 
00224                         2*hom_degree_of(*it) );
00225       inclusion.set_image( ans.variables_in_use(),
00226                            (*it) * (*it) );
00227     }
00228 
00229     //add the twofold products
00230     i= 0;
00231     for(it= odds.begin(); it!= odds.end(); it++)
00232       for(itp= it, itp++; itp != odds.end(); itp++) {
00233         i++;
00234         autoname.str("");
00235         autoname << "p_" << i;
00236         ans.new_variable(autoname.str(), 
00237                          hom_degree_of(*it)+hom_degree_of(*itp) );
00238         inclusion.set_image( ans.variables_in_use(),
00239                              (*it) * (*itp) );
00240       }
00241 
00242   }
00243 
00245 
00252   long top_degree() const {
00253     typename list< Polynomial<K> >::const_iterator it;
00254     PowProd pow;
00255     long i, n;
00256     Tuple<long> nilp;
00257     Tuple< Polynomial<K> > vars= this->get_variables();
00258     Polynomial<K> P;
00259 
00260     nilp.resize(this->var_in_use + 1);
00261 
00262     for(i=1; i<= this->var_in_use; i++){
00263       P= vars[i];
00264       n= 0;
00265       //finds n such that P**(n+1) = 0
00266       while( !this->reduced_form(P).is_zero() ){
00267         P*= vars[i];
00268         n++;
00269       }
00270       nilp[i]= n;
00271     }//for i among variables
00272     
00273     //now the result is sum_i degree(variable i)*nilp(i)
00274     long ans=0;
00275     for(i= 1; i<= this->var_in_use; i++)
00276       ans+= nilp[i] * hom_degrees.find(i)->second;
00277 
00278     return ans;
00279   }
00280 
00282 
00291   void list_monomials(long degree, Tuple< Polynomial<K> >& result) const {
00292     long d;
00293     long i, j;
00294     Tuple< Polynomial<K> > temp;
00295     set< PowProd > ans;
00296     // note: ans is a set of powprods rather than
00297     // polynomials, because there is an order on 
00298     // powprods, and this is required for set<>.
00299     // The container set<> is very convenient right
00300     // here, even if there are some annoying conversions
00301     // between polynomials and powprods below (we certainly
00302     // want the final answer given with polynomials !)
00303     Polynomial<K> P, P_red;
00304     static map< long, Tuple< Polynomial<K> > > already_computed;
00305 
00306     // if degree is absurd
00307     if(degree < 0){
00308       result.resize(0);
00309       return;
00310     }
00311     //in degree 0, there is only 1
00312     if(degree == 0){
00313       result.resize(1);
00314       result[0]= this->one();
00315       return;
00316     }
00317     //else, have we computed this already ?
00318     if(already_computed.count(degree) > 0){
00319       result= already_computed[degree];
00320       return;
00321     }
00322     //else... need some work !
00323     ans.clear();
00324 
00325     for(i=1; i<= this->var_in_use; i++){
00326       d= degree - hom_degrees.find(i)->second;
00327       if(already_computed.count(d) > 0)
00328         temp= already_computed[d];
00329       else{
00330         list_monomials(d, temp);
00331         already_computed[d]= temp;
00332       }
00333       for(j=0; j< temp.size(); j++){
00334         P= temp[j]*Polynomial<K>( PowProd(i) );
00335         P_red= this->reduced_form(P);
00336         if( !P_red.is_zero() )
00337           ans.insert(P.lp());
00338         
00339       }//end inside for
00340     }//endfor
00341 
00342     result.resize( ans.size() );
00343     typename set< PowProd >::iterator it;
00344     
00345     for(it= ans.begin(), i=0;
00346         it!= ans.end();
00347         it++, i++){
00348       result[i]= Polynomial<K>(*it);
00349       result[i].alphabet= (Alphabet *) this;
00350     }
00351   }// done !
00352 
00353 
00354   // friend which prints *******************************
00355   // ***************************************************
00356 
00357 
00358   friend ostream& operator<<(ostream& os, const GradedAlgebra<K>& R){
00359     typename map<long, string>::const_iterator it_gen;
00360     typename map<long, long>::const_iterator it_deg;
00361     typename list< Polynomial<K> >::const_iterator it_rel;
00362 
00363     os << "generators:" << endl << endl;
00364     for(it_gen= R.names.begin(), it_deg= R.hom_degrees.begin(); 
00365         it_gen!= R.names.end(); 
00366         it_gen++, it_deg++)
00367       os << it_gen->second
00368          << " of degree "
00369          << it_deg->second << endl << endl;
00370     
00371     os << endl << "relations:" << endl << endl;
00372     for(it_rel=R.relations.generators.begin(); 
00373         it_rel!= R.relations.generators.end(); it_rel++)
00374       os << *it_rel << endl << endl;
00375 
00376     return os;
00377   }
00379   friend ofstream& operator<<(ofstream& file, GradedAlgebra<K>& A){
00380 
00381     // write the underlying affine algebra
00382     AffineAlgebra<K> *ptr;
00383     ptr= &A;
00384     file << *ptr;
00385     // write the degrees
00386     for(long i=1; i <= A.var_in_use; i++)
00387       file << A.hom_degrees[i] << " ";
00388 
00389     return file;
00390   }
00391 
00392   friend void operator>>(ifstream& file, GradedAlgebra<K>& A){
00393 
00394     //read the underlying affine algebra
00395     AffineAlgebra<K> *ptr;
00396     ptr= &A;
00397     file >> *ptr;
00398     //read the degrees
00399     long deg;
00400     for(long i=1; i<= A.var_in_use; i++){
00401       file >> deg;
00402       A.hom_degrees[i]=deg;
00403     }
00404   }
00405 
00406 
00407 };
00408 
00409 
00410 
00411 #endif

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