realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/solver_uv_continued_fraction.hpp
Go to the documentation of this file.
00001 /*******************************************************************
00002  *   This file is part of the source code of the realroot kernel.
00003  *   Author(s): 
00004  *        E. Tsigaridas <et@di.uoa.gr>
00005  *           Department of Informatics and Telecommunications
00006  *           University of Athens (Greece).
00007  *   Modification:
00008  *        B. Mourrain, GALAAD, INRIA
00009  ********************************************************************/
00010 #ifndef realroot_solve_contfrac_hpp
00011 #define realroot_solve_contfrac_hpp
00012 
00065 //====================================================================
00066 #include <realroot/GMP.hpp>
00067 #include <realroot/univariate_bounds.hpp>
00068 #include <realroot/sign_variation.hpp>
00069 #include <realroot/Seq.hpp>
00070 #include <realroot/solver.hpp>
00071 #include <realroot/contfrac_intervaldata.hpp>
00072 #include <realroot/contfrac_lowerbound.hpp>
00073 
00074 # define TMPL    template<class C, class R, class V>
00075 # define SOLVER  solver<C, ContFrac<R,V> >
00076 //====================================================================
00077 namespace mmx {
00078 
00079   template<class M> struct ContFrac{};
00080 
00081   //--------------------------------------------------------------------
00082   template<class K, class B> struct continued_fraction_isolate: public K
00083   {
00084     typedef typename K::integer           integer;
00085     typedef typename K::rational          rational;
00086     typedef polynomial<integer, with<MonomialTensor> > Polynomial;
00087     typedef typename K::interval_rational root_t;
00088     typedef Seq<root_t>                   sol_t;
00089     
00090     typedef IntervalData< integer, Polynomial>  data;  
00091 
00092     static inline root_t as_root(const data& ID)
00093     {
00094       return as<root_t>(ID);
00095     }
00096     static inline bool        is_empty(const data& ID)        {return ID.s==0;}
00097     static inline bool        is_good (const data& ID)        {return ID.s==1;}
00098     static inline integer lower_bound (const Polynomial& p)   {return B::lower_bound(p);}
00099   };
00100 
00101 
00102   template<class K, class B> struct continued_fraction_approximate: public K
00103   {
00104     typedef typename K::integer           integer;
00105     typedef typename K::rational          rational;
00106     typedef typename K::interval_rational interval_rational;
00107     typedef polynomial<integer, with<MonomialTensor> >   Polynomial;
00108     typedef interval_rational             root_t;
00109     typedef Seq<root_t>                   sol_t;
00110     typedef IntervalData< integer, Polynomial>  data;  
00111 
00112     static unsigned prec;
00113     static inline void     set_precision(unsigned n){ prec = n;}
00114     static inline unsigned get_precision() { return prec; }
00115 
00116     static inline root_t as_root(const data& ID)
00117     {
00118       return as<root_t>(ID);
00119     }
00120 
00121     static inline bool is_empty(const data& ID) {return ID.s==0;}
00122     static inline bool is_good (const data& ID) 
00123     {
00124       //      std::cout << __FUNCTION__ <<" "<<ID.p<<" "<<ID.s<<std::endl; 
00125       if(ID.s !=1)
00126         return false;
00127       else
00128         {
00129           integer N = ID.a*ID.d-ID.b*ID.c, D=ID.c*ID.d ;
00130           if(D==0)
00131             return false;
00132           if(N<0) N = -N;
00133           N<<=prec;
00134           if(D<0) D = -D;
00135           if(N<D)  
00136             return true;
00137           else
00138             return false;
00139         }      
00140     }
00141     static inline integer lower_bound(const Polynomial& p) {return B::lower_bound(p);}
00142 
00143   };
00144 
00145   template<class K, class B> unsigned continued_fraction_approximate<K,B>::prec = 
00146               solver_default_precision;
00147 
00148   template < class K >
00149   struct continued_fraction_subdivision : public K {
00150     typedef typename K::integer       RT;
00151     typedef typename K::integer       integer;
00152     typedef typename K::rational      FT;
00153     typedef typename K::rational      rational;
00154     typedef typename K::floating      floating;
00155     typedef typename K::root_t        root_t;
00156     typedef typename K::Polynomial    polynomial_integer;
00157     typedef polynomial< rational, with<MonomialTensor> >  polynomial_rational;
00158     typedef polynomial< floating, with<MonomialTensor> >  polynomial_floating;
00159     typedef typename K::data          data;
00160 
00161     static void set_precision(int prec) {K::set_precision(prec);}
00162 
00163     static void 
00164     solve_positive(Seq<root_t>& sol, const polynomial_integer& f, bool posneg) {
00165       //      std::cout << __FUNCTION__ << " "<<f<<" "<<posneg<<std::endl; 
00166 
00167       typedef typename K::data IntervalData;  
00168 
00169             IntervalData ID(1, 0, 0, 1, f, 0);
00170             if (!posneg) 
00171             {      
00172                 ID.a=-1;
00173                 for (int i = 1; i <= degree(f); i+=2) ID.p[i] *= -1;
00174             }
00175             ID.s = sign_variation(ID.p);
00176         
00177             if ( K::is_empty(ID) ) { return; }
00178             if ( K::is_good(ID)  ) {
00179                 //std::cout << "A) Sign variation: 1"<<std::endl;;
00180                 FT B = bound_root( f, Cauchy<FT>());
00181                 if ( posneg )
00182                      sol << root_t( FT(0), B);
00183                 else sol << root_t( FT(0), FT(-B));
00184                 return;
00185             }
00186 
00187             solve_homography(sol,ID);
00188     }
00189   
00190     template<class output> static void 
00191     solve_homography(output& sol, const data& ID) {
00192       //            std::cout << __FUNCTION__ << " "<<ID.p<<std::endl; 
00193 
00194       polynomial_integer X(1,0,1); 
00195       //X[1] = RT(1); X[0]=RT(0);
00196       
00197       int iters  = 0;
00198       const RT One(1);
00199       FT Zero(0);
00200       //    std::cout << "Polynomial is " << ID.p << std::endl;
00201 
00202       typedef data IntervalData;  
00203       std::stack< IntervalData > S;
00204       S.push( ID );
00205       while ( !S.empty() ) {
00206         ++iters;
00207         IntervalData ID = S.top();
00208         S.pop();
00209         
00210         // std::cout << "Polynomial is " << ID.p << std::endl;
00211         // Steps 3 - 4: Choose the method for computing the lower bound 
00212         //--------------------------------------------------------------------
00213         RT a = K::lower_bound(ID.p);
00214         //    long k = Bd.lower_power_2( ID.p);
00215         //    std::cout<< "\t Lower bound is "<< a<< std::endl;
00216         
00217         if ( a > RT(1) ) {
00218           scale(ID,a);
00219           a = RT(1);
00220         }
00221         //--------------------------------------------------------------------
00222         // Step 5 //
00223         if ( a >= RT(1) ) {
00224           shift(ID, a);
00225           //            std::cout<<"Shift by "<<a<<std::endl;
00226           
00227           if ( ID.p[0] == RT(0)) 
00228             {
00229               div_x(ID.p,1);
00230               sol << root_t( to_FT( ID.b, ID.d), to_FT( ID.b, ID.d ));
00231             }
00232           ID.s = sign_variation( ID.p);
00233         }
00234         //int s= Kernel::init_shift(ID);
00235         //--------------------------------------------------------------------
00236         if ( K::is_empty(ID) ) 
00237           continue; 
00238         else if( K::is_good(ID) ) {
00239           sol << K::as_root(ID);
00240           continue;
00241         }
00242         //--------------------------------------------------------------------
00243         // Step 6
00244         IntervalData I1;
00245         shift_by_1( I1, ID);
00246         
00247         unsigned long r  = 0;
00248         
00249         if (I1.p[0] == RT(0)) {
00250           //    std::cout << "Zero at end point"<<std::endl;;
00251           sol << root_t( to_FT( I1.b, I1.d), to_FT(I1.b, I1.d) );
00252           div_x(I1.p,1);
00253           r = 1;
00254         }
00255         I1.s = sign_variation( I1.p);
00256         
00257         IntervalData I2;
00258         I2.s = ID.s - I1.s - r;
00259         reverse_shift_homography(I2,ID);
00260                 
00261         // std::cout <<I1.s <<" "<<I2.s<<std::endl;
00262         // Step 7;
00263         if ( !K::is_empty(I2) && !K::is_good(I2) ) {
00264           
00265           //p2 = p2( 1 / (x+1));
00266           reverse( I2.p, ID.p);
00267           shift_by_1(I2.p);
00268           
00269           if ( I2.p[0] == 0) {
00270             div_x(I2.p,1);
00271           }
00272           I2.s = sign_variation( I2.p);
00273         }
00274         
00275         // Step 8
00276         if ( I1.s < I2.s ) {std::swap( I1, I2); }
00277         
00278         // Step 9
00279         if ( K::is_good(I1) ) {
00280           //    std::cout << "C) Sign variation: 1"<<std::endl;;
00281           sol << K::as_root(I1);
00282         } else if ( !K::is_empty(I1) ) {
00283           S.push(I1); //IntervalData( I1.a, I1.b, I1.c, I1.d, I1.p, I1.s));
00284         }
00285         // Step 10
00286         if ( K::is_good(I2) ) {
00287           //    std::cout << "D) Sign variation: 1"<<std::endl;;
00288           sol <<  K::as_root(I2);
00289         } else if ( !K::is_empty(I2) ) {
00290           S.push(I2); //IntervalData( I2.a, I2.b, I2.c, I2.d, I2.p, I2.s));
00291         }
00292       } // while
00293       //    std::cout << "-------------------- iters: " << iters << std::endl; 
00294       return;  
00295     }
00296 
00297     template < class output> inline static void 
00298     solve(output& sol,  const polynomial_integer& f, int  mult=1) {
00299       //      std::cout << __FUNCTION__ << " I "<<f<<std::endl; 
00300       Seq < root_t > isolating_intervals;
00301       // Check if 0 is a root
00302       int idx;
00303       for (idx = 0; idx <= degree( f); ++idx) {
00304         if ( f[idx] != 0 ) break;
00305       }
00306 
00307       polynomial_integer p;
00308       if ( idx == 0 ) { p = f; } 
00309       else {
00310         p= polynomial_integer(1,degree(f) - idx);
00311         for (int j = idx; j <= degree(f); j++) 
00312           p[j-idx] = f[j];
00313       }
00314       
00315       // std::cout << "Solving: " << p << std::endl; 
00316       // Isolate the negative roots
00317       //    for (int i = 1; i <= degree(p); i+=2) p[i] *= -1;
00318       solve_positive( isolating_intervals, p, false);
00319       // Is 0 a root?
00320       // std::cout << "ok negative" << std::endl; 
00321       if (idx != 0) isolating_intervals << root_t( 0, 0);
00322       //    for (int i = 1; i <= degree(p); i+=2) p[i] *= -1;
00323       solve_positive( isolating_intervals, p, true);
00324       // sort( isolating_intervals.begin(), isolating_intervals.end(), CompareFIT());
00325       // std::cout << "ok positive" << std::endl; 
00341       // std::cout << "now p: " << p << ",  #nr: " << isolating_intervals.size() << std::endl; 
00342       
00343       //      std::cout << "Done...." << std::endl; 
00344       for (unsigned i = 0 ; i < isolating_intervals.size(); ++i) 
00345         {sol << isolating_intervals[i];}
00346       //    return sol;
00347     }
00348     
00349     template < class output> inline static void 
00350     solve(output& sol,  const polynomial_rational& f) {
00351       //      std::cout << __FUNCTION__ << " R "<<f<<std::endl; 
00352       solve(sol, univariate::numer<polynomial_integer> (f));
00353     }
00354     
00355     template < class output> inline static void 
00356     solve(output& sol,  const polynomial_floating& f) {
00357       //      std::cout << __FUNCTION__ << " R "<<f<<std::endl; 
00358       polynomial_rational p(rational(0),degree(f));
00359       
00360       for(int i=0;i<degree(f)+1;i++) {
00361         p[i] = as<rational>(f[i]);
00362       }
00363       solve(sol,p);
00364     }
00365     
00366   };
00367 
00368   //--------------------------------------------------------------------
00369   template<class C> 
00370   struct solver<C,ContFrac<Approximate> > {
00371     typedef typename texp::kernelof<C>::T K;
00372     typedef continued_fraction_subdivision<
00373               continued_fraction_approximate<K,
00374                  AkritasBound<typename K::integer> > >
00375                                                  base_t;
00376     typedef typename K::interval_rational        interval_t;
00377     typedef Seq<interval_t>                      Solutions;
00378     typedef typename base_t::Polynomial          polynomial_integer;
00379     typedef typename base_t::polynomial_rational polynomial_rational;
00380     typedef typename base_t::polynomial_floating polynomial_floating;
00381 
00382 
00383     static inline void set_precision(unsigned p) {
00384        continued_fraction_approximate<K,AkritasBound<typename K::integer> >::set_precision(p);
00385     }
00386     
00387     template < class output > inline static void 
00388     solve(output& sol, const polynomial_integer& f) {
00389        base_t::solve(sol, f);
00390     }
00391 
00392     template < class output > inline
00393     static void solve(output& sol, const polynomial_rational& f) {
00394       base_t::solve(sol, f);
00395     }
00396     template < class output > inline static void 
00397     solve(output& sol, const polynomial_floating& f) {
00398        base_t::solve(sol, f);
00399     }
00400 
00401     template < class output > inline static void 
00402     solve(output& sol, const polynomial_integer& f, int prec) {
00403       base_t::set_precision(prec);
00404       solve(sol, f);
00405       base_t::set_precision(solver_default_precision);
00406     }
00407 
00408     template <class output> inline static void 
00409     solve(output& sol, const polynomial_integer& f, 
00410           const  typename K::rational& u, const  typename K::rational& v) {
00411       typedef typename K::integer integer;
00412       integer 
00413         a= numerator(v), 
00414         b= numerator(u), 
00415         c= denominator(v),  
00416         d= denominator(u);
00417       IntervalData<integer, polynomial_integer> D = 
00418         as_interval_data(a,b,c,d,f);
00419       base_t::solve_homography(sol,D);
00420     }
00421 
00422     template <class output> inline static void 
00423     solve(output& sol, const polynomial_rational& f, 
00424           const  typename K::rational& u, const  typename K::rational& v) {
00425       solve(sol, univariate::numer<polynomial_integer>(f), u, v);
00426     }
00427     
00428     
00429   };
00430 
00431   //====================================================================
00432   template<class C> 
00433   struct solver<C,ContFrac<Isolate> > {
00434     typedef typename texp::kernelof<C>::T K;
00435     typedef Seq<typename K::interval_rational>   Solutions;
00436     typedef continued_fraction_subdivision<
00437               continued_fraction_isolate<K,
00438                  AkritasBound<typename K::integer> > > base_t;
00439 
00440     template < class output, class POL> inline static void 
00441     solve(output& sol, const POL& f) {
00442       base_t::solve(sol,f);
00443     }
00444   };
00445 
00446  //---------------------------------------------------------------------
00447   template<class POL, class M>
00448   typename solver<typename POL::Scalar, ContFrac<M> >::Solutions 
00449   solve (const POL& p, const ContFrac<M>& slv) {
00450     typedef typename POL::Scalar                             Scalar;
00451     typedef solver<Scalar, ContFrac<M> >                     Solver;
00452     typedef typename solver<Scalar, ContFrac<M> >::Solutions Solutions;
00453     Solutions sol;
00454     Solver::solve(sol,p);
00455     return sol;
00456   }
00457 
00458   //---------------------------------------------------------------------
00459   template<class POL, class M, class B>
00460   typename solver<typename POL::Scalar, ContFrac<M> >::Solutions 
00461   solve (const POL& p, const ContFrac<M>& slv, const B& b1, const B& b2) {
00462     typedef solver<B, ContFrac<M> >                     Solver;
00463     typedef typename solver<B, ContFrac<M> >::Solutions Solutions;
00464     Solutions sol;
00465     Solver::solve(sol,p,b1,b2);
00466     return sol;
00467   }
00468   //--------------------------------------------------------------------
00469 
00470 } //namespace mmx 
00471 //====================================================================
00472 # undef TMPL
00473 # undef SOLVER
00474 //====================================================================
00475 #endif // _realroot_solve_contfrac_hpp_