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

exp_classes.H

00001 #ifndef _EXP_CLASSES_H_
00002 #define _EXP_CLASSES_H_
00003 
00004 #include "my_gmp.H"
00005 #include <sstream>
00006 #include <string>
00007 #include "algebras.H"
00008 #include "tables.H"
00009 #include "repring.H"
00010 using namespace std;
00011 
00013 
00023 template <class K>
00024 class Exponentiator {
00025 public:
00026   // source and target *********************************
00027   // ***************************************************
00029   RepresentationRing *source;
00031   GradedAlgebra<K> *target;
00032 
00033   // a bunch of things to do with variables ************
00034   // ***************************************************
00036 
00042   long last_actual_variable;
00044 
00048   long max_dim;
00050 
00060   long max_dim_rel;
00062 
00067   Table< Polynomial<K> > var;
00069 
00088   Tuple< Polynomial<K> > a, b, s, sp;  
00089   // things to do with the relations *******************
00090   // ***************************************************
00092 
00100   list< pair< Polynomial<QQ>, Polynomial<QQ> > > equations;
00102   list< Polynomial<K> > total_relations;
00104   list< Polynomial<K> >  exp_relations;
00105   // misc ********************************************
00106   // *************************************************
00108   long factor;
00109   // some universal polynomials
00111 
00121   map< pair<long, long> , Polynomial<K> > univ_computed;
00123   map< pair<long, long> , Polynomial<K> > lambda_univ_computed;
00124 
00125   //**************************************************
00126   // methods: destructor *****************************
00127   // *************************************************
00128 
00129   virtual ~Exponentiator<K>(){}
00130 
00131 
00132   // variables, set-up **********************
00133   // *************************************************
00134 
00136 
00142 virtual void create_regular_variables(string prefix){
00143     long i, j, dim;
00144     QQ d;
00145     ostringstream autoname;
00146 
00147 
00148     // looks for the largest dimension
00149     dim= 0;
00150     for(i=1; i <= source->variables_in_use(); i++){
00151       d= source->epsilon[i];
00152       if( d > dim)
00153         dim= ZZtolong(d);
00154     }
00155 
00156     max_dim= dim;
00157     var.resize(source->variables_in_use() +1, dim+1);
00158 
00159     //now create the variables and populate var
00160     for(i=1; i <= source->variables_in_use(); i++){
00161 
00162       dim= ZZtolong( source->epsilon[i] );
00163       for(j=1; j<= dim; j++){ 
00164 
00165         autoname.str("");
00166         autoname << prefix << "_" << j
00167                  << "(" << source->nameof(i) << ")";
00168         var(i,j)= target->new_variable(autoname.str(), factor*j);
00169       }
00170     }
00171 
00172   }
00173 
00175 
00188   void create_extra_variables(string prefix){
00189     long i;
00190     ostringstream autoname;
00191 
00192     last_actual_variable= target->variables_in_use();
00193 
00194     a.resize(max_dim+1);
00195     for(i=1; i<= max_dim; i++){
00196       autoname.str("");
00197       autoname << "a_" << i;      
00198       a[i]= target->new_variable(autoname.str(), 1);
00199     }
00200 
00201     b.resize(max_dim_rel+1);
00202     for(i=1; i<= max_dim_rel; i++){
00203       autoname.str("");
00204       autoname << "b_" << i;      
00205       b[i]= target->new_variable(autoname.str(), 1);
00206     }
00207 
00208     s.resize(max_dim+1);
00209     for(i=1; i<= max_dim; i++){
00210       autoname.str("");
00211       autoname << prefix << "_" << i;      
00212       s[i]= target->new_variable(autoname.str(), i);
00213     }
00214 
00215     sp.resize(max_dim_rel+1);
00216     for(i=1; i<= max_dim_rel; i++){
00217       autoname.str("");
00218       autoname << prefix << "'_" << i;      
00219       sp[i]= target->new_variable(autoname.str(), i);
00220     }
00221   }
00222 
00224   void kill_extra_variables(){
00225     long i,n;
00226     Polynomial<K> zero_poly;
00227 
00228     n= target->variables_in_use() - last_actual_variable;
00229     for(i=1; i<= n;i++)
00230       target->kill_top_variable(zero_poly);
00231   }
00232 
00233 
00234 
00235 
00237 
00249   void clean_up_equations(){
00250     Polynomial<QQ> left, right;
00251     Polynomial<QQ> temp, dummy;;
00252     QQ num, den;
00253     ZZ thegcd;
00254     long d, max_dim_pow;
00255     typename list< Polynomial<QQ> >::iterator it;
00256     typename map< PowProd, QQ >::iterator pow_it;
00257 
00258     left.alphabet= source;
00259     right.alphabet= source;
00260     max_dim_pow= 0;
00261 
00262     for(it= source->relations.generators.begin();
00263         it != source->relations.generators.end();
00264         it++){
00265       temp= *it;
00266       thegcd= 0;
00267       for(pow_it= temp.coeffs.begin();
00268           pow_it != temp.coeffs.end();
00269           pow_it ++){
00270         // checks out the dimension of the rep
00271         dummy= Polynomial<QQ>(pow_it->first);
00272         d= ZZtolong(dummy.evaluate(source->epsilon));
00273         if(d > max_dim_pow)
00274           max_dim_pow= d;
00275         // clears up denominators
00276         // (there should not be any anyway)
00277         num= pow_it->second.get_num();
00278         den= pow_it->second.get_den();
00279         temp *= den;
00280         // updates gcp
00281         thegcd= gcd(thegcd, num);
00282         // decides if we write to the LHS or RHS
00283         if(num > 0)
00284           left.add_term(pow_it->first, num);
00285         else
00286           right.add_term(pow_it->first, -num);
00287       }
00288       // divides by gcd
00289       left*= 1/QQ(thegcd);
00290       right*= 1/QQ(thegcd);
00291 
00292       equations.push_back( make_pair( left, right ) );
00293       left.sets_to_zero();
00294       right.sets_to_zero();
00295     }
00296     max_dim_rel= max_dim_pow;    
00297 }
00298 
00299 
00300 
00301 
00302   // methods which do the actual work ***********************
00303   // ********************************************************
00305 
00322   Polynomial<K> compute_tensor_relation(long max_dim1, long max_dim2){
00323     long i, j, deg;
00324     Polynomial<K> P, Q, I, debug;
00325     Tuple< Polynomial<K> > sigma, sigmap;
00326     PowProd pow;
00327     Polynomial<K> ans;
00328     
00329     I= target->one();
00330     
00331     // compute the elementary symmetric functions
00332     // in the a_i's and the b_i's.
00333     sigma.resize(max_dim1 + 1);
00334     sigmap.resize(max_dim2 + 1);
00335     P= I;
00336     Q= I;
00337     debug= I;
00338     for(i=1; i<=max_dim1; i++){
00339       P*= I + a[i];
00340     }
00341     for(i=1; i<=max_dim2; i++){
00342       Q*= I + b[i];
00343     }
00344 
00345     for(i=1; i<=max_dim1; i++){
00346       sigma[i]= target->hom_part_of(P,i);
00347     }
00348     for(i=1; i<=max_dim2; i++){
00349       sigmap[i]= target->hom_part_of(Q,i);
00350     }
00351 
00352     // compute the polynomial that needs to be
00353     // rewritten as a poly in the sigma_i and sigma_i'
00354 
00355     P= I;
00356 
00357     for(i=1; i<=max_dim1; i++)
00358       for(j=1; j<=max_dim2; j++)
00359         P*= I + a[i] + b[j];// done !
00360     
00361     
00362     // do the actual work 
00363     ans=I; // for the alphabet !!
00364     ans.sets_to_zero();
00365 
00366 
00367     while( !P.is_zero() ){
00368 
00369 
00370       pow= P.lp();
00371       
00372       // compute a poly in the sigma_i's with the same lp()
00373      
00374       Q= I;
00375       debug= I;
00376       for(i=1; i<=max_dim1; i++){
00377         deg= pow.power_of(last_actual_variable + max_dim1 + 1 - i);
00378         if(i != max_dim1)       
00379           deg-= pow.power_of(last_actual_variable + max_dim1 - i);
00380         // now multiply Q by sigma[i] to the power deg
00381         for(j=1; j<= deg; j++){
00382           Q *= sigma[i];
00383           debug *= s[i];
00384         }
00385       }
00386       // now same with sigmaprime
00387       for(i=1; i<=max_dim2; i++){
00388         deg= pow.power_of(last_actual_variable + max_dim + max_dim2 + 1 - i);
00389         if(i != max_dim2)       
00390           deg-= pow.power_of(last_actual_variable + max_dim + max_dim2 - i);
00391         // now multiply Q by sigma[i] to the power deg
00392         for(j=1; j<= deg; j++){
00393           Q *= sigmap[i];
00394           debug *= sp[i];
00395         }
00396       }
00397       
00398       //       cout << "le poly obtenu: " << debug << endl;
00399       // cout << "qui developpe donne " << Q << endl;
00400       
00401       ans+= debug*P.coeff_of(pow);
00402       P+= Q*(-1)*P.coeff_of(pow);
00403     }
00404 
00405     return ans;
00406 
00407   }
00409 
00416   void write_lambda_factors(list< Polynomial<K> >& result, long ext, long first, long last){
00417     list< Polynomial<K> > temp1, temp2;
00418     typename list< Polynomial<K> >::iterator it;
00419 
00420 
00421     // trivial cases: ext too small or too large
00422     if( (ext < 1) ){
00423       result.clear();
00424       result.push_front( target->one() );
00425       return;
00426     }
00427   
00428     if(  (ext > last - first + 1) ){
00429       result.clear();
00430       return;
00431     }
00432     
00433     // else...
00434     // use recursion:
00435     write_lambda_factors(result, ext, first + 1, last);
00436     write_lambda_factors(temp2, ext - 1, first + 1, last);
00437     // now add the 'first' variable to the terms
00438     // in temp2
00439     for(it= temp2.begin(); it != temp2.end(); it++)
00440       result.push_back( *it + a[ first ] );
00441     return;
00442 
00443   }
00445 
00448   Polynomial<K> compute_lambda_relation(long ext, long dim){
00449     long i, j, deg;
00450     Polynomial<K> P, Q, I, debug;
00451     Tuple< Polynomial<K> > sigma;
00452     PowProd pow;
00453     Polynomial<K> ans;
00454     list< Polynomial<K> > splits;
00455     typename list< Polynomial<K> >::iterator it;
00456 
00457     I= target->one();
00458 
00459     // compute the elementary symmetric functions
00460     // in the a_i's.
00461     sigma.resize(dim + 1);
00462     P= I;
00463     
00464     for(i=1; i<=dim; i++){
00465       P*= I + a[i];
00466     }
00467 
00468     for(i=1; i<= dim; i++){
00469       sigma[i]= target->hom_part_of(P,i);
00470     }
00471 
00472 
00473     // compute the polynomial that needs to be
00474     // rewritten as a poly in the sigma_i
00475 
00476     write_lambda_factors(splits, ext, 1, dim);
00477     // now just multiply out the factors
00478     
00479     for(P= I, it= splits.begin(); it != splits.end(); it++)
00480       P*= *it;
00481 
00482 
00483     // do the actual work 
00484     ans=I; // for the alphabet !!
00485     ans.sets_to_zero();
00486     
00487     
00488     while( !P.is_zero() ){
00489       
00490       
00491       pow= P.lp();
00492       
00493       // compute a poly in the sigma_i's with the same lp()
00494       
00495       Q= I;
00496       debug= I;
00497       for(i=1; i<=dim; i++){
00498         deg= pow.power_of(last_actual_variable + dim + 1 - i);
00499         if(i != dim)    
00500           deg-= pow.power_of(last_actual_variable + dim - i);
00501         // now multiply Q by sigma[i] to the power deg
00502         for(j=1; j<= deg; j++){
00503           Q *= sigma[i];
00504           debug *= s[i];
00505         }
00506       }
00507         
00508       ans+= debug*P.coeff_of(pow);
00509       P+= Q*(-1)*P.coeff_of(pow);
00510     }
00511    
00512     return ans;
00513   }
00514 
00515 
00516 
00518 
00540   void exp_classes_after_tensoring(const Polynomial<K>& exp,
00541                                    long dim,
00542                                    const PowProd& pow,
00543                                    Polynomial<K>& result) {
00544 
00545     long i, j, d;
00546     PowProd new_pow;
00547     Polynomial<K> universal;
00548    
00549 
00550     if(pow == PowProd(0)){ // trivial case
00551       result= exp;
00552       return;
00553     }
00554     // else...
00555     // let's look at the first variable in pow 
00556     // with positive power;
00557     for(i=1; i<= pow.nvars(); i++)
00558       if( pow.power_of(i) > 0 )
00559         break; //done !
00560     d= ZZtolong(source->epsilon[i]);
00561     // get the universal polynomial for a tensor prod
00562     // already computed?
00563     if( univ_computed.count( make_pair(d,dim) )==0 )
00564       univ_computed[ make_pair(d,dim) ] = compute_tensor_relation(d, dim);
00565     
00566     universal=  univ_computed[ make_pair(d,dim) ] ;
00567     // do the substitutions:
00568     // s[j] gets replaced by var(i,j)
00569     for(j=1; j<= d; j++)
00570       universal.substitute_variable(last_actual_variable + max_dim
00571                                  + max_dim_rel +j, var(i,j) );
00572     // sp[j] gets replaced by hom part of(exp)
00573     for(j=1; j<= dim; j++)
00574       universal.substitute_variable(last_actual_variable + 2*max_dim
00575                                     + max_dim_rel + j, 
00576                                     target->hom_part_of(exp,j*factor));
00577     
00578     // good ! now we have computed the exp classes of the given
00579     // rep tensored with the rep given by variable i in *source.
00580     // now use recursion:
00581     new_pow= pow/PowProd(i);
00582     exp_classes_after_tensoring(universal, d*dim, new_pow, result);
00583     return;
00584   }
00585 
00587 
00599   Polynomial<K> exp_classes_of_ext_power(long thevar, long ext){
00600     long dim, j;
00601     Polynomial<K> universal;
00602 
00603     dim= ZZtolong(source->epsilon[thevar]);
00604 
00605     // get the universal polynomial for an exterior power
00606     // already computed?
00607     if( lambda_univ_computed.count( make_pair(ext,dim) )==0 )
00608       lambda_univ_computed[ make_pair(ext,dim) ] = compute_lambda_relation(ext, dim);
00609     
00610     universal=  lambda_univ_computed[ make_pair(ext,dim) ] ;
00611     // do the substitutions:
00612     // s[j] gets replaced by var(thevar,j)
00613     for(j=1; j<= dim; j++)
00614       universal.substitute_variable(last_actual_variable + max_dim
00615                                  + max_dim_rel +j, var(thevar,j) );
00616     return universal;
00617   }
00618 
00620 
00635   void compute_exp_relations(){
00636     Polynomial<K> templeft, tempright, P, Q;
00637     long i, j, k, n;
00638     typename list< pair< Polynomial<QQ>, Polynomial<QQ> > >::iterator it;
00639     typename map< PowProd, QQ>::iterator it_pow;
00640    
00642     //we go through the multiplicative equations one by one
00643 
00644     if(target->verbose)
00645       cout << endl 
00646            <<"{\\bf Translating the relations}"
00647            << endl << endl;
00648 
00649     for(it= equations.begin(); it!= equations.end(); it++){
00650 
00651       if(target->very_verbose)
00652         cout << "we examine equation $" << it->first
00653              << " = " << it->second 
00654              << "$" << endl << endl;
00655 
00656       templeft= target->one();
00657       tempright= target->one();
00658       //we go through the powprods on the left
00659       for(it_pow= it->first.coeffs.begin();
00660           it_pow!= it->first.coeffs.end();
00661           it_pow++){
00662         // we compute in P the exp classes of the monomial
00663         exp_classes_after_tensoring(target->one(), 1, it_pow->first, P);
00664         // we put this to the appropriate power
00665         n= ZZtolong(it_pow->second);
00666         Q= P;
00667         for(i=2; i<= n; i++)
00668           P*= Q;
00669         //we multiply templeft by P
00670         templeft*= P;
00671       }
00672       //we go through the powprods on the right
00673       for(it_pow= it->second.coeffs.begin();
00674           it_pow!= it->second.coeffs.end();
00675           it_pow++){
00676         // we compute in P the exp classes of the monomial
00677         exp_classes_after_tensoring(target->one(), 1, it_pow->first, P);
00678         // we put this to the appropriate power
00679         n= ZZtolong(it_pow->second);
00680         Q= P;
00681         for(i=2; i<= n; i++)
00682           P*= Q;
00683         //we multiply tempright by P
00684         tempright*= P;
00685       }
00686       // we add the equation templeft-tempright = 0
00687       templeft+= tempright*(-1);
00688       total_relations.push_back(templeft);
00689 
00690       if(target->very_verbose)
00691         cout << "translated into $" << templeft
00692              << " = 0" << "$" << endl << endl;
00693 
00694     }// end of main for loop
00695 
00697     // next, we examine the lambda relations
00698 
00699     for(i= 1; i <= source->variables_in_use(); i++)
00700       for(j= 2; j <= source->epsilon[i]; j++){
00701         // we are now looking at lambda^j( x_i )
00702       if(target->very_verbose)
00703         cout << "we examine equation $\\lambda^" << j
00704              << "(" << source->nameof(i) << ") = "
00705              << source->lambda_operations[i][j] 
00706              << "$" << endl << endl;
00707 
00708 
00709         templeft= exp_classes_of_ext_power(i, j);
00710         tempright= target->one();
00711         // we explore the pows in the expression 
00712         // for lambda^j(x_i) given in *source   
00713         for(it_pow= source->lambda_operations[i][j].coeffs.begin();
00714             it_pow != source->lambda_operations[i][j].coeffs.end();
00715             it_pow++){
00716         exp_classes_after_tensoring(target->one(), 1, it_pow->first, P);
00717         n= ZZtolong( it_pow->second );
00718         if( n < 0 ) // then we multiply templeft by P^-n
00719           for(k=1; k <= -n; k++)
00720             templeft*= P;
00721         else        // we multiply tempright by P^n
00722           for(k=1; k <= n; k++)
00723             tempright*= P;
00724         }
00725       // we add the equation templeft-tempright = 0
00726       templeft+= tempright*(-1);
00727       total_relations.push_back(templeft);
00728 
00729       if(target->very_verbose)
00730         cout << "translated into $" << templeft
00731              << " = 0$" << endl << endl;
00732       }
00733 
00734 
00735 
00736   }
00737 
00738   void split_and_sort(){
00739     long i;
00740     Polynomial<K> P;
00741     typename list< Polynomial<K> >::iterator total_it;
00742     
00744     // now we split the equations in total_relations
00745     // into homogeneous parts, sort them according
00746     // to their degrees, and add them to exp_relations
00747 
00748     if(target->verbose)
00749       cout << endl 
00750            << "{\\bf Now splitting into homogeneous parts}" 
00751            << endl << endl;
00752 
00753     // now we split the relations we have just
00754     // obtained into homogeneous parts, sorted by degree
00755     i= 0;
00756     while( !total_relations.empty() ){
00757       i++;
00758 
00759       if(target->very_verbose)
00760         cout << "adding the relations in degree " << i 
00761              << endl << endl;
00762 
00763       for(total_it= total_relations.begin();
00764           total_it != total_relations.end();){
00765         P= target->hom_part_of(*total_it, i);
00766         if( !P.is_zero() ){
00767           if( target->very_verbose)
00768             cout << "adding $" << P << " = 0$" 
00769                  << endl << endl;
00770           exp_relations.push_back(P);
00771           *total_it += P*(-1);
00772         }
00773         if( total_it->is_zero() )
00774           total_it= total_relations.erase(total_it);
00775         else
00776           total_it++;
00777       }
00778     }// end of WHILE
00779 
00780 
00781 
00782   }
00783 
00784 
00786 
00791   void add_relations(){
00792 
00793     target->relations.generators= exp_relations;
00794     exp_relations.clear();
00795     total_relations.clear();
00796   }
00797 
00799 
00841   void start(RepresentationRing *thesource,
00842              GradedAlgebra<K> *thetarget,
00843              string prefix,
00844              long thefactor){
00845 
00846     source= thesource;
00847     target= thetarget;
00848     factor= thefactor;
00849 
00850     this->create_regular_variables(prefix);
00851     this->clean_up_equations();
00852     this->create_extra_variables(prefix);
00853     this->compute_exp_relations();
00854     this->split_and_sort();
00855     this->kill_extra_variables();
00856     this->add_relations();
00857   }
00858 
00859 };
00860 
00861 
00862 #endif
00863 
00864 
00865 
00866 
00867 
00868 

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