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

polynomials.H

Go to the documentation of this file.
00001 
00012 #ifndef _POLYNOMIALS_H_
00013 #define _POLYNOMIALS_H_
00014 
00015 #include "powerprod.H"
00016 #include <map>
00017 #include <iostream>
00018 #include <fstream>
00019 using namespace std;
00020 
00021 
00022 // a silly little something
00023 template <class K>
00024 K _raise_to_power(K c, long n){
00025   K ans;
00026 
00027   ans= 1;
00028   for(long i=1; i<= n;i++)
00029     ans*= c;
00030 
00031   return ans;
00032 }
00033 
00035 
00042 template <class K> class Polynomial {
00043 private:
00045 
00048   static int order_override;
00049   static long variable_priority;
00050 
00051 public:
00053   Alphabet *alphabet;
00055   map<PowProd, K> coeffs;
00056 
00057   // constructors *******************************************
00058   //*********************************************************
00059   Polynomial<K>(){
00060     alphabet= PowProd::get_default_alphabet();
00061   }
00062 
00063   Polynomial<K>(const Polynomial<K>& that){
00064     coeffs= that.coeffs;
00065     alphabet= that.alphabet;
00066   }
00068   Polynomial<K>(const PowProd& pow){
00069     coeffs[pow]=1;
00070     alphabet= PowProd::get_default_alphabet();
00071   }
00072 
00073   // methods to handle the static data, 
00074   //order_override and variable_priority ************************
00075   //*************************************************************
00076   static void set_order_override(int theorder){
00077     order_override= theorder;
00078   }
00079 
00080   static void default_order(){
00081     order_override= 0;
00082   }
00083 
00084   static int get_order_override(){
00085     return order_override;
00086   }
00087 
00088   static void set_variable_priority(long thepriority){
00089     variable_priority= thepriority;
00090   }
00091 
00092   static void no_variable_priority(){
00093     variable_priority= 0;
00094   }
00095 
00096   static long get_variable_priority(){
00097     return variable_priority;
00098   }
00099 
00100   // a few things to do with the polynomial being 0 ******************
00101   //*******************************************************************
00103   bool is_zero() const {
00104     typename map<PowProd,K>::const_iterator it;
00105     
00106     it=coeffs.begin();
00107     return (it == coeffs.end());
00108   }
00110   void sets_to_zero() {
00111     coeffs.clear();
00112   }
00113 
00114   // some checks for variables showing up *****************************
00115   //*******************************************************************
00117   bool involves_variable(long i) const {
00118     typename map<PowProd,K>::const_iterator it;
00119 
00120     for(it= coeffs.begin(); it!= coeffs.end(); it++)
00121       if( it->first.power_of(i) > 0 )
00122         return true;
00123 
00124     return false;
00125   }
00126 
00128   long nvars() const {
00129     long ans=0;
00130     typename map<PowProd,K>::const_iterator it;
00131 
00132     for(it= coeffs.begin(); it!= coeffs.end(); it++)
00133       if(it->first.nvars() > ans)
00134         ans= it->first.nvars();
00135 
00136     return ans;
00137   }
00138 
00139 
00141 
00150   long has_lonely_variable(Polynomial<K>& replacement){
00151     typename map<PowProd,K>::const_iterator it;
00152     long var;
00153 
00154     for(it= coeffs.begin(); it!= coeffs.end(); it++){
00155       if( it->first.degree()==1 ){
00156         var= it->first.nvars();
00157         replacement= *this;
00158         replacement.add_term( it->first, - it->second);
00159         if(!replacement.involves_variable(var)){
00160           replacement*= (-1/it->second);
00161           return var;
00162         }
00163       }
00164     }
00165 
00166     return 0;
00167   }
00168 
00169 
00171 
00181   long has_unitary_variable(Polynomial<K>& replacement){
00182     typename map<PowProd,K>::const_iterator it;
00183     long var;
00184 
00185     for(it= coeffs.begin(); it!= coeffs.end(); it++){
00186       if( it->first.degree()==1 && (it->second == 1 || it->second == -1) ){
00187         var= it->first.nvars();
00188         replacement= *this;
00189         replacement.add_term( it->first, - it->second);
00190         if(!replacement.involves_variable(var)){
00191           replacement*= (-1/it->second);
00192           return var;
00193         }
00194       }
00195     }
00196 
00197     return 0;
00198   }
00199 
00200 
00201 
00202 
00203   // returning information on the polynomial **************************
00204   //*******************************************************************
00206 
00213   K coeff_of(const PowProd& pow) const {
00214     typename map<PowProd,K>::const_iterator it;
00215 
00216     it= coeffs.find(pow);
00217     if( it != coeffs.end() )
00218       return it->second;
00219     else 
00220       return 0;
00221   }
00223 
00249   PowProd lp() const {
00250     typename map<PowProd,K>::const_iterator it, itprime;
00251 
00252     if( order_override == 0){// default: we return the last powprod
00253       it= coeffs.end(); // this is the leading powprod with respect
00254       if( it == coeffs.begin() ) // to the order specified by
00255         return PowProd( 0 ); // PowProd::order.
00256       else{
00257         it--;
00258         return it->first;
00259       }
00260     }
00261     else{ // using an alternative order
00262     
00263       itprime= coeffs.begin();
00264       it= coeffs.begin();
00265       if( it == coeffs.end() )
00266         return PowProd( 0 ); // return 1 if poly is zero
00267       
00268 
00269       for(it++; it != coeffs.end(); it++){
00270         if( powprod_compare(itprime->first, it->first, order_override, variable_priority) )
00271           itprime= it;
00272       }
00273 
00274       return itprime->first;
00275       }
00276   }
00277 
00278 
00280   Polynomial<K> lt() const {
00281     PowProd leading;
00282     Polynomial<K> ans;
00283     
00284     leading= lp();
00285     ans= Polynomial<K>( leading );
00286     ans.alphabet= this->alphabet;
00287     ans*= coeff_of( leading );
00288     return ans;
00289   }
00290 
00292   K lc() const {
00293     return coeff_of( lp() );    
00294   }
00295 
00296 
00297 
00298 
00299   // arithmetic, operators *****************************************
00300   //*******************************************************************
00301 
00303   void add_term(const PowProd& pow, const K& c){
00304 
00305     if( coeffs.count( pow ) == 0)
00306       coeffs[pow]=c;
00307     else
00308       coeffs[pow]+=c;
00309     if(coeffs[pow] == 0)
00310       coeffs.erase(pow);
00311   }
00312 
00313   Polynomial<K>& operator+=(const Polynomial<K>& that){
00314     typename map<PowProd,K>::const_iterator it;
00315 
00316     for(it= that.coeffs.begin(); it != that.coeffs.end(); it++)
00317       add_term(it->first, it->second);      
00318 
00319     return *this;
00320   }
00321 
00322  Polynomial<K> operator+(const Polynomial<K>& that) const {
00323    Polynomial<K> ans;
00324 
00325    ans= *this;
00326    ans+=that;
00327    return ans;
00328 
00329  }
00330 
00331 
00332  
00334   Polynomial<K>& operator*=(const K& c){
00335     typename map<PowProd,K>::const_iterator it;
00336 
00337     if( c == 0 )
00338       sets_to_zero();
00339     else{
00340       for(it=coeffs.begin(); it != coeffs.end(); it++)
00341         coeffs[it->first] *= c;
00342     }
00343 
00344     return *this;
00345   }
00346 
00347   friend void polyprod(const Polynomial<K>& P, const Polynomial<K>& Q, Polynomial<K>& R){
00348     PowProd pow;
00349     K c;
00350     typename map<PowProd,K>::const_iterator i_this, i_that;
00351 
00352     R.coeffs.clear();
00353     for(i_this= P.coeffs.begin(); i_this != P.coeffs.end(); i_this ++)
00354       for(i_that=Q.coeffs.begin(); i_that != Q.coeffs.end(); i_that++){
00355         pow= i_this->first;
00356         pow *= i_that->first;
00357         c= i_this->second;
00358         c*= i_that->second;
00359         R.add_term(pow,c);
00360       }
00361     R.alphabet= P.alphabet;
00362   }
00363 
00364   Polynomial<K> operator*(const Polynomial<K>& that) const {
00365     Polynomial<K> ans;
00366 
00367     polyprod(*this, that, ans);
00368     return ans;
00369   }
00370 
00371   Polynomial<K>& operator*=(const Polynomial<K>& that){
00372     Polynomial<K> temp;
00373 
00374     polyprod(*this, that, temp);
00375     coeffs= temp.coeffs;   
00376 
00377     return *this;
00378   }
00379 
00380 
00381   Polynomial<K> operator*(const K& c) const {
00382     Polynomial<K> ans;
00383     
00384     ans= *this;
00385     ans *= c;
00386     return ans;
00387   }
00388   
00389   // a couple of things related to substitutions *********************
00390   //*******************************************************************
00392   void swap_variables(long i, long j){
00393     typename map<PowProd,K>::const_iterator it;
00394     Polynomial<K> temp;
00395     PowProd pow;
00396     
00397     for(it= coeffs.begin(); it != coeffs.end(); it++){
00398       pow= it->first;
00399       pow.swap(i,j);
00400       temp.add_term(pow, it->second);
00401     }
00402 
00403     coeffs= temp.coeffs;
00404   }
00405 
00407   void shift_variables(long n){
00408     typename map<PowProd,K>::const_iterator it;
00409     Polynomial<K> temp;
00410     PowProd pow;
00411     
00412     for(it= coeffs.begin(); it != coeffs.end(); it++){
00413       pow= it->first;
00414       pow.shift(n);
00415       temp.add_term(pow, it->second);
00416     }
00417     
00418     coeffs= temp.coeffs;
00419   }
00420 
00421 
00422 
00423   void substitute_variable(long i, const Polynomial<K>& f) {
00424     Tuple< Polynomial<K> > computed;
00425     long max_degree, n;
00426     typename map<PowProd,K>::const_iterator it;
00427     Polynomial<K> ans;
00428     PowProd pow;
00429 
00430     max_degree= 0;
00431     for(it= coeffs.begin(); it != coeffs.end(); it++){
00432       n= it->first.power_of(i);
00433       if(n > max_degree)
00434         max_degree= n;
00435     }
00436 
00437     if(max_degree==0)
00438       return;
00439 
00440     // first set computed[n]=f^n
00441     computed.resize(max_degree + 1);
00442     computed[1]= f;
00443     for(n=2; n <= max_degree; n++)
00444       computed[n]= f * computed[n-1]; 
00445 
00446     for(it= coeffs.begin(); it != coeffs.end(); it++){
00447       n= it->first.power_of(i);
00448       if(n==0)
00449         ans.add_term(it->first, it->second);
00450       else{
00451         pow= it->first;
00452         pow/=PowProd(i,n);
00453         ans+= computed[n] * Polynomial<K>( pow ) * it->second;
00454       }
00455     }// end of for
00456 
00457     coeffs= ans.coeffs;
00458   }
00459 
00461   K evaluate(const map<long,K>& augmentation) const {
00462     K ans, a, b;
00463     long i;
00464     typename map<PowProd,K>::const_iterator it;
00465     
00466     ans= 0;
00467     for(it= coeffs.begin(); it != coeffs.end(); it++){
00468       a= it->second;      
00469       for(i=1; i<= it->first.nvars(); i++){
00470         b= augmentation.find(i)->second;
00471         a*= _raise_to_power(b,it->first.power_of(i));
00472       }
00473       ans += a;
00474     }
00475 
00476     return ans;
00477   }
00478 
00479   // friends, creating polynomials ***********************************
00480   //*******************************************************************
00481   // creates a one-letter polynomial on a variable with specified name
00482   /*
00483    * See alphabet.H for an example of code using this.
00484    * DELETED! becomes ambiguous when several K's are
00485    * used in the same program.
00486    */
00487   /*
00488   friend Polynomial<K> new_indeterminate(SimpleAlphabet& alpha, const string& name){
00489     Polynomial<K> ans;
00490 
00491     ans= Polynomial<K>( PowProd( alpha.new_variable(name) ) );
00492     ans.alphabet= &alpha;
00493 
00494     return ans;
00495   }
00496   // returns the constant polynomial, equal to 1, on the alphabet alpha.
00497   friend Polynomial<K> constant_polynomial(const SimpleAlphabet& alpha){
00498     Polynomial<K> ans;
00499 
00500     ans= Polynomial<K>( PowProd(0) );
00501     ans.alphabet= (Alphabet*) &alpha;
00502 
00503     return ans;
00504   }
00505   */
00506   // friends printing **************************************************
00507   //*******************************************************************
00509 
00515   friend ostream& operator<<(ostream& os, const Polynomial<K>& P){
00516     
00517     typename map<PowProd,K>::const_iterator it;
00518     Alphabet *temp;
00519 
00520     temp= PowProd::get_current_alphabet();
00521     PowProd::set_alphabet(P.alphabet);
00522     
00523     // prints 0 if the polynomial is 0...
00524     if( P.is_zero() ){
00525       os << "0";
00526       return os;
00527     }
00528     // else...
00529     for(it=P.coeffs.begin(); it != P.coeffs.end();){
00530       if( it-> second != 1)
00531         os << it->second;
00532       os << it->first;
00533 
00534       //it->first.debug();
00535 
00536       if( (++it) != P.coeffs.end() )
00537         os << " + ";
00538     }
00539     PowProd::set_alphabet(temp);
00540     return os;
00541   }
00542 
00544   friend ofstream& operator<<(ofstream& file, Polynomial<K>& P){
00545     typename map< PowProd, K >::iterator it;
00546     K scalar;
00547     PowProd pow;
00548     
00549     
00550     for(it= P.coeffs.begin(); it!= P.coeffs.end(); it++){
00551       scalar= it->second;
00552       pow= it->first;
00553       file << scalar;
00554       file << " ";
00555       file << pow;
00556     }
00557     
00558     file << 0 << " ";
00559     return file;
00560   }
00561   
00563   friend void operator>>(ifstream& file, Polynomial<K>& P){
00564     PowProd pow;
00565     K scalar;
00566     
00567     P.coeffs.clear();
00568     
00569     file >> scalar;
00570 
00571     while( scalar != 0){
00572       file >> pow;
00573       P.add_term(pow, scalar);
00574       file >> scalar;
00575 
00576     }
00577     
00578   }
00579 
00580 
00581 
00582 
00583   // friend computing the S polynomial ********************************
00584   //*******************************************************************
00585 
00587   friend Polynomial<K> S_polynomial(const Polynomial<K>& f, const Polynomial<K>& g){
00588     PowProd a,b,c;
00589     K lambda, mu;
00590     Polynomial<K> ans, temp;
00591 
00592     a= f.lp(); 
00593     b= g.lp(); 
00594     c= lcm(a,b); 
00595     lambda= 1 / f.lc();
00596     mu= -1 / g.lc();
00597     a= c/a; 
00598     b= c/b; 
00599     // ans = f*a*lambda + g*b*mu
00600     ans= f; 
00601     ans*= Polynomial<K>( a ); 
00602     ans*= lambda; 
00603     temp= g; 
00604     temp*= Polynomial<K>( b ); 
00605     temp*= mu; 
00606     ans+= temp; 
00607     ans.alphabet= f.alphabet;
00608     
00609     return ans;
00610   }
00616   friend Polynomial<K> S_polynomial_with_coefficients(const Polynomial<K>& f, 
00617                                                       const Polynomial<K>& g,
00618                                                       pair< Polynomial<K>, Polynomial<K> >& coeffs){
00619     PowProd a,b,c;
00620     K lambda, mu;
00621     Polynomial<K> ans, temp;
00622 
00623     a= f.lp(); 
00624     b= g.lp(); 
00625     c= lcm(a,b); 
00626     lambda= 1 / f.lc();
00627     mu= -1 / g.lc();
00628     a= c/a; 
00629     b= c/b; 
00630     // ans = f*a*lambda + g*b*mu
00631     coeffs.first= Polynomial<K>(a) * lambda;
00632     coeffs.first.alphabet= f.alphabet;
00633     coeffs.second= Polynomial<K>(b) * mu;
00634     coeffs.second.alphabet= f.alphabet;
00635     ans= f * coeffs.first + g * coeffs.second; 
00636     ans.alphabet= f.alphabet;
00637     
00638     return ans;
00639  }
00640   
00641   
00642 };
00643 
00644 template <class K> int Polynomial<K>::order_override=0;
00645 template <class K> long Polynomial<K>::variable_priority=0;
00646 
00647 
00648 #endif
00649 
00650 
00651 
00652 
00653 
00654 
00655 

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