GiNaCRA  0.6.4
CAD.h
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 
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