00001 #ifndef _AFFHOM_H_
00002 #define _AFFHOM_H_
00003
00004 #include "algebras.H"
00005 using namespace std;
00006
00007
00008
00010
00018 template <class K>
00019 class AffineHomomorphism : public AbstractHomomorphism<K> {
00020 public:
00021 const AffineAlgebra<K> *source, *target;
00022 Ideal<K> kernel;
00024
00032 AffineAlgebra<K> assoc_alg;
00033
00034
00036
00037 AffineHomomorphism() : AbstractHomomorphism<K>::AbstractHomomorphism(){
00038
00039 source= target= 0;
00040 }
00041
00042 AffineHomomorphism(const AffineAlgebra<K> *thesource,
00043 const AffineAlgebra<K> *thetarget) : AbstractHomomorphism<K>::AbstractHomomorphism() {
00044
00045 source= thesource;
00046 target= thetarget;
00047 }
00048
00049
00051
00053 void make_identity(const AffineAlgebra<K> *ptr){
00054
00055 source= target= ptr;
00056 AbstractHomomorphism<K>::make_identity(ptr->variables_in_use());
00057 fix_alphabets();
00058 }
00060 void fix_alphabets(){
00061 typename map< long, Polynomial<K> >::iterator it;
00062
00063 for(it= this->images.begin(); it!= this->images.end(); it++)
00064 it->second.alphabet= (Alphabet *) target;
00065 }
00067
00074 void remove_extra_data(){
00075 typename map< long, Polynomial<K> >::iterator it, itp;
00076
00077
00078 for(it= this->images.begin(); it!= this->images.end();)
00079 if( it->first > source->variables_in_use() ){
00080 itp= it;
00081 itp++;
00082 this->images.erase(it->first);
00083 it= itp;
00084 }
00085 else
00086 it++;
00087
00088
00089 typename list< Polynomial<K> >::iterator itker;
00090
00091 for(itker= this->kernel.generators.begin();
00092 itker != this->kernel.generators.end();
00093 ){
00094 if( itker->nvars() > source->variables_in_use() ){
00095 itker= this->kernel.generators.erase( itker );
00096 }
00097 else
00098 itker++;
00099 }
00100 }
00102
00106 bool fill_zeroes()
00107 {
00108 long i;
00109 bool ans= false;
00110 Polynomial<K> P=target->one();
00111
00112 P.sets_to_zero();
00113
00114 for(i=1; i<= source->variables_in_use(); i++)
00115 if( !this->has_image_set(i) ){
00116 ans= true;
00117 this->set_image(i, P);
00118 }
00119
00120 return ans;
00121 }
00122
00124
00127 void get_data_from(const AbstractHomomorphism<K>& f){
00128 AbstractHomomorphism<K> *ptr;
00129
00130 ptr= (AbstractHomomorphism<K> *) this;
00131 *ptr = f;
00132 fix_alphabets();
00133 remove_extra_data();
00134 }
00136
00142 bool is_well_defined() const {
00143 typename list< Polynomial<K> >::const_iterator it;
00144
00145 for(it= source->relations.generators.begin();
00146 it != source->relations.generators.end();
00147 it++)
00148 if( !target->reduced_form( this->of(*it) ).is_zero() )
00149 return false;
00150
00151 return true;
00152 }
00153
00155
00171 AffineHomomorphism<K> simple_section() const {
00172 AffineHomomorphism<K> ans;
00173 long i, j;
00174 Tuple< Polynomial<K> > x;
00175
00176 ans.source= this->target;
00177 ans.target= this->source;
00178 x= source->get_variables();
00179 for(i=1; i<= target->variables_in_use(); i++) {
00180 for(j=1; j<= source->variables_in_use(); j++)
00181 if( source->nameof(j) == target->nameof(i) )
00182 break;
00183 ans.set_image(i, x[j]);
00184 }
00185
00186 return ans;
00187 }
00188
00190
00197 void read_from_GAP_file(ifstream& file) {
00198 long i, j;
00199 Polynomial<K> P= target->one();
00200 K coeff;
00201
00202 this->images.clear();
00203 for(i=1; i<= source->variables_in_use(); i++){
00204 P.sets_to_zero();
00205 for(j=0; j<= target->variables_in_use(); j++) {
00206 file >> coeff;
00207 P.add_term( PowProd(j), coeff);
00208 }
00209 this->set_image(i, P);
00210 }
00211 }
00212
00213
00214
00215
00217
00219
00225 void compute_kernel()
00226 {
00227 AffineAlgebra<K> alg;
00228 long i;
00229 Tuple< Polynomial<K> > vars= source->get_variables();
00230 Polynomial<K> P;
00231
00232 alg= *source;
00233 alg.relations.generators.clear();
00234 alg.tensor_with(*target);
00235 for(i=1; i<= source->variables_in_use(); i++){
00236 P= this->of_generator(i);
00237 P.shift_variables( source->variables_in_use() );
00238 P*= -1;
00239 alg.add_relation( vars[i] + P);
00240 }
00241
00242
00243 alg.find_grobner_basis();
00244 alg.reduce_grobner_basis();
00245
00246
00247
00248 kernel.generators.clear();
00249 typename list< Polynomial<K> >::iterator it;
00250 for(it= alg.relations.generators.begin();
00251 it!= alg.relations.generators.end();
00252 it++)
00253 if( it->nvars() <= source->variables_in_use() ){
00254 P= *it;
00255 P.alphabet= (Alphabet *) source;
00256 kernel.generators.push_back( P );
00257 }
00258 }
00260
00269 void populate_associated_algebra()
00270 {
00271 long i;
00272 Tuple< Polynomial<K> > vars= source->get_variables();
00273 Polynomial<K> P;
00274
00275 assoc_alg= *source;
00276 assoc_alg.relations.generators.clear();
00277 assoc_alg.tensor_with(*target);
00278 for(i=1; i<= source->variables_in_use(); i++){
00279 P= this->of_generator(i);
00280 P.shift_variables( source->variables_in_use() );
00281 P*= -1;
00282 assoc_alg.add_relation( vars[i] + P);
00283 }
00284
00285
00286 assoc_alg.find_grobner_basis();
00287
00288 kernel.generators.clear();
00289 typename list< Polynomial<K> >::iterator it;
00290 for(it= assoc_alg.relations.generators.begin();
00291 it!= assoc_alg.relations.generators.end();
00292 it++)
00293 if( it->nvars() <= source->variables_in_use() ){
00294 P= *it;
00295 P.alphabet= (Alphabet *) source;
00296 kernel.generators.push_back( P );
00297 }
00298 }
00299
00300 bool maps_onto(const Polynomial<K>& P) const {
00301 Polynomial<K> Q;
00302
00303 Q= P;
00304 Q.shift_variables( source->variables_in_use() );
00305 Q= assoc_alg.reduced_form( Q );
00306 return ( Q.nvars() <= source->variables_in_use() );
00307 }
00308
00309 bool maps_onto(const Polynomial<K>& P,
00310 Polynomial<K>& pre_image) const {
00311
00312 pre_image= P;
00313 pre_image.shift_variables( source->variables_in_use() );
00314 pre_image= assoc_alg.reduced_form( pre_image );
00315 if(pre_image.nvars() <= source->variables_in_use() ){
00316 pre_image.alphabet= (Alphabet *) source;
00317 return true;
00318 }
00319 else
00320 return false;
00321 }
00322
00324
00327 bool factors_through(const Ideal<K>& J) const
00328 {
00329 list< Polynomial<K> > kernel;
00330 typename list< Polynomial<K> >::const_iterator it;
00331
00332 for(it= J.generators.begin();
00333 it!= J.generators.end();
00334 it++)
00335 if( !target->reduced_form( this->of(*it) ).is_zero() )
00336 return false;
00337
00338 return true;
00339 }
00340
00341
00342
00344
00346
00352 bool is_finite() const
00353 {
00354 AffineAlgebra<K> A;
00355 long i;
00356
00357
00358 A= *target;
00359 A.fix_alphabets();
00360
00361 for(i=1; i<= source->variables_in_use(); i++)
00362 A.add_relation( this->images.find(i)->second );
00363
00364
00365 A.find_grobner_basis();
00366 A.reduce_grobner_basis();
00367
00368 return A.is_finite_dimensional();
00369 }
00371
00375 bool is_essentially_surjective() const
00376 {
00377 AffineAlgebra<K> A;
00378 long i;
00379
00380
00381 A= *target;
00382 A.fix_alphabets();
00383
00384 for(i=1; i<= source->variables_in_use(); i++)
00385 A.add_relation( this->images.find(i)->second );
00386
00387
00388 A.find_grobner_basis();
00389 A.reduce_grobner_basis();
00390
00391
00392 Polynomial<K> P;
00393
00394 for(i=1; i<= A.variables_in_use(); i++){
00395 P= Polynomial<K>( PowProd(i) );
00396
00397 if( !A.reduced_form(P).is_zero() ){
00398
00399
00400 return false;
00401 }
00402
00403 }
00404
00405 return true;
00406
00407 }
00409 bool is_essentially_contained_in(const AffineHomomorphism<K>& g) const
00410 {
00411 AffineAlgebra<K> alg;
00412 long i;
00413
00414 alg= *target;
00415 for(i=1; i<= source->variables_in_use(); i++)
00416 alg.add_relation( g.of_generator(i) );
00417 alg.fix_alphabets();
00418 alg.find_grobner_basis();
00419
00420 for(i=1; i<= source->variables_in_use(); i++)
00421 if( !alg.reduced_form( this->of_generator(i) ).is_zero() )
00422 break;
00423
00424 return (i == source->variables_in_use()+1 );
00425 }
00426
00427
00428
00430
00431
00432 AffineHomomorphism<K>& operator*=(const AffineHomomorphism<K>& f){
00433 AbstractHomomorphism<K> *a= this;
00434 const AbstractHomomorphism<K> *b= &f;
00435
00436 *a *= *b;
00437 source= f.source;
00438
00439 return *this;
00440 }
00441
00442
00443 AffineHomomorphism<K> operator*(const AffineHomomorphism<K>& f) const {
00444 AffineHomomorphism<K> ans;
00445 const AbstractHomomorphism<K> *a= this;
00446 const AbstractHomomorphism<K> *b= &f;
00447
00448 ans.source= f.source;
00449 ans.target= this->target;
00450 ans.get_data_from( *a * *b );
00451
00452 return ans;
00453 }
00454
00456 friend ostream& operator<<(ostream& os, const AffineHomomorphism<K>& f){
00457 typename map< long, Polynomial<K> >::const_iterator it;
00458
00459 for(it= f.images.begin(); it!= f.images.end(); it++)
00460 os << f.source->nameof(it->first)
00461 <<" --> " << it->second
00462 << endl << endl;
00463
00464 return os;
00465 }
00466
00468 friend ofstream& operator<<(ofstream& file, AffineHomomorphism<K>& f){
00469 AbstractHomomorphism<K> *g;
00470
00471 g=(AbstractHomomorphism<K> *) &f;
00472 file << *g;
00473 return file;
00474 }
00475
00477 friend void operator>>(ifstream& file, AffineHomomorphism<K>& f){
00478 AbstractHomomorphism<K> *g;
00479
00480 g=(AbstractHomomorphism<K> *) &f;
00481 file >> *g;
00482 f.fix_alphabets();
00483
00484 }
00485
00486
00487
00488
00489 };
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 #endif