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
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
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
00074
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
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
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
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){
00253 it= coeffs.end();
00254 if( it == coeffs.begin() )
00255 return PowProd( 0 );
00256 else{
00257 it--;
00258 return it->first;
00259 }
00260 }
00261 else{
00262
00263 itprime= coeffs.begin();
00264 it= coeffs.begin();
00265 if( it == coeffs.end() )
00266 return PowProd( 0 );
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
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
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
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 }
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
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
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
00524 if( P.is_zero() ){
00525 os << "0";
00526 return os;
00527 }
00528
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
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
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
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
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