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 00029 #ifndef GINACRA_CAD_H 00030 #define GINACRA_CAD_H 00031 00032 //#define GINACRA_CAD_DEBUG 00033 00034 #include <unordered_map> 00035 00036 #include "tree.h" 00037 #include "settings.h" 00038 #include "Constraint.h" 00039 #include "UnivariatePolynomialSet.h" 00040 #include "RealAlgebraicNumber.h" 00041 #include "RealAlgebraicNumberFactory.h" 00042 #include "RealAlgebraicPoint.h" 00043 00044 namespace GiNaCRA 00045 { 00047 // TYPES // 00049 00050 typedef std::unordered_map<RealAlgebraicNumberPtr, RealAlgebraicNumberPtr, RealAlgebraicNumberPtrHasher> SampleSimplification; 00051 00059 struct SampleList: 00060 public std::list<RealAlgebraicNumberPtr> 00061 { 00062 private: 00064 list<RealAlgebraicNumberPtr> mQueue; 00067 pair<list<RealAlgebraicNumberNRPtr>, list<RealAlgebraicNumberIRPtr> > mNRsIRs; 00070 pair<list<RealAlgebraicNumberPtr>, list<RealAlgebraicNumberPtr> > mNonrootsRoots; 00071 00072 public: 00073 00082 pair<iterator, bool> insert( const RealAlgebraicNumberPtr& r ) 00083 { 00084 RealAlgebraicNumberNRPtr rNR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( r ); 00085 std::list<RealAlgebraicNumberPtr>::iterator position = this->begin(); 00086 if( !this->empty() ) 00087 { 00088 position = std::lower_bound( position, this->end(), r, RealAlgebraicNumberFactory::less ); 00089 if( position != this->end() && RealAlgebraicNumberFactory::equal( *position, r )) // already contained in the list 00090 return pair<std::list<RealAlgebraicNumberPtr>::iterator, bool>( position, false ); // return iterator to the already contained element 00091 // else: append r to the end of the list 00092 } 00093 if( rNR != 0 ) 00094 mNRsIRs.first.push_back( rNR ); 00095 else // r is numerically represented 00096 mNRsIRs.second.push_back( std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( r )); 00097 if( r->isRoot() ) 00098 mNonrootsRoots.second.push_back( r ); 00099 else 00100 mNonrootsRoots.first.push_back( r ); 00101 mQueue.push_back( r ); 00102 return pair<std::list<RealAlgebraicNumberPtr>::iterator, bool>( std::list<RealAlgebraicNumberPtr>::insert( position, r ), true ); // insert safely and return iterator to the new element 00103 } 00104 00111 template<class InputIterator> 00112 void insert( InputIterator first, InputIterator last ) 00113 { 00114 for( InputIterator i = first; i != last; ++i ) 00115 insert( *i ); 00116 } 00117 00123 void insert( const SampleList& l ) 00124 { 00125 this->insert( l.begin(), l.end() ); 00126 } 00127 00133 SampleList::iterator remove( SampleList::iterator position ) 00134 { 00135 assert( position != this->end() ); 00136 removeFromQueue( *position ); 00137 removeFromNRIR( *position ); 00138 removeFromNonrootRoot( *position ); 00139 return this->erase( position ); 00140 } 00141 00147 inline const RealAlgebraicNumberPtr next() 00148 { 00149 if( this->empty() ) 00150 assert( false ); // do not call next on empty lists 00151 return mQueue.front(); 00152 } 00153 00161 inline const RealAlgebraicNumberPtr nextNR() 00162 { 00163 if( this->empty() ) 00164 assert( false ); // do not call next on empty lists 00165 if( mNRsIRs.first.empty() ) // only IRs left 00166 return mNRsIRs.second.front(); 00167 return mNRsIRs.first.front(); // return NR 00168 } 00169 00175 inline const RealAlgebraicNumberPtr nextNonroot() 00176 { 00177 if( this->empty() ) 00178 assert( false ); // do not call next on empty lists 00179 if( mNonrootsRoots.first.empty() ) // only roots left 00180 return mNonrootsRoots.second.front(); 00181 return mNonrootsRoots.first.front(); // return non-root 00182 } 00183 00189 inline const RealAlgebraicNumberPtr nextRoot() 00190 { 00191 if( this->empty() ) 00192 assert( false ); // do not call next on empty lists 00193 if( mNonrootsRoots.second.empty() ) // only non-roots left 00194 return mNonrootsRoots.first.front(); 00195 return mNonrootsRoots.second.front(); // return root 00196 } 00197 00202 void pop() 00203 { 00204 #ifdef GINACRA_CAD_DEBUG 00205 cout << "pop()" << endl; 00206 #endif 00207 if( this->empty() ) 00208 return; // nothing to pop 00209 RealAlgebraicNumberPtr r = this->next(); 00210 list<RealAlgebraicNumberPtr>::iterator position = std::lower_bound( this->begin(), this->end(), r, RealAlgebraicNumberFactory::less ); 00211 if( position != this->end() ) // found in the list 00212 this->erase( position ); // remove next() 00213 else 00214 assert( false ); // r should be in this list 00215 mQueue.pop_front(); 00216 removeFromNRIR(r); 00217 removeFromNonrootRoot(r); 00218 } 00219 00224 void popNR() 00225 { 00226 #ifdef GINACRA_CAD_DEBUG 00227 cout << "popNR()" << endl; 00228 #endif 00229 if( this->empty() ) 00230 return; // nothing to pop 00231 RealAlgebraicNumberPtr r = this->nextNR(); 00232 list<RealAlgebraicNumberPtr>::iterator position = std::lower_bound( this->begin(), this->end(), r, RealAlgebraicNumberFactory::less ); 00233 if( position != this->end() ) // found in the list 00234 this->erase( position ); // remove nextNR() 00235 else 00236 assert( false ); // r should be in this list 00237 // remove next also from its bucket 00238 if( mNRsIRs.first.empty() ) // only IRs left, so pop from them 00239 mNRsIRs.second.pop_front(); 00240 else // NRs left, so pop from them 00241 mNRsIRs.first.pop_front(); 00242 removeFromNonrootRoot(r); 00243 removeFromQueue(r); 00244 } 00245 00250 void popNonroot() 00251 { 00252 #ifdef GINACRA_CAD_DEBUG 00253 cout << "popNonroot()" << endl; 00254 #endif 00255 if( this->empty() ) 00256 return; // nothing to pop 00257 RealAlgebraicNumberPtr r = this->nextNonroot(); 00258 list<RealAlgebraicNumberPtr>::iterator position = std::lower_bound( this->begin(), this->end(), r, RealAlgebraicNumberFactory::less ); 00259 if( position != this->end() ) // found in the list 00260 this->erase( position ); // remove nextNonroot() 00261 else 00262 assert( false ); // r should be in this list 00263 // remove next from its bucket 00264 if( mNonrootsRoots.first.empty() ) // only roots left 00265 mNonrootsRoots.second.pop_front(); 00266 else 00267 mNonrootsRoots.first.pop_front(); 00268 removeFromNRIR(r); 00269 removeFromQueue(r); 00270 } 00271 00276 void popRoot() 00277 { 00278 #ifdef GINACRA_CAD_DEBUG 00279 cout << "popRoot()" << endl; 00280 #endif 00281 if( this->empty() ) 00282 return; // nothing to pop 00283 RealAlgebraicNumberPtr r = this->nextRoot(); 00284 list<RealAlgebraicNumberPtr>::iterator position = std::lower_bound( this->begin(), this->end(), r, RealAlgebraicNumberFactory::less ); 00285 if( position != this->end() ) // found in the list 00286 this->erase( position ); // remove nextNonroot() 00287 else 00288 assert( false ); // r should be in this list 00289 // remove next from its bucket 00290 if( mNonrootsRoots.second.empty() ) // only non-roots left 00291 mNonrootsRoots.first.pop_front(); 00292 else 00293 mNonrootsRoots.second.pop_front(); 00294 removeFromNRIR(r); 00295 removeFromQueue(r); 00296 } 00297 00305 pair< SampleSimplification, bool> simplify() 00306 { 00307 pair< SampleSimplification, bool> simplification = pair< SampleSimplification, bool>(); 00308 simplification.second = false; 00309 for( list<RealAlgebraicNumberIRPtr>::iterator irIter = mNRsIRs.second.begin(); irIter != mNRsIRs.second.end(); ) 00310 { 00311 if( !(*irIter)->isNumeric() && (*irIter)->refinementCount() == 0 ) // try at least one refinement 00312 (*irIter)->refine(); 00313 if( (*irIter)->isNumeric() ) 00314 { 00315 #ifdef GINACRA_CAD_DEBUG 00316 cout << "FOUND numeric in "; 00317 print( *irIter, cout ); 00318 #endif 00319 RealAlgebraicNumberPtr r = std::tr1::dynamic_pointer_cast<RealAlgebraicNumber>( *irIter ); 00320 RealAlgebraicNumberNRPtr rNR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( *irIter ); 00321 if( rNR != 0 ) // already simplified! 00322 continue; 00323 RealAlgebraicNumberNRPtr nr = RealAlgebraicNumberNRPtr( new RealAlgebraicNumberNR( (*irIter)->value(), (*irIter)->isRoot() )); 00324 #ifdef GINACRA_CAD_DEBUG 00325 cout << "SIMP: replacing " << **irIter << " by " << *nr << endl; 00326 #endif 00327 // store simplification result 00328 simplification.first[r] = nr; 00329 simplification.second = true; 00330 // add to NRs 00331 mNRsIRs.first.push_back( nr ); 00332 // erase in IRs 00333 irIter = mNRsIRs.second.erase( irIter ); 00334 // replace in basic list 00335 list<RealAlgebraicNumberPtr>::iterator position = std::lower_bound( this->begin(), this->end(), r, 00336 RealAlgebraicNumberFactory::less ); 00337 if( position != this->end() ) // found in the list 00338 *position = nr; // replace ir by nr 00339 else 00340 assert( false ); // there must be an occurrence in the sample list or there was an error inserting the number 00341 // replace in root/non-root lists 00342 if( nr->isRoot() ) 00343 { 00344 position = std::find( mNonrootsRoots.second.begin(), mNonrootsRoots.second.end(), r ); 00345 if( position != mNonrootsRoots.second.end() ) // found in the list 00346 *position = nr; // replace ir by nr 00347 else 00348 assert( false ); // there must be an occurrence in the sample list or there was an error inserting the number 00349 } 00350 else 00351 { 00352 position = std::find( mNonrootsRoots.first.begin(), mNonrootsRoots.first.end(), r ); 00353 if( position != mQueue.end() ) // found in the list 00354 *position = nr; // replace ir by nr 00355 else 00356 assert( false ); // there must be an occurrence in the sample list or there was an error inserting the number 00357 } 00358 // replace in queue 00359 position = std::find( mQueue.begin(), mQueue.end(), r ); 00360 if( position != mQueue.end() ) // found in the list 00361 *position = nr; // replace ir by nr 00362 else 00363 assert( false ); // there must be an occurrence in the sample list or there was an error inserting the number 00364 } 00365 else 00366 ++irIter; 00367 } 00368 return simplification; 00369 } 00370 00375 bool contains( RealAlgebraicNumberPtr r ) const 00376 { 00377 std::list<RealAlgebraicNumberPtr>::const_iterator position = std::lower_bound( this->begin(), this->end(), r, RealAlgebraicNumberFactory::less ); 00378 return position != this->end(); 00379 } 00380 00385 bool emptyNR() const 00386 { 00387 return mNRsIRs.first.empty(); 00388 } 00389 00394 bool emptyIR() const 00395 { 00396 return mNRsIRs.second.empty(); 00397 } 00398 00403 bool emptyNonroot() const 00404 { 00405 return mNonrootsRoots.first.empty(); 00406 } 00407 00412 bool emptyRoot() const 00413 { 00414 return mNonrootsRoots.second.empty(); 00415 } 00416 00417 private: 00418 00420 // AUXILIARY METHODS // 00422 00423 void removeFromNonrootRoot( RealAlgebraicNumberPtr r ) 00424 { 00425 if( r->isRoot() ) 00426 { 00427 list<RealAlgebraicNumberPtr>::iterator pos = std::find( mNonrootsRoots.second.begin(), mNonrootsRoots.second.end(), r ); // find in roots non-root list 00428 if( pos != mNonrootsRoots.second.end() ) 00429 mNonrootsRoots.second.erase( pos ); 00430 else 00431 assert( false ); // r is marked as root 00432 } 00433 else 00434 { 00435 list<RealAlgebraicNumberPtr>::iterator pos = std::find( mNonrootsRoots.first.begin(), mNonrootsRoots.first.end(), r ); // find in roots non-root list 00436 if( pos != mNonrootsRoots.first.end() ) 00437 mNonrootsRoots.first.erase( pos ); 00438 else 00439 assert( false ); // r is marked as root 00440 } 00441 } 00442 00443 void removeFromQueue( RealAlgebraicNumberPtr r ) 00444 { 00445 // remove from queue 00446 list<RealAlgebraicNumberPtr>::iterator pos = std::find( mQueue.begin(), mQueue.end(), r ); // find in roots non-root list 00447 if( pos != mQueue.end() ) 00448 mQueue.erase( pos ); 00449 else 00450 assert( false ); // r is marked as root 00451 } 00452 00453 void removeFromNRIR( RealAlgebraicNumberPtr r ) 00454 { 00455 #ifdef GINACRA_CAD_DEBUG 00456 cout << "removeFromNRIR: " << r << endl; 00457 cout << "List: " << endl; 00458 for( list<RealAlgebraicNumberPtr>::const_iterator i = begin(); i != end(); ++i ) 00459 cout << " " << *i; 00460 cout << endl << "NR: " << endl; 00461 for( list<RealAlgebraicNumberPtr>::const_iterator i = mNRsIRs.first.begin(); i != mNRsIRs.first.end(); ++i ) 00462 cout << " " << **i; 00463 cout << endl << "IR: " << endl; 00464 for( list<RealAlgebraicNumberPtr>::const_iterator i = mNRsIRs.second.begin(); i != mNRsIRs.second.end(); ++i ) 00465 cout << " " << **i; 00466 #endif 00467 RealAlgebraicNumberNRPtr rNR = std::tr1::dynamic_pointer_cast<RealAlgebraicNumberNR>( r ); 00468 if( rNR != 0 ) 00469 { 00470 list<RealAlgebraicNumberNRPtr>::iterator pos = std::find( mNRsIRs.first.begin(), mNRsIRs.first.end(), rNR ); 00471 if( pos != mNRsIRs.first.end() ) 00472 mNRsIRs.first.erase( pos ); 00473 else 00474 assert( false ); // r should be in this list, otherwise it was maybe simplified and moved to the other list 00475 } 00476 else 00477 { 00478 list<RealAlgebraicNumberIRPtr>::iterator pos = std::find( mNRsIRs.second.begin(), mNRsIRs.second.end(), 00479 std::tr1::dynamic_pointer_cast<RealAlgebraicNumberIR>( r )); 00480 if( pos != mNRsIRs.second.end() ) 00481 mNRsIRs.second.erase( pos ); 00482 else 00483 assert( false ); // r should be in this list 00484 } 00485 } 00486 00487 }; 00488 00491 struct CADSettings 00492 { 00494 // ATTRIBUTES // 00496 00498 bool (*mUP_isLess)( const UnivariatePolynomial&, const UnivariatePolynomial& ); 00500 RealAlgebraicNumberSettings::IsolationStrategy mIsolationStrategy; 00501 00503 // METHODS // 00505 00512 static const CADSettings getSettings( unsigned setting = DEFAULT_CADSETTING, 00513 RealAlgebraicNumberSettings::IsolationStrategy isolationStrategy = RealAlgebraicNumberSettings::DEFAULT_ISOLATIONSTRATEGY ) 00514 { 00515 CADSettings cadSettings = CADSettings(); 00516 cadSettings.mIsolationStrategy = isolationStrategy; 00517 if( setting & LOWDEG_CADSETTING ) 00518 cadSettings.mUP_isLess = UnivariatePolynomial::univariatePolynomialIsLessLowDeg; 00519 if( setting & ODDDEG_CADSETTING ) 00520 cadSettings.mUP_isLess = UnivariatePolynomial::univariatePolynomialIsLessOddDeg; 00521 if( setting & LOWDEG_CADSETTING & ODDDEG_CADSETTING ) 00522 cadSettings.mUP_isLess = UnivariatePolynomial::univariatePolynomialIsLessOddLowDeg; 00523 if( setting & EVENDEG_CADSETTING ) 00524 cadSettings.mUP_isLess = UnivariatePolynomial::univariatePolynomialIsLessEvenDeg; 00525 if( setting & LOWDEG_CADSETTING & EVENDEG_CADSETTING ) 00526 cadSettings.mUP_isLess = UnivariatePolynomial::univariatePolynomialIsLessEvenLowDeg; 00527 if( setting & EAGERLIFTING_CADSETTING ) 00528 cadSettings.mPreferNRSamples = true; 00529 if( setting & GROEBNER_CADSETTING ) 00530 cadSettings.mSimplifyByGroebner = true; 00531 if( setting & REALROOTCOUNT_CADSETTING ) 00532 cadSettings.mSimplifyByRootcounting = true; 00533 if( setting & SQUAREFREEELIMINATION_CADSETTING ) 00534 cadSettings.mSimplifyBySquarefreeing = true; 00535 return cadSettings; 00536 } 00537 00538 friend std::ostream& operator <<( std::ostream& os, const CADSettings& settings ) 00539 { 00540 list<string> settingStrs = list<string>(); 00541 if( settings.mSimplifyByGroebner ) 00542 settingStrs.push_back( "Simplify the input polynomials corresponding to equations by a Groebner basis." ); 00543 if( settings.mSimplifyByRootcounting ) 00544 settingStrs.push_back( "Simplify the base elimination level by real root counting." ); 00545 if( settings.mSimplifyBySquarefreeing ) 00546 settingStrs.push_back( "Simplify all elimination levels by replacing the polynomials by their square-free part." ); 00547 if( settings.mPreferNRSamples ) 00548 settingStrs.push_back( "Prefer numerics to interval representations for sample choice." ); 00549 if( settings.mPreferSamplesByIsRoot && settings.mPreferNonrootSamples ) 00550 settingStrs.push_back( "Prefer non-root to root samples for sample choice." ); 00551 if( settings.mPreferSamplesByIsRoot && !settings.mPreferNonrootSamples ) 00552 settingStrs.push_back( "Prefer root to non-root samples for sample choice." ); 00553 os << "+------------------------------------ CAD Setting -----------------------------------"; 00554 if( settingStrs.empty() ) 00555 os << endl << "| Default "; 00556 else 00557 { 00558 for( list<string>::const_iterator i = settingStrs.begin(); i != settingStrs.end(); ++i ) 00559 os << endl << "↳ " << *i; 00560 } 00561 return os << endl << "+------------------------------------------------------------------------------------"; 00562 } 00563 00564 bool simplifyByGroebner() const 00565 { 00566 return mSimplifyByGroebner; 00567 } 00568 00569 void setSimplifyByGroebner( bool b ) 00570 { 00571 mSimplifyByGroebner = b; 00572 } 00573 00574 bool simplifyByRootcounting() const 00575 { 00576 return mSimplifyByRootcounting; 00577 } 00578 00579 void setSimplifyByRootcounting( bool b ) 00580 { 00581 mSimplifyByRootcounting = b; 00582 } 00583 00584 bool simplifyBySquarefreeing() const 00585 { 00586 return mSimplifyBySquarefreeing; 00587 } 00588 00589 void setSimplifyBySquarefreeing( bool b ) 00590 { 00591 mSimplifyBySquarefreeing = b; 00592 } 00593 00594 bool preferNRSamples() const 00595 { 00596 return mPreferNRSamples; 00597 } 00598 00599 void setPreferNRSamples( bool b ) 00600 { 00601 mPreferNRSamples = b; 00602 // dependency: PreferNRSamples excludes the use of PreferSamplesByIsRoot and vice versa 00603 mPreferSamplesByIsRoot = b ? false : mPreferSamplesByIsRoot; 00604 } 00605 00606 bool preferSamplesByIsRoot() const 00607 { 00608 return mPreferSamplesByIsRoot; 00609 } 00610 00611 void setPreferSamplesByIsRoot( bool b ) 00612 { 00613 mPreferSamplesByIsRoot = b; 00614 // dependency: PreferSamplesByIsRoot excludes the use of PreferNRSamples and vice versa 00615 mPreferNRSamples = b ? false : mPreferNRSamples; 00616 } 00617 00618 bool preferNonrootSamples() const 00619 { 00620 return mPreferNonrootSamples; 00621 } 00622 00627 void setPreferNonrootSamples( bool b ) 00628 { 00629 setPreferSamplesByIsRoot( true ); 00630 mPreferNonrootSamples = b; 00631 } 00632 00633 protected: 00634 00636 // ATTRIBUTES // 00638 00640 bool mPreferNRSamples; 00642 bool mPreferSamplesByIsRoot; 00644 bool mPreferNonrootSamples; 00646 bool mSimplifyByGroebner; 00648 bool mSimplifyByRootcounting; 00650 bool mSimplifyBySquarefreeing; 00651 00652 private: 00653 00662 CADSettings(): 00663 mUP_isLess( UnivariatePolynomial::univariatePolynomialIsLess ), 00664 mIsolationStrategy( RealAlgebraicNumberSettings::DEFAULT_ISOLATIONSTRATEGY ), 00665 mPreferNRSamples( false ), 00666 mPreferSamplesByIsRoot( false ), 00667 mPreferNonrootSamples( false ), 00668 mSimplifyByGroebner( false ), 00669 mSimplifyByRootcounting( false ), 00670 mSimplifyBySquarefreeing( false ) 00671 {} 00672 00673 }; 00674 00678 struct isLessInLiftingPositions 00679 { 00680 vector<UnivariatePolynomial> mEliminationSet; 00681 bool (*mIsLess)( const UnivariatePolynomial&, const UnivariatePolynomial& ); 00682 00688 isLessInLiftingPositions( const vector<UnivariatePolynomial>& eliminationSet, bool (*isLess)( const UnivariatePolynomial&, const UnivariatePolynomial& ) ) : 00689 mEliminationSet(eliminationSet), 00690 mIsLess( isLess ) 00691 {} 00692 00693 bool operator ()( unsigned i, unsigned j ) const 00694 { 00695 return mIsLess( mEliminationSet[i], mEliminationSet[j] ); 00696 } 00697 }; 00698 00707 class CAD 00708 { 00709 public: 00710 00712 // Constructors and Destructors // 00714 00715 /* 00716 * Standard constructor doing nothing. 00717 */ 00718 CAD(); 00719 00727 CAD( const UnivariatePolynomialSet& s, const vector<symbol>& v, CADSettings setting = CADSettings::getSettings() ); 00728 00729 /* 00730 * Copy constructor. 00731 */ 00732 CAD( const CAD& cad ): 00733 mVariables( cad.mVariables ), 00734 mSampleTree( cad.mSampleTree ), 00735 mSampleListIncrements( cad.mSampleListIncrements ), 00736 mEliminationSets( cad.mEliminationSets ), 00737 mLiftingPositions( cad.mLiftingPositions ), 00738 mIsComplete( cad.mIsComplete ), 00739 mSetting( cad.mSetting ) 00740 {} 00741 00743 // Selectors // 00745 00746 /* 00747 * @return list of main variables of the polynomials of this cad 00748 */ 00749 const vector<symbol> variables() 00750 { 00751 return mVariables; 00752 } 00753 00754 /* 00755 * Returns the input set of polynomials underlying this cad as a list. 00756 * @return the set of polynomials underlying this cad as a list 00757 */ 00758 const vector<UnivariatePolynomial> polynomials() 00759 { 00760 return mEliminationSets[0]; 00761 } 00762 00763 /* 00764 * Sets with successively eliminated variables due to a CAD projection. Index i corresponds to the set where i variables were eliminated. 00765 * <br/ >For i>0, the i-th set was obtained by eliminating the variable i-1. 00766 * @return all eliminations of the polynomials and the polynomials themselves (at position 0) computed so far 00767 */ 00768 const vector<vector<UnivariatePolynomial> > eliminationSets() 00769 { 00770 return mEliminationSets; 00771 } 00772 00773 /* 00774 * @return true if the cad is computed completely, false if there are still samples to compute 00775 */ 00776 bool isComplete() const 00777 { 00778 return mIsComplete; 00779 } 00780 00782 // Operations on CAD object // 00784 00788 void complete(); 00789 00794 const vector<RealAlgebraicPoint> samples(); 00795 00807 bool check( const vector<Constraint>& constraints, RealAlgebraicPoint& r ); 00808 00813 void printSampleTree( std::ostream& os = std::cout ); 00814 00825 void addPolynomial( const UnivariatePolynomial& p, const vector<GiNaC::symbol>& v, unsigned setting = DEFAULT_CADSETTING ) 00826 { 00827 list<UnivariatePolynomial> l = list<UnivariatePolynomial>( 1, p ); 00828 addPolynomials( l.begin(), l.end(), v, setting ); 00829 } 00830 00842 template<class InputIterator> 00843 void addPolynomials( InputIterator first, InputIterator last, const vector<GiNaC::symbol>& v, unsigned setting = DEFAULT_CADSETTING ) 00844 { 00845 this->alterSetting( setting ); 00846 // settings (need to be set before every other process because of VariableListPool) 00847 if( mSetting.simplifyByGroebner() ) 00848 { 00849 MultivariatePolynomialSettings::InitializeGiNaCRAMultivariateMR(); 00850 for( vector<symbol>::const_iterator i = mVariables.begin(); i != mVariables.end(); ++i ) 00851 VariableListPool::addVariable( *i ); 00852 } 00853 00854 /* Algorithm overview: 00855 * (1) Determine the variables differing from mVariables and add them to the front of the existing variables. 00856 * (2) Add as many levels to the front of eliminationSets as new variables were determined. 00857 * (3) Compute the elimination for the new elimination sets with the new polynomials, add the prevailing ones, and perform pairwise elimination with the prevailing ones. 00858 * (4) Re-compute elimination for the newly arriving polynomials in the old elimination sets. 00859 */ 00860 // (1) 00861 vector<GiNaC::symbol> newVariables = vector<GiNaC::symbol>(); 00862 unsigned newVariableCount = 0; 00863 for( vector<GiNaC::symbol>::const_iterator i = v.begin(); i != v.end(); ++i ) 00864 { 00865 if( std::find( mVariables.begin(), mVariables.end(), *i ) == mVariables.end() ) 00866 { // found a new variable 00867 newVariables.push_back( *i ); 00868 ++newVariableCount; 00869 } 00870 } 00871 for( vector<GiNaC::symbol>::const_iterator i = mVariables.begin(); i != mVariables.end(); ++i ) 00872 newVariables.push_back( *i ); 00873 if( newVariableCount != 0 ) 00874 { // extend the other data structures depending on level 00875 vector<SampleList> newSampleListIncrements = vector<SampleList>( newVariableCount, SampleList() ); 00876 for( vector<SampleList>::const_iterator i = mSampleListIncrements.begin(); i != mSampleListIncrements.end(); ++i ) 00877 newSampleListIncrements.push_back( *i ); 00878 mSampleListIncrements = newSampleListIncrements; 00879 } 00880 // (2) 00881 vector<vector<UnivariatePolynomial> > newEliminationSets = 00882 vector<vector<UnivariatePolynomial> >( mEliminationSets.size() + newVariableCount, vector<UnivariatePolynomial>() ); 00883 for( unsigned i = newVariableCount; i < newEliminationSets.size(); ++i ) // copy previous elimination sets 00884 newEliminationSets[i] = mEliminationSets[i - newVariableCount]; 00885 UnivariatePolynomialSet currentEliminationSet = UnivariatePolynomialSet( newEliminationSets[0].begin(), newEliminationSets[0].end() ); 00886 UnivariatePolynomialSet s = UnivariatePolynomialSet( first, last ); // collect the new polynomials 00887 for( UnivariatePolynomialSet::const_iterator i = s.begin(); i != s.end(); ++i ) 00888 { // add new polynomials to level 0, unifying their variables 00889 UnivariatePolynomial pNewVar( *i, newVariables.front() ); 00890 newEliminationSets[0].push_back( pNewVar ); 00891 currentEliminationSet.insert( pNewVar ); 00892 } 00893 // (3) and (4) [can be made more efficient by making use of the atomic elimination operators] 00894 // Caution: The elimination is recomputed completely in case we have multivariate polynomials. 00895 // this loop does nothing if we have univariate polynomials 00896 for( unsigned i = 1; i != newVariables.size(); ++i ) 00897 { // perform elimination of level i-1 00898 // position i of mEliminationSets corresponds to variable i-1 (current main variable) eliminated in position i-1 of mEliminationSets 00899 currentEliminationSet = eliminationSet( currentEliminationSet, newVariables[i] ); 00900 for( vector<UnivariatePolynomial>::const_iterator j = newEliminationSets[i].begin(); j != newEliminationSets[i].end(); 00901 ++j ) // insert possibly existing polynomials of the current level 00902 currentEliminationSet.insert( *j ); 00903 vector<UnivariatePolynomial> currentEliminationList( currentEliminationSet.begin(), currentEliminationSet.end() ); 00904 // *** CADSettings: simplifyBySquarefreeing 00905 if( mSetting.simplifyBySquarefreeing() ) 00906 { 00907 for( unsigned k = 0; k < currentEliminationList.size(); ++k ) 00908 currentEliminationList[k] = currentEliminationList[k].sepapart(); 00909 } 00910 std::sort( currentEliminationList.begin(), currentEliminationList.end(), mSetting.mUP_isLess ); 00911 if( mSetting.simplifyBySquarefreeing() ) 00912 std::unique( currentEliminationList.begin(), currentEliminationList.end() ); 00913 newEliminationSets[i] = vector<UnivariatePolynomial>( currentEliminationList.begin(), currentEliminationList.end() ); 00914 // *** /CADSettings: simplifyBySquarefreeing 00915 } 00916 // apply heuristics 00917 // *** CADSettings: simplifyByRootcounting 00918 if( mSetting.simplifyByRootcounting() ) 00919 { 00920 vector<UnivariatePolynomial> baseLevel = mEliminationSets.back(); 00921 for( unsigned i = 0; i < baseLevel.size(); ) 00922 { 00923 if( baseLevel[i].degree() % 2 == 0 ) 00924 { // there could only be complex roots if the degree is even 00925 RationalUnivariatePolynomial p( baseLevel[i] ); 00926 if( p.countRealRoots() == 0 ) 00927 { 00928 baseLevel.erase( baseLevel.begin() + i ); 00929 continue; // do not increase i 00930 } 00931 } 00932 ++i; 00933 } 00934 mEliminationSets.back() = baseLevel; 00935 } 00936 // *** CADSettings: /simplifyByRootcounting 00937 mVariables = newVariables; 00938 mEliminationSets = newEliminationSets; 00939 mIsComplete = false; 00940 // reset all lifting positions 00941 mLiftingPositions = vector< list<unsigned> >( mVariables.size(), list<unsigned>() ); 00942 for( unsigned i = 0; i < mVariables.size(); ++i ) 00943 { 00944 for( unsigned j = 0; j < mEliminationSets[i].size(); ++j ) 00945 mLiftingPositions[i].push_back(j); 00946 // l.sort( isLessInLiftingPositions( mEliminationSets[i], mSetting.mUP_isLess ) ); 00947 } 00948 } 00949 00951 // PUBLIC STATIC METHODS // 00953 00961 static const UnivariatePolynomialSet eliminationSet( const UnivariatePolynomialSet& P, 00962 const symbol& nextVariable ) 00963 throw ( invalid_argument ); 00964 00973 static const SampleList samples( const list<RealAlgebraicNumberPtr>& roots, SampleList& currentSamples ) throw ( invalid_argument ); 00974 00987 static const SampleList samples( const list<RationalUnivariatePolynomial>& polynomials, 00988 SampleList& currentSamples ) 00989 throw ( invalid_argument ); 00990 00991 // ATOMIC METHODS // 00993 01005 static void elimination( const UnivariatePolynomial& p, const symbol& variable, UnivariatePolynomialSet& eliminated ) throw ( invalid_argument ); 01006 01019 static void elimination( const UnivariatePolynomial& p, 01020 const UnivariatePolynomial& q, 01021 const symbol& variable, 01022 UnivariatePolynomialSet& eliminated ) 01023 throw ( invalid_argument ); 01024 01034 static const SampleList samples( const RationalUnivariatePolynomial& p, 01035 SampleList& currentSamples, 01036 CADSettings settings = CADSettings::getSettings() ) 01037 throw ( invalid_argument ); 01038 01049 static const SampleList samples( const UnivariatePolynomial& p, 01050 const list<RealAlgebraicNumberPtr>& sample, 01051 const list<symbol>& variables, 01052 SampleList& currentSamples, 01053 CADSettings settings = CADSettings::getSettings() ) 01054 throw ( invalid_argument ); 01055 01056 private: 01057 01059 // Heuristics // 01061 01067 void alterSetting( unsigned setting = DEFAULT_CADSETTING, 01068 RealAlgebraicNumberSettings::IsolationStrategy isolationStrategy = RealAlgebraicNumberSettings::DEFAULT_ISOLATIONSTRATEGY ) 01069 { 01070 mSetting = CADSettings::getSettings( setting, isolationStrategy ); 01071 } 01072 01074 // ATTRIBUTES // 01076 01078 vector<symbol> mVariables; 01080 tree<RealAlgebraicNumberPtr> mSampleTree; 01082 vector<SampleList> mSampleListIncrements; 01084 vector<vector<UnivariatePolynomial> > mEliminationSets; 01086 vector<list<unsigned> > mLiftingPositions; 01088 bool mIsComplete; 01090 CADSettings mSetting; 01091 01093 // Auxiliary methods // 01095 01102 inline const RealAlgebraicPoint constructSampleAt( tree<RealAlgebraicNumberPtr>::iterator node, 01103 const tree<RealAlgebraicNumberPtr>::iterator& root ) const; 01104 01115 inline const bool liftCheck( tree<RealAlgebraicNumberPtr>::iterator node, 01116 const list<RealAlgebraicNumberPtr>& sample, 01117 unsigned level, 01118 const list<symbol>& variables, 01119 const vector<Constraint>& constraints, 01120 RealAlgebraicPoint& r ) 01121 throw ( invalid_argument ); 01122 01129 inline const bool satisfys( const RealAlgebraicPoint& r, const vector<Constraint>& constraints ) const; 01130 01132 // STATIC AUXILIARY METHODS // 01134 01143 static const UnivariatePolynomialSet truncation( const UnivariatePolynomial& P ); 01144 01153 static const UnivariatePolynomialSet truncation( const UnivariatePolynomialSet& P ); 01154 }; 01155 } // namespace GiNaC 01156 #endif