GiNaCRA
0.6.4
|
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 }