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
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
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
00125
00126
00128 void find_grobner_basis(){
00129 relations.grobnerize();
00130
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
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
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;
00169 if (j == i )
00170 break;
00171 }
00172 }
00173 if( it == relations.generators.end() )
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
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
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
00281 if( !relations.variable_shows_up(var_in_use) )
00282 return false;
00283
00284
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
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
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 }
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
00513 rel.swap_variables(var, this->var_in_use + 1);
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
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
00593 rel.swap_variables(var, this->var_in_use + 1);
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
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
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
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
00693 file >> n;
00694 P.alphabet= &x;
00695 while(n > 0){
00696 file >> P;
00697 x.add_relation(P);
00698 n--;
00699 }
00700
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