synaps/usolve/Symbolic.h

00001 #ifndef synaps_solve_Symbolic_H
00002 #define synaps_solve_Symbolic_H
00003 //--------------------------------------------------------------------
00004 #include <synaps/init.h>
00005 #include <synaps/arithm/sign.h>
00006 #include <synaps/upol/UPolDse.h>
00007 #include <synaps/upol/SturmSeq.h>
00008 #include <synaps/usolve/Algebraic.h>
00009 #include <synaps/arithm/symbolic/real.h>
00010 #include <synaps/base/Seq.h>
00011 #include <synaps/usolve/bezier/IslBzBdg.h>
00012 #include <synaps/upol/SturmSeq.h>
00013 //#include <synaps/arithm/double.h>
00014 //--------------------------------------------------------------------
00015 __BEGIN_NAMESPACE_SYNAPS
00016 //--------------------------------------------------------------------
00017 struct Bounding;
00018 //--------------------------------------------------------------------
00019 template<class C, class SLV= Bezier<C,Bounding> , class X=double>
00020 //--------------------------------------------------------------------
00021 struct Symbolic
00022 {
00023   X eps;
00024   Symbolic():eps(1.e-6) {}
00025   Symbolic(const X& e):eps(e) {}
00026   Symbolic(const Symbolic & mth): eps(mth.eps) {}
00027 };
00028 
00029 namespace symbolic {
00030 
00031   template<class C>
00032   struct sqrt_rep : public real_rep<C>
00033   {
00034   protected:
00035     real<C> alpha;
00036   public:
00037     //  friend class sqrtof<C>;
00038     sqrt_rep(real<C> x)
00039       : real_rep<C>(sqrt(x.lower()),sqrt(x.upper())), alpha(x) {};
00040     
00041     sqrt_rep(const C & x)
00042       :
00043       real_rep<C>(sqrt(x)-real<C>::eps/2,sqrt(x)+real<C>::eps/2),
00044       alpha(x)        {};
00045     
00046     C prec() { return this->upper()-this->lower(); }
00047     unsigned improve()
00048     {
00049       if(prec()> real<C>::eps)
00050         {
00051           C m = (this->lower()+this->upper())*0.5;
00052           int s =(alpha>m*m);
00053           if(s==1)
00054             { this->lower()=m; return 1;}
00055           else if(s==-1)
00056             { this->upper()=m; return 1;}
00057           else
00058             return 0;
00059         }
00060       else
00061         return 0;
00062     }
00063     
00064     void print(std::ostream & os)
00065     {
00066       os<<"Sqrt["<<this->lower()<<", "<<this->upper()<<"] of "<<alpha;
00067     }
00068   };
00069 
00071   template<class C>
00072   struct sqrt
00073   {
00074   protected:
00075     sqrt_rep<C>* _rep;
00076   public:
00077     sqrt(const real<C> & x): _rep(new sqrt_rep<C>(x)) {}
00078     sqrt(const C & x): _rep(new sqrt_rep<C>(x)) {}
00079     inline operator real<C> () { return real<C>(_rep); }
00080   };
00081   
00083   template<class C>
00084   real<C> Sqrt(real<C> a) {return sqrt<C>(a);}
00085 
00089   template<class C>
00090   real<C> Sqrt(const C a) {return sqrt<C>(a);}
00091   
00092   //--------------------------------------------------------------------
00093   template<class C,class R> struct root_rep;
00094   //--------------------------------------------------------------------
00095   template<class C,class R>
00096   int sturmcompare(root_rep<C,R>* a, root_rep<C,R>* b)
00097   {
00098     if (a->upper() < b->lower())
00099       return -1;
00100     else if (b->upper() < a->lower())
00101       return 1;
00102     else if (a->poly() == b->poly())
00103       {
00104         if (a->su != b->sl)
00105           return 0;
00106         else
00107           if(a->lower() < b->lower())
00108             return -1;
00109           else if(a->lower()> b->lower())
00110             return 1;
00111           else
00112             return 0;
00113       }
00114     else
00115       {
00116         // SturmSeq<R> s(a->poly(), Diff(a->poly())*b->poly(), SUBRES());
00117         SturmSeq<R> s(a->poly(), b->poly(), SUBRES());
00118         R l= std::max(a->lower(),b->lower()),
00119           u= std::min(a->upper(),b->upper());
00120         int v0 = variation(s,l) - variation(s,u);
00121         if(v0==0)
00122           if(a->lower() < b->lower())
00123             return -1;
00124           else if(a->lower()> b->lower())
00125             return 1;
00126           else
00127             return 0;
00128         else
00129           return v0 * b->su;
00130       }
00131   }
00132 
00133   //--------------------------------------------------------------------
00134   template<class R, class ZT=R>
00135   struct root_rep: public real_rep<R>, ALGEBRAIC::root_of<ZT>
00136   {
00137     int    sl, su;
00138     
00139     typedef typename ALGEBRAIC::root_of<ZT>::FT FT;
00140 
00141     root_rep(const UPolDse<ZT> & t, const FT & a, const FT &b)
00142       : ALGEBRAIC::root_of<ZT>(t,a,b)
00143     {
00144       let::assign(this->lower(),a);
00145       let::assign(this->upper(),b);
00146       sl=sign(UPOLDAR::eval_horner(this->poly(),this->lower()));
00147       su=sign(UPOLDAR::eval_horner(this->poly(),this->upper()));
00148     }
00149     root_rep(const UPolDse<ZT> & t, const FT & a, const FT &b, unsigned idx)
00150       : ALGEBRAIC::root_of<ZT>(t,a,b,idx)
00151     {
00152       let::assign(this->lower(),a);
00153       let::assign(this->upper(),b);
00154       sl=sign(UPOLDAR::eval_horner(this->poly(),this->lower()));
00155       su=sign(UPOLDAR::eval_horner(this->poly(),this->upper()));
00156     }
00157     
00158     root_rep(char *s, const R& a, const R& b)
00159       : real_rep<R>(a,b),
00160         ALGEBRAIC::root_of<ZT>(s)
00161     {
00162       sl=sign(UPOLDAR::eval_horner(this->poly(),a));
00163       su=sign(UPOLDAR::eval_horner(this->poly(),b));
00164     }
00165     
00166     UPolDse<ZT> pol() { return this->poly(); }
00167     
00168     unsigned improve()
00169     {
00170       if (prec()> real<R>::eps)
00171         {
00172           int s = sign(UPOLDAR::eval_horner(this->poly(),R((this->lower()+this->upper())/2)));
00173           if(s==0) {
00174             this->lower()=(this->lower()+this->upper())/2; this->upper()=this->lower();
00175           }
00176           else if(s*sl<0) {
00177             this->upper()=(this->lower()+this->upper())/2; su=s;
00178           }
00179           else {
00180             this->lower()=(this->lower()+this->upper())/2; sl=s;
00181           }
00182           return 1;
00183         }
00184       else
00185         return 0;
00186     }
00187     
00188     R prec() { return this->upper()-this->lower(); }
00189     
00190     int compare(real_rep<R>* b)
00191     {
00192 #if 1
00193       if (this->upper() < b->lower()) return -1;
00194       else if (b->upper() < this->lower()) return 1;
00195       else if ( (this->prec() < real<R>::eps) &&
00196                 (b->prec() < real<R>::eps) )
00197         return sturmcompare(this, dynamic_cast<root_rep<R,ZT>*>(b));
00198       else
00199         {
00200           int i1=this->improve(), i2=b->improve();
00201           if(i1 || i2)
00202             return (this->compare(b));
00203         }
00204 #endif
00205       return sturmcompare(this, dynamic_cast<symbolic::root_rep<R,ZT>*>(b));
00206     }
00207     
00208     void print(std::ostream & os) const
00209     {
00210       os<<"Rootof(";
00211       UPOLDAR::print(os,this->poly());
00212       os<<", ["<<this->lower()<<", "<<this->upper()<<"])";
00213     }
00214   };
00215 
00216   //--------------------------------------------------------------------
00222   template<class R, class Z=R>
00223   struct root
00224   {
00225     typedef typename ALGEBRAIC::root_of<Z>::FT FT;
00226   protected:
00227     root_rep<R,Z>* rep_;
00228   public:
00229     root(const UPolDse<Z> & t, const FT& a, const FT& b)
00230       :rep_(new root_rep<R,Z>(t,a,b)) {}
00231     root(const UPolDse<Z> & t, const FT& a, const FT& b,unsigned idx)
00232       :rep_(new root_rep<R,Z>(t,a,b,idx)) {}
00233     root_rep<R,Z>* operator -> () {return rep_;}
00234     root_rep<R,Z>* operator -> () const {return rep_;}
00235     root_rep<R,Z>  rep         () {return *rep_;}
00236 
00237     inline operator real<R> () { return real<R> (rep_); }
00238   };
00239 } //symbolic
00240 //====================================================================
00242 template<class R> 
00243 std::ostream& operator<<(std::ostream& os, const symbolic::root<R> &a)
00244 {
00245   a->print(os);
00246 }
00247 //--------------------------------------------------------------------
00248 // Comparison operators:
00249 //--------------------------------------------------------------------
00251 template<class R> inline
00252 bool operator< (symbolic::real<R> a, symbolic::real<R> b) 
00253 { 
00254   return (a.compare(b)>0); 
00255 }
00257 template<class R> inline
00258 bool operator> (symbolic::real<R> a, symbolic::real<R> b) 
00259 {  
00260   return (a.compare(b)<0); 
00261 }
00263 template<class R> inline
00264 bool operator< (const R& a, symbolic::real<R> b) { return (compare(b,a)<0); }
00266 template<class R> inline
00267 bool operator> (const R& a, symbolic::real<R> b) { return (compare(b,a)>0); }
00269 template<class R> inline
00270 bool operator< (symbolic::real<R> a, const R& b) { return (compare(a,b)>0); }
00272 template<class R> inline
00273 bool operator> (symbolic::real<R> a, const R& b) { return (compare(a,b)<0); }
00274 
00275 //--------------------------------------------------------------------
00289 template < typename C_T,
00290            typename UPOL_T >
00291 symbolic::root<C_T,typename UPOL_T::coeff_t> RealRoot(const UPOL_T& p, unsigned idx)
00292 {
00293   typedef typename UPOL_T::coeff_t RT;
00294   typedef typename Sturm<RT>::RO_t                   RO_t;
00295   typedef std::vector<RO_t>                          Cont;
00296   typedef std::back_insert_iterator< Cont >          OutIter;
00297   
00298   Cont sol;
00299   OutIter tt(sol);
00300   Sturm<RT> mth;
00301 //  ALGEBRAIC::Solve(p, tt, mth);
00302   ALGEBRAIC::solve_sturm(p, tt, mth);
00303   std::stable_sort( sol.begin(), sol.end(), ALGEBRAIC::Refine_compare());
00304 
00305   Seq<RO_t> solutions(sol);
00306   assert(idx<solutions.size());
00307   RO_t s=solutions[idx];
00308   return symbolic::root<C_T,RT>(s.poly(),s.left(),s.right(),idx);
00309 }
00310 //--------------------------------------------------------------------
00311 template<typename T, typename C>
00312 inline bool has_type(symbolic::real_rep<C>* object)
00313 {
00314     return dynamic_cast<T*>(object) != 0;
00315 }
00316 
00317 
00318 
00319 //--------------------------------------------------------------------
00323 template<class FT, class C, class MTH>
00324 void AppendSol(Seq< symbolic::real<FT> > & res,
00325                const UPolDse<C> & P, 
00326                const Symbolic<FT,MTH> & mth,
00327                const FT& a, const FT & b)//, const SturmSeq<C> & s)
00328 {
00329   assert(a<=b);
00330   //  std::cout<<"Closed root "<<P<<" "<<a<<" "<<b<<std::endl;
00331   //  typedef typename NumberTraits<C>::FT FT;
00332   typedef FT sol_t;
00333   Seq<Interval<sol_t> > sol = solve(P,IslBzBdg<FT>(1e-2),a,b);
00334   //Seq<sol_t> sol; AppendSol(sol,P,Bezier<sol_t,SyNum>(1e-2),a,b);
00335   //  AppendSol(sol,P,Bezier<sol_t,Isolation>(1e-2),a,b);
00336   int v0=0;
00337   if(v0==1)
00338     res.push_back(symbolic::root<FT,C>(P,a,b));
00339   else if(v0>1)
00340     {
00341       std::cout<<"Isolation still needed "<<a<<" "<<b<<std::endl;
00342 //       FT m=(a+b)/2;
00343 //       AppendSol(res,P,mth,a,m);
00344 //       AppendSol(res,P,mth,m,b);
00345     }
00346 }
00347 //--------------------------------------------------------------------
00348 template<class FT, class C, class MTH>
00349 void AppendSol(Seq< symbolic::real<FT> > & res,
00350                const UPolDse<C> & P, const Symbolic<FT,MTH> & mth)
00351 {
00352   using let::assign;
00353   typedef typename NumberTraits<C>::FT  field_t;
00354   typedef FT sol_t;
00355   SturmSeq<C> s(P, diff(P), HABICHT());
00356   if(degree(s[s.size()-1])!=0)
00357     {
00358       std::cout<<"Not square free"<<std::endl;
00359       //      AppendSol(res, P/s[s.size()-1],mth);
00360     }
00361   else 
00362     {
00363       Seq<Interval<double> > sol = solve(P, IslBzBdg<double>(1e-3));
00364       //  Seq<double> sol = Isole(P, Bezier<double,Bounding>(1e-3));
00365       //Seq<sol_t> sol = Isole(P, MTH(1e-6));
00366       //  std::cout<<sol<<std::endl;
00367       
00368       FT a,b;
00369       for(unsigned i=0; i<sol.size(); i++)
00370         {
00371           assign(a,sol[i].inf()); assign(b,sol[i].sup());
00372           //      AppendSol(res,P,Bezier<field_t,Isolation>(),a,b);
00373           //      std::cout<<a<<" "<<b<<" "<<v0<<std::endl;
00374           if(a!= b)
00375             {
00376               int v0 = variation(s,a) - variation(s,b);
00377               if(v0==1)
00378                 res.push_back(symbolic::root<FT,C>(P, a, b));
00379               else if(v0>1)
00380                 AppendSol(res,P,mth,a,b);
00381         }
00382           else if(P(a)==0)
00383             res.push_back(symbolic::root<FT,C>(P, a, a));
00384           
00385         }
00386     }
00387 }
00388 
00389 //--------------------------------------------------------------------
00390 template<class C, class FT>
00391 Seq< symbolic::real<FT> >
00392 solve(const UPolDse<C> & P, const Symbolic<FT> & mth)
00393 { 
00394   Seq< symbolic::real<FT> > res;
00395   //  UPolDse<C> Pr = square_free(P);
00396   UPolDse<C> Pr = P;
00397   AppendSol(res, Pr, mth);
00398   return res;
00399 }
00400 //--------------------------------------------------------------------
00401 __END_NAMESPACE_SYNAPS
00402 //--------------------------------------------------------------------
00403 #endif // synaps_solve_Symbolic_H
00404 

SYNAPS DOCUMENTATION
logo