00001 #include "unstable.H"
00002 using namespace std;
00003
00004
00005 void UnstableAlgebra::swap_variables_order(long i,
00006 long j,
00007 list< Polynomial<F_2> >& polys){
00008 Tuple< Polynomial<F_2> > dummy;
00009 long a, b;
00010
00011 GradedAlgebra<F_2>::swap_variables_order(i, j, polys);
00012 dummy.steal(steenrod[i]);
00013 steenrod[i].steal( steenrod[j] );
00014 steenrod[j].steal( dummy );
00015
00016 for(a=1; a<= var_in_use; a++)
00017 for(b=0; b<= hom_degrees[a]; b++)
00018 steenrod[a][b].swap_variables(i, j);
00019 }
00020
00021
00022 void UnstableAlgebra::swap_variables_order(long i, long j){
00023 list< Polynomial<F_2> > empty_list;
00024
00025 this->swap_variables_order(i,j,empty_list);
00026 }
00027
00028 void UnstableAlgebra::kill_top_variable(const Polynomial<F_2>& replacement,
00029 list< Polynomial<F_2> >& polys){
00030 long a,b;
00031
00032 GradedAlgebra<F_2>::kill_top_variable(replacement, polys);
00033 steenrod.erase(this->var_in_use + 1);
00034
00035 for(a=1; a<= this->var_in_use; a++)
00036
00037
00038 if(steenrod[a].size() == hom_degrees[a] + 1)
00039 for(b=0; b<= hom_degrees[a]; b++)
00040 steenrod[a][b].substitute_variable(var_in_use + 1, replacement);
00041
00042 }
00043
00044
00045 void UnstableAlgebra::kill_top_variable(const Polynomial<F_2>& replacement){
00046 list< Polynomial<F_2> > empty_list;
00047
00048 this->kill_top_variable(replacement,empty_list);
00049 }
00050
00051
00052 void UnstableAlgebra::fix_alphabets() {
00053
00054 GradedAlgebra<F_2>::fix_alphabets();
00055
00056 long a, b;
00057 for(a=1; a<= var_in_use; a++)
00058 for(b=0; b<= hom_degrees[a]; b++)
00059 steenrod[a][b].alphabet= this;
00060 }
00061
00062
00063
00065 void UnstableAlgebra::write_trivial_steenrod_operations(){
00066 long i, n;
00067 Tuple< Polynomial<F_2> > vars= get_variables();
00068
00069 for(i=1; i<=this->var_in_use; i++){
00070 n= hom_degrees[i];
00071 steenrod[i].resize( n + 1 );
00072 steenrod[i][0]= vars[i];
00073 steenrod[i][n]= vars[i] * vars[i];
00074 }
00075 }
00076
00077
00078 Polynomial<F_2> UnstableAlgebra::Sq(long i,
00079 const Polynomial<F_2>& x) const {
00080
00081 if(i==0)
00082 return x;
00083
00084 long n= hom_degree_of(x);
00085 Polynomial<F_2> ans= x;
00086
00087
00088 if(i < 0 || i > n || ans.is_zero() ){
00089 ans.sets_to_zero();
00090 return ans;
00091 }
00092
00093 Polynomial<F_2> P= ans.lt();
00094 ans+= P;
00095 if( !ans.is_zero() )
00096 return Sq(i, ans) + Sq(i, P);
00097
00098 PowProd pow= P.lp();
00099 long s= pow.nvars();
00100 if(s==0){
00101 ans.sets_to_zero();
00102 return ans;
00103 }
00104
00105 P= Polynomial<F_2>( pow/PowProd(s) );
00106 P.alphabet= (Alphabet *) this;
00107 long k, min, deg;
00108 deg= hom_degrees.find(s)->second;
00109 min= deg > i ? i : deg;
00110 ans.sets_to_zero();
00111
00112 for(k=0; k<= min; k++)
00113 ans+= (steenrod.find(s)->second[k]) * Sq(i-k, P);
00114
00115 return ans;
00116 }
00117
00118 Polynomial<F_2> UnstableAlgebra::Q(long i,
00119 const Polynomial<F_2>& x) const {
00120 long n, j;
00121
00122 if( i < 0 )
00123 return x;
00124 if( i == 0 )
00125 return Sq(1, x);
00126
00127 n= 1;
00128 for(j= 0; j< i; j++)
00129 n*= 2;
00130 return Sq(n, Q(i-1, x)) + Q(i-1, Sq(n, x));
00131 }
00132
00133
00134
00135
00136
00137
00138 void UnstableAlgebra::insert(const Polynomial<F_2>& P,
00139 const string& com,
00140 list< Polynomial<F_2> >& thelist){
00141 list< Polynomial<F_2> >::iterator locit;
00142 list< string >::iterator locitcom;
00143
00144 for(locit= thelist.begin(), locitcom= comments.begin();
00145 locit!= thelist.end();
00146 locit++, locitcom++)
00147 if( hom_degree_of( *locit) >= hom_degree_of(P) )
00148 break;
00149
00150 thelist.insert(locit, P);
00151 comments.insert(locitcom, com);
00152 }
00153
00154
00155
00156 AbstractHomomorphism<F_2> UnstableAlgebra::saturate_and_reduce(){
00157 bool grobner_done;
00158 long nb_relations, current_relation, var;
00159 Polynomial<F_2> rel, P;
00160 list< Polynomial<F_2> > pretty_relations;
00161 list< Polynomial<F_2> >::iterator it;
00162 list< string >::iterator itcom;
00163 AbstractHomomorphism<F_2> ans, temphom;
00164 ostringstream autoname;
00165 long k;
00166
00167
00168 if(verbose)
00169 cout << "{\\bf Now saturating & reducing variables and relations}"
00170 << endl << endl;
00171
00172 grobner_done= false;
00173 ans.make_identity(this->var_in_use);
00174 nb_relations= 0;
00175 current_relation= 1;
00176
00177
00178 pretty_relations.splice(pretty_relations.begin(), relations.generators );
00179 comments.clear();
00180 for(it= pretty_relations.begin(); it!= pretty_relations.end(); it++)
00181 comments.push_back("");
00182
00183
00184
00185 for(it= pretty_relations.begin(), itcom= comments.begin();
00186 it!= pretty_relations.end();){
00187
00188 if( (var= it->has_lonely_variable(rel)) > 0 ){
00189 if(very_verbose)
00190 cout << "relation " << current_relation
00191 << " yields a variable redundancy: $"
00192 << this->nameof(var) << " = " << rel
00193 << "$" << endl << endl;
00194 it= pretty_relations.erase(it);
00195 itcom= comments.erase(itcom);
00196 kill_variable(var, rel, pretty_relations);
00197 grobner_done= false;
00198
00199 rel.swap_variables(var, this->var_in_use + 1);
00200 temphom.make_identity(this->var_in_use + 1);
00201 temphom.set_image(this->var_in_use + 1, Polynomial<F_2>( PowProd(var) ) );
00202 temphom.set_image(var, rel);
00203 ans= temphom * ans;
00204 }
00205 else{
00206
00207 if( !grobner_done ){
00208 find_grobner_basis();
00209 grobner_done= true;
00210 }
00211 rel= reduced_form( *it );
00212 if( !rel.is_zero() ){
00213 nb_relations++;
00214 if(very_verbose)
00215 cout << "adding relation " << current_relation
00216 << " (total " << nb_relations << " relations added): "
00217 << "$" << rel << "$" << endl << endl;
00218 add_relation(rel);
00219 grobner_done= false;
00220
00221
00222 if( *itcom == "" ){
00223 autoname.str("");
00224 autoname << "(" << nb_relations << ")";
00225 *itcom= autoname.str();
00226 }
00227
00228 for(k=1; k < hom_degree_of( *it ); k++){
00229 P= Sq(k, *it);
00230 if( !P.is_zero() ){
00231 autoname.str("");
00232 autoname << "Sq^" << k << *itcom;
00233 insert( P, autoname.str(), pretty_relations );
00234 }
00235 }
00236 it++;
00237 itcom++;
00238 }
00239 else{
00240 if(very_verbose)
00241 cout << "relation " << current_relation << " redundant"
00242 << endl << endl;
00243 it= pretty_relations.erase(it);
00244 itcom= comments.erase(itcom);
00245 }
00246 }
00247 current_relation++;
00248 }
00249
00250 if(verbose)
00251 cout << "{\\bf Final presentation: } "
00252 << var_in_use << " variables kept, "
00253 << nb_relations << " relations kept"
00254 << endl << endl;
00255
00256 relations.generators.clear();
00257 relations.generators.splice( relations.generators.begin(), pretty_relations);
00258 return ans;
00259 }
00260
00261 void UnstableAlgebra::display() const {
00262 list< Polynomial<F_2> >::const_iterator it;
00263 list< string >::const_iterator itcom;
00264 map<long, string>::const_iterator it_gen;
00265 map<long, long>::const_iterator it_deg;
00266
00267
00268 cout << "generators:" << endl << endl;
00269 for(it_gen= names.begin(), it_deg= hom_degrees.begin();
00270 it_gen!= names.end();
00271 it_gen++, it_deg++)
00272 cout << "$" << it_gen->second << "$"
00273 << " of degree "
00274 << it_deg->second << endl << endl;
00275
00276
00277 cout << endl << "relations:" << endl;
00278
00279 for(it= relations.generators.begin(), itcom= comments.begin();
00280 it!= relations.generators.end(); it++, itcom++){
00281 cout << *itcom << " : " << *it << endl << endl;
00282 }
00283
00284
00285 long i, j;
00286
00287 cout << "Steenrod operations:" << endl << endl;
00288 for(i=1; i<= var_in_use; i++)
00289 for(j=1; j< steenrod.find(i)->second.size()-1; j++)
00290 cout << "$Sq^" << j << "(" << nameof(i) << ") = "
00291 << steenrod.find(i)->second[j] << "$" << endl << endl;
00292
00293
00294
00295 }
00296
00297
00298
00299 bool UnstableAlgebra::is_saturated() const {
00300 list< Polynomial<F_2> >::const_iterator it;
00301 long k;
00302
00303 for(it= relations.generators.begin();
00304 it!= relations.generators.end();
00305 it++)
00306 for(k=1; k < hom_degree_of( *it ); k++)
00307 if(!reduced_form( Sq(k, *it) ).is_zero() )
00308 return false;
00309
00310 return true;
00311
00312 }
00313
00314
00315 bool UnstableAlgebra::has_closure_of(const AffineHomomorphism<F_2>& f) const {
00316 long i, k;
00317 Polynomial<F_2> P;
00318
00319 for(i=1; i<= f.source->variables_in_use(); i++) {
00320 P= f.of_generator(i);
00321 for(k=1; k < this->hom_degree_of(P); k++)
00322 if( !f.maps_onto( Sq(k, P) ) ) {
00323 cout << "no! one has Sq^" << k
00324 << "(" << P << ") = "
00325 << Sq(k, P) << " which is not in the image"
00326 << endl;
00327 return false;
00328 }
00329 }
00330 return true;
00331 }
00332
00333
00334
00335
00336
00338
00339 ostream& operator<<(ostream& os, const UnstableAlgebra& A){
00340 const GradedAlgebra<F_2> *ptr;
00341
00342 ptr= &A;
00343 os << *ptr;
00344
00345 long i, j;
00346
00347 os << "Steenrod operations:" << endl << endl;
00348 for(i=1; i<= A.variables_in_use(); i++)
00349 for(j=1; j< A.steenrod.find(i)->second.size()-1; j++)
00350 os << "Sq^" << j << "(" << A.nameof(i) << ") = "
00351 << A.steenrod.find(i)->second[j] << endl << endl;
00352
00353 return os;
00354 }
00355
00356 ofstream& operator<<(ofstream& file, UnstableAlgebra& A){
00357 GradedAlgebra<F_2> *ptr;
00358
00359 ptr= &A;
00360 file << *ptr;
00361
00362
00363 long i, j;
00364
00365 for(i=1; i<= A.variables_in_use(); i++)
00366 for(j=1; j< A.steenrod.find(i)->second.size()-1; j++)
00367 file << A.steenrod[i][j];
00368
00369
00370
00371 list< string >::iterator it;
00372 i= 0;
00373 for(it= A.comments.begin(); it!= A.comments.end(); it++)
00374 i++;
00375 file << i << " ";
00376 for(it= A.comments.begin(); it!= A.comments.end(); it++)
00377 file << *it << " ";
00378
00379 return file;
00380 }
00381
00382 void operator>>(ifstream& file, UnstableAlgebra& A){
00383 GradedAlgebra<F_2> *ptr;
00384
00385 ptr= &A;
00386 file >> *ptr;
00387
00388
00389 A.write_trivial_steenrod_operations();
00390
00391 long i, j;
00392
00393 for(i=1; i<= A.variables_in_use(); i++)
00394 for(j=1; j< A.steenrod.find(i)->second.size()-1; j++)
00395 file >> A.steenrod[i][j];
00396
00397 A.fix_alphabets();
00398
00399
00400 string foo;
00401 A.comments.clear();
00402 file >> i;
00403 while( i>0 ){
00404 file >> foo;
00405 A.comments.push_back( foo );
00406 i--;
00407 }
00408
00409 }