GiNaCRA  0.6.4
Groebner.cpp
Go to the documentation of this file.
00001 /*
00002  * GiNaCRA - GiNaC Real Algebra package
00003  * Copyright (C) 2010-2012  Ulrich Loup, Joachim Redies, Sebastian Junges
00004  *
00005  * This file is part of GiNaCRA.
00006  *
00007  * GiNaCRA is free software: you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation, either version 3 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * GiNaCRA is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with GiNaCRA.  If not, see <http://www.gnu.org/licenses/>.
00019  *
00020  */
00021 
00022 
00023 #include <algorithm>
00024 #include <list>
00025 
00026 #include "Groebner.h"
00027 #include "MultivariatePolynomialMR.h"
00028 
00029 namespace GiNaCRA
00030 {
00031     Groebner::Groebner():
00032         mIsSolved( true ),
00033         mIsReduced( true )
00034     {}
00035 
00036     Groebner::Groebner( const MultivariatePolynomialMR& p1 ):
00037         mIsSolved( true ),
00038         mIsReduced( false )
00039     {
00040         mIdeal.push_back( p1 );
00041         mGB.assign( mIdeal.begin(), mIdeal.end() );
00042     }
00043 
00044     Groebner::Groebner( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ):
00045         mIsSolved( false ),
00046         mIsReduced( false )
00047     {
00048         mIdeal.push_back( p1 );
00049         mIdeal.push_back( p2 );
00050         mIdeal.sort( MultivariatePolynomialMR::sortByLeadingTerm );
00051         mGB.assign( mIdeal.begin(), mIdeal.end() );
00052         fillB();
00053     }
00054 
00055     Groebner::Groebner( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2, const MultivariatePolynomialMR& p3 ):
00056         mIsSolved( false ),
00057         mIsReduced( false )
00058     {
00059         mIdeal.push_back( p1 );
00060         mIdeal.push_back( p2 );
00061         mIdeal.push_back( p3 );
00062         mIdeal.sort( MultivariatePolynomialMR::sortByLeadingTerm );
00063         mGB.assign( mIdeal.begin(), mIdeal.end() );
00064         fillB();
00065 
00066     }
00067 
00068     Groebner::Groebner( std::list<MultivariatePolynomialMR>::iterator begin_generatingset,
00069                         std::list<MultivariatePolynomialMR>::iterator end_generatingset ):
00070         mIsSolved( false ),
00071         mIsReduced( false )
00072     {
00073         mIdeal = std::list<MultivariatePolynomialMR>( begin_generatingset, end_generatingset );
00074         mIdeal.sort( MultivariatePolynomialMR::sortByLeadingTerm );
00075         mGB.assign( mIdeal.begin(), mIdeal.end() );
00076         fillB();
00077     }
00078 
00079     void Groebner::addPolynomial( const MultivariatePolynomialMR& p1 )
00080     {
00081         lpol_It
00082         inputloc = std::lower_bound<lpol_It, MultivariatePolynomialMR>( mGB.begin(), mGB.end(), p1, MultivariatePolynomialMR::sortByLeadingTerm );
00083         inputloc    = mGB.insert( inputloc, p1 );
00084         lpol_It end = mGB.end();
00085         // Add all new pairs
00086         for( lpol_It i = mGB.begin(); i != end; ++i )
00087         {
00088             if( i == inputloc )
00089                 continue;
00090             pairsToBeChecked.push_back( std::make_pair<lpol_cIt, lpol_cIt>( i, inputloc ));
00091 
00092         }
00093 
00094         lpol_It inputlocIdeal = std::lower_bound<lpol_It, MultivariatePolynomialMR>( mIdeal.begin(), mIdeal.end(), p1,
00095                                                                                      MultivariatePolynomialMR::sortByLeadingTerm );
00096         mIdeal.insert( inputlocIdeal, p1 );
00097 
00098         mIsReduced = false;
00099     }
00100 
00101     void Groebner::solve()
00102     {
00103         while( !pairsToBeChecked.empty() )
00104         {
00105             std::pair<lpol_cIt, lpol_cIt> p = pairsToBeChecked.front();
00106             pairsToBeChecked.pop_front();
00107 
00108             //   std::cout << "(i,j) =  ("<< *(p.first) << ", " << *(p.second) << ")"<< std::endl;
00109             MultivariatePolynomialMR r = MultivariatePolynomialMR::SPol( *(p.first), *(p.second) );
00110             //    std::cout << "Spol " <<r << std::endl;
00111             MultivariatePolynomialMR rem = MultivariatePolynomialMR::SPol( *(p.first), *(p.second) ).CalculateRemainder( mGB.begin(), mGB.end() );
00112             //     std::cout << "Remainder " << rem << std::endl;
00113 
00114             // If the remainder is not zero, we will add it to the ideal
00115             if( rem.isConstant() )
00116             {
00117                 mGB.clear();
00118                 mGB.push_back( rem );
00119                 mIsSolved  = true;
00120                 mIsReduced = true;
00121                 return;
00122             }
00123 
00124             if( !rem.isZero() )
00125             {
00126                 addPolynomial( rem );
00127             }
00128 
00129         }
00130     }
00131 
00132     void Groebner::reduce()
00133     {
00134         bool solved;
00135         if( pairsToBeChecked.empty() )
00136             solved = true;
00137         if( mIsReduced )
00138             return;
00139         // Minimize (faster than the reduction algorithm)
00140         for( lpol_It i = mGB.begin(); i != mGB.end(); )
00141         {
00142             bool div = false;
00143             for( lpol_It j = mGB.begin(); j != i &&!div; ++j )
00144             {
00145                 div = i->lterm().dividable( j->lterm() );
00146             }
00147 
00148             lpol_It j = i;
00149             ++j;
00150             for( ; !div && j != mGB.end(); ++j )
00151             {
00152                 div = i->lterm().dividable( j->lterm() );
00153             }
00154 
00155             if( div )
00156             {
00157                 i = mGB.erase( i );
00158             }
00159             else
00160             {
00161                 ++i;
00162             }
00163         }
00164         // Calculate reduction
00165         // The number of polynomials will not change anymore!
00166         std::list<MultivariatePolynomialMR> reduced;
00167         lpol_It i = mGB.begin();
00168         reduced.push_back( i->normalized() );
00169         for( ++i; i != mGB.end(); ++i )
00170         {
00171             reduced.push_back( i->CalculateRemainder( reduced.begin(), reduced.end() ).normalized() );
00172         }
00173         mGB.swap( reduced );
00174 
00175         if( solved )
00176         {
00177             mIsReduced = true;
00178         }
00179         else
00180         {
00181             fillB();
00182         }
00183     }
00184 
00185     void Groebner::fillB()
00186     {
00187         for( lpol_cIt i = mGB.begin(); i != mGB.end(); ++i )
00188         {
00189             for( lpol_cIt j = i; j != mGB.end(); ++j )
00190             {
00191                 if( i == j )
00192                     continue;
00193                 pairsToBeChecked.push_back( std::pair<lpol_cIt, lpol_cIt>( i, j ));
00194             }
00195         }
00196     }
00197 
00202     bool Groebner::hasBeenReduced() const
00203     {
00204         if( mIdeal.size() != mGB.size() )
00205             return true;
00206 
00207         return !std::equal( mIdeal.begin(), mIdeal.end(), mGB.begin() );
00208 
00209     }
00210 
00211 }