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
00021
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
00042
00043
00044
00045
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
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() )
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 }
00179
00180 }
00181
00182
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
00203 ans= empty;
00204 inclusion.clear();
00205 inclusion.source= &ans;
00206 inclusion.target= this;
00207
00208
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
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
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
00266 while( !this->reduced_form(P).is_zero() ){
00267 P*= vars[i];
00268 n++;
00269 }
00270 nilp[i]= n;
00271 }
00272
00273
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
00297
00298
00299
00300
00301
00302
00303 Polynomial<K> P, P_red;
00304 static map< long, Tuple< Polynomial<K> > > already_computed;
00305
00306
00307 if(degree < 0){
00308 result.resize(0);
00309 return;
00310 }
00311
00312 if(degree == 0){
00313 result.resize(1);
00314 result[0]= this->one();
00315 return;
00316 }
00317
00318 if(already_computed.count(degree) > 0){
00319 result= already_computed[degree];
00320 return;
00321 }
00322
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 }
00340 }
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 }
00352
00353
00354
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
00382 AffineAlgebra<K> *ptr;
00383 ptr= &A;
00384 file << *ptr;
00385
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
00395 AffineAlgebra<K> *ptr;
00396 ptr= &A;
00397 file >> *ptr;
00398
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