realroot_doc 0.1.1
|
00001 /******************************************************************** 00002 * Author(s): A. Mantzaflaris, GALAAD, INRIA 00003 ********************************************************************/ 00004 #ifndef _realroot_SOLVER_FIRST_ROOT_CONFRAC_H 00005 #define _realroot_SOLVER_FIRST_ROOT_CONFRAC_H 00006 /********************************************************************/ 00007 00008 # include <realroot/Interval.hpp> 00009 00010 # include <realroot/homography.hpp> 00011 # include <realroot/sign_variation.hpp> 00012 # include <realroot/univariate_bounds.hpp> 00013 # include <stack> 00014 # include <realroot/solver.hpp> 00015 00016 # define NO_ROOT -1.0 00017 # define TMPL template<class POL> 00018 # define TMPLR template<class Real, class POL> 00019 # define N_ITER 10000 00020 00021 namespace mmx { 00022 00023 struct CFfirstIsolate{}; 00024 struct CFfirstApproximate{}; 00025 struct CFfirstFloor{}; 00026 struct CFallIsolate{}; 00027 struct CFseparate{}; 00028 struct CFdecide{}; 00029 00030 //bit_size support for QQ 00031 00032 // inline long bit_size(QQ q) 00033 // { 00034 // long n,d; 00035 // n= bit_size( numerator(q) ); 00036 // d= bit_size(denominator(q) ); 00037 // return( n>d ? n : d ) ; 00038 // } 00039 00040 00041 /* ******************************************************** */ 00042 /* Represents the polynomial on an interval [u,v]. 00043 Keeps homography information to map [0,inf] back to [u,v]. 00044 Main operations are shift, contraction and reciprocal. 00045 */ 00046 TMPL 00047 class interval_rep 00048 { 00049 typedef typename POL::scalar_t C; 00050 00051 POL f; 00052 homography<C> hg; 00053 00054 public: 00055 00056 interval_rep(){ } 00057 00058 interval_rep(const POL p) 00059 { 00060 f = p; 00061 hg = homography<C>() ; 00062 } 00063 00064 interval_rep(const POL p, homography<C> h) 00065 { 00066 f = p; 00067 hg = h; 00068 } 00069 00070 00071 interval_rep(const POL p, C u, C v ) 00072 { 00073 f = p; 00074 hg = homography<C>() ; 00075 00076 shift_box ( u ); 00077 contract_box ( v-u ); 00078 reverse_and_shift_box (1); 00079 //print(); 00080 } 00081 00082 /* Access the equation */ 00083 POL inline poly() {return f;}; 00084 /* Access the homography */ 00085 homography<C> hom() { return hg; } 00086 00087 /* Access the domain */ 00088 template<class Real> 00089 Interval<Real> domain() 00090 { 00091 Real l, r; 00092 Interval<Real> s ; 00093 //lim to 0 00094 if ( hg.b!=0 && hg.d!=0 ) 00095 l= as<Real>(hg.b)/as<Real>(hg.d); 00096 else if ( hg.d==0 ) 00097 l= 10000000; 00098 else if ( hg.b==0 ) 00099 l= 0 ; 00100 else 00101 l= as<Real>(hg.a)/as<Real>(hg.c) ; 00102 //lim to inf 00103 if ( hg.a!=0 && hg.c!=0 ) 00104 r= as<Real>(hg.a)/as<Real>(hg.c); 00105 else if ( hg.c==0 ) 00106 r=10000000; 00107 else if ( hg.a==0 ) 00108 r= 0 ; 00109 else 00110 r= as<Real>(hg.b)/as<Real>(hg.d); 00111 00112 if ( l<=r ) s= Interval<Real>(l,r); 00113 else s= Interval<Real>(r,l); 00114 00115 return s; 00116 } 00117 00118 /* Access the size of the domain */ 00119 template<class Real> 00120 Real inline width() 00121 { 00122 return this->template domain<Real>().width(); 00123 } 00124 00125 /* Access the point where t\in\RR_+ corresponds */ 00126 template<class Real> 00127 Real inline point(C & t) 00128 { 00129 return ( as<Real>(hg.a)*as<Real>(t) + as<Real>(hg.b) ) / 00130 ( as<Real>(hg.c)*as<Real>(t) + as<Real>(hg.d) ) ; 00131 } 00132 00133 C middle() 00134 { 00135 C t(hg.d / hg.c); 00136 00137 if (t>0) 00138 return ( t ) ; 00139 else 00140 return C(1); 00141 } 00142 00143 unsigned sign_var() 00144 { 00145 return sign_variation(f.begin(),f.end()) ; 00146 } 00147 00148 00149 // Shift the polynomial by t 00150 void shift_box(const C& t) 00151 { 00152 int s, k,j, sz= f.size(); 00153 00154 for ( s = sz, j = 0; j <= s-2; j++ ) 00155 for( k = s-2; k >= j; k-- ) 00156 f[k] += t*f[k+1]; 00157 00158 //update homography 00159 hg.shift_hom(t); 00160 }; 00161 00162 // x = t*x 00163 void contract_box(const C & t ) 00164 { 00165 int s, sz= f.size(); 00166 00167 for ( s = 0 ; s < sz; ++s ) 00168 f[s] *= pow(t,s) ; 00169 00170 //update homography 00171 hg.contract_hom(t); 00172 }; 00173 00174 // x = 1/x -- parameter t=1 unused for now 00175 void reverse_box(const C & t=1 ) 00176 { 00177 unsigned s, l= f.size()-1; 00178 00179 for (s = 0 ; s <= l/2; s++ ) 00180 std::swap(f[s], f[l-s]); 00181 00182 //update homography 00183 hg.reciprocal_hom(t); 00184 }; 00185 00186 // x = 1/(x+1) -- parameter t=1 unused for now 00187 void inline reverse_and_shift_box(const C & t=1) 00188 { 00189 reverse_box(t); 00190 shift_box (C(1)); 00191 }; 00192 00193 void print() 00194 { 00195 std::cout << "----------Interval---------------" << "\n" ; 00196 std::cout << poly() << "\n" ; 00197 std::cout<< "("<<hg.a <<"x + " << hg.b<<")/("<<hg.c<<"x+ "<<hg.d << ")"<<", sv:"<<sign_var() <<std::endl; 00198 std::cout << domain() << "\n" ; 00199 std::cout << "-------------------------------" << "\n" ; 00200 } 00201 00202 }; /* Interval_rep */ 00203 00204 00205 /* ******************************************************** */ 00206 /* 00207 Solver interface 00208 */ 00209 TMPLR 00210 struct solver_cffirst { 00211 00212 interval_rep<POL> ir; 00213 Real eps; 00214 00215 solver_cffirst(interval_rep<POL> p){ 00216 ir = p; 00217 eps= as<Real>(1e-7); 00218 } 00219 00220 interval_rep<POL> first_root(); 00221 Interval<Real> first_root_isolate(); 00222 Real first_root_approximate(); 00223 Real first_root_floor(); 00224 00225 Seq<interval_rep<POL> > all_roots(); 00226 Seq<Interval<Real> > all_roots_isolate(); 00227 Seq<Real> all_roots_separate(); 00228 }; 00229 00230 /* 00231 Main routine: 00232 Returns an "interval_rep" containing the minimum >0 root. 00233 */ 00234 TMPLR 00235 interval_rep<POL> solver_cffirst<Real,POL>::first_root() 00236 { 00237 typedef interval_rep<POL> BOX; 00238 std::stack<BOX * > uboxes; 00239 typedef typename POL::scalar_t C; 00240 00241 POL zero(0); 00242 Interval<Real> mid(0); 00243 BOX * b, * tmp; 00244 POL p; 00245 unsigned s, iters=0; 00246 00247 Interval<Real> I; 00248 AkritasBound<C> lb; 00249 //HongBound<C> lb; 00250 //Kioustelidis<C> lb; 00251 //NISP<C> lb; 00252 //Cauchy<C> lb; 00253 00254 C lower; 00255 b= new BOX(ir); 00256 uboxes.push (b); 00257 00258 while ( !uboxes.empty() && iters++ < N_ITER ) 00259 00260 { 00261 b = uboxes.top() ; 00262 p = b->poly() ; 00263 uboxes.pop(); 00264 00265 if ( p==zero && (!uboxes.empty()) ) { 00266 return *b;} 00267 00268 s = b->sign_var() ; 00269 I = b->template domain<Real>(); 00270 00271 if ( s==1 && (!uboxes.empty()) ) { 00272 return *b;} 00273 00274 if ( s > 0 ) 00275 { 00276 if ( b->template width<Real>() < eps ) 00277 {std::cout<< "first_root: multiple root?"<<b->template domain<Real>() <<std::endl;} 00278 else 00279 { 00280 lower= lb.lower_bound(p) ; 00281 if ( lower!=0 ) 00282 { 00283 if ( p( lower ) == 0 ) 00284 return *b; 00285 00286 tmp= new BOX( *b ) ; 00287 free(b); 00288 tmp->shift_box( lower ); 00289 uboxes.push (tmp); 00290 } 00291 else 00292 { 00293 // right box 00294 tmp = new BOX( *b ) ; 00295 tmp->shift_box( 1 ); 00296 uboxes.push ( tmp ); 00297 //middle if needed 00298 if ( p( Real(1) ) == Real(0) ) 00299 { tmp = new BOX(zero, b->hom() ) ; 00300 uboxes.push ( tmp ); } 00301 //left 00302 tmp = new BOX( *b ) ; 00303 tmp->reverse_and_shift_box( 1 ); 00304 tmp->reverse_box( 1 ); 00305 uboxes.push ( tmp ); 00306 00307 free(b); 00308 } 00309 } 00310 } 00311 } 00312 /* -1 = No positive root */ 00313 return BOX(-1); 00314 } 00315 00316 /* 00317 Returns a list of "interval_rep"s isolating the positive roots, 00318 in increasing order. 00319 */ 00320 TMPLR 00321 Seq<interval_rep<POL> > solver_cffirst<Real,POL>::all_roots() 00322 { 00323 typedef interval_rep<POL> BOX; 00324 std::stack<BOX * > uboxes; 00325 typedef typename POL::scalar_t C; 00326 00327 Real ev(0); 00328 Seq<interval_rep<POL> > sols; 00329 POL zero(0); 00330 Interval<Real> mid(0); 00331 BOX * b, * tmp; 00332 POL p; 00333 unsigned s, iters=0; 00334 00335 Interval<Real> I; 00336 AkritasBound<C> lb; 00337 //HongBound<C> lb; 00338 //Kioustelidis<C> lb; 00339 //NISP<C> lb; 00340 //Cauchy<C> lb; 00341 00342 C lower; 00343 b= new BOX(ir); 00344 uboxes.push (b); 00345 00346 while ( !uboxes.empty() && iters++ < N_ITER ) 00347 { 00348 b = uboxes.top() ; 00349 p = b->poly() ; 00350 uboxes.pop(); 00351 00352 if ( p==zero && (!uboxes.empty()) ) { 00353 sols<< *b;} 00354 00355 I = b->template domain<Real>(); 00356 // Interval<Real> ev= p( I ) ; 00357 // if ( ev.m * ev.M > 0 ) continue; 00358 s = b->sign_var() ; 00359 if ( s==1 && (!uboxes.empty()) ) { 00360 sols << *b; continue; } 00361 00362 if ( s > 0 ) 00363 { 00364 if ( (!uboxes.empty()) && b->template width<Real>() < eps*.1 ) 00365 {std::cout<< 00366 "all_roots: multiple root?"<<b->template domain<Real>() <<std::endl; 00367 std::cout<< b->poly()<<" , "<<b->template width<Real>()<<std::endl; 00368 std::cout<<"source: "<<ir.poly()<<std::endl; 00369 00370 } 00371 else 00372 { 00373 lower= lb.lower_bound(p) ; 00374 if ( lower!=0 ) 00375 { 00376 00377 let::assign(ev,lower); 00378 if ( p(ev) == 0 ) 00379 sols<< *b; 00380 00381 tmp= new BOX( *b ) ; 00382 free(b); 00383 tmp->shift_box( lower ); 00384 uboxes.push (tmp); 00385 } 00386 else 00387 { 00388 // right box 00389 tmp = new BOX( *b ) ; 00390 tmp->shift_box( 1 ); 00391 uboxes.push ( tmp ); 00392 //middle if needed 00393 ev=1; 00394 if ( p( ev ) == Real(0) ) 00395 { tmp = new BOX(zero, b->hom() ) ; 00396 uboxes.push ( tmp ); } 00397 //left 00398 tmp = new BOX( *b ) ; 00399 tmp->reverse_and_shift_box( 1 ); 00400 tmp->reverse_box( 1 ); 00401 uboxes.push ( tmp ); 00402 00403 free(b); 00404 } 00405 } 00406 } 00407 } 00408 return sols; 00409 } 00410 00411 /* 00412 Return isolation box of the first positive root, [-1,-1] if none exists. 00413 */ 00414 TMPLR 00415 Interval<Real> solver_cffirst<Real,POL>::first_root_isolate() 00416 { 00417 interval_rep<POL> a( first_root() ); 00418 typename POL::scalar_t t(1); 00419 00420 if ( a.poly()== POL(-1) ) 00421 return (0); 00422 else 00423 if (a.poly()==POL(0) ) 00424 return( a.template point<Real>(t) ); 00425 else 00426 return ( a.template domain<Real>() ); 00427 } 00428 00429 TMPLR 00430 Real solver_cffirst<Real,POL>::first_root_approximate() 00431 { 00432 typedef interval_rep<POL> BOX; 00433 typedef typename POL::scalar_t C; 00434 BOX * l, * r= new BOX( first_root() ) ; 00435 C t(1); 00436 00437 if ( r->poly()== POL(-1) ) 00438 return (0); 00439 else 00440 if (r->poly()==POL(0) ) 00441 return( r->template point<Real>(t) ); 00442 else 00443 { 00444 /* Approximate */ 00445 while ( r->template width<Real>() > eps ) 00446 { 00447 t= r->middle(); 00448 00449 if ( r->poly()( t ) == 0 ) return( r->template point<Real>(t) ); 00450 l= new BOX( *r) ; 00451 l->shift_box( t ); 00452 00453 if ( l->sign_var() ) 00454 { 00455 free(r); 00456 r=l; 00457 continue; 00458 } 00459 else 00460 { 00461 free(l); 00462 r->contract_box(t); 00463 r->reverse_and_shift_box(1); 00464 r->reverse_box(1); 00465 } 00466 } 00467 00468 return ( r->template domain<Real>() ); 00469 } 00470 } 00471 00472 TMPLR 00473 Real solver_cffirst<Real,POL>::first_root_floor() 00474 { 00475 typedef interval_rep<POL> BOX; 00476 typedef typename POL::scalar_t C; 00477 00478 BOX * l, * r= new BOX( first_root() ) ; 00479 Interval<Real> I; 00480 C t(1); 00481 if ( r->poly()== POL(-1) ) 00482 return (0); 00483 else 00484 if (r->poly()==POL(0) ) 00485 return( r->template point<Real>(t) ); 00486 else 00487 { 00488 00489 I= r->template domain<Real>(); 00490 if ( r->poly() == POL(0) ) return as<Real> (floor(as<double>(r->template point<Real>(t))) ); 00491 while ( rfloor(I.m)!=rfloor(I.M) ) 00492 { 00493 t= r->middle(); 00494 if ( r->poly()( t ) == 0 ) return as<Real>( floor(as<double>(r->template point<Real>(t))) ); 00495 00496 l= new BOX( *r) ; 00497 l->shift_box( t ); 00498 00499 if ( l->sign_var() ) 00500 { 00501 free(r); 00502 r=l; 00503 I= r->template domain<Real>(); 00504 continue; 00505 } 00506 else 00507 { 00508 free(l); 00509 r->reverse_and_shift_box(); 00510 r->reverse_box(); 00511 I= r->template domain<Real>(); 00512 } 00513 } 00514 } 00515 return as<Real>( floor(as<double>(I.m)) ); 00516 }/*first_root_floor*/ 00517 00518 TMPLR 00519 Seq<Interval<Real> > solver_cffirst<Real,POL>::all_roots_isolate() 00520 { 00521 Seq<interval_rep<POL> > a( all_roots() ); 00522 Seq<Interval<Real> > s; 00523 typename POL::scalar_t t(1); 00524 00525 for ( unsigned i=0; i<a.size(); ++i) 00526 if (a[i].poly()==POL(0) ) 00527 s<< Interval<Real>(a[i].template point<Real>(t) ); 00528 else 00529 s<< a[i].template domain<Real>(); 00530 00531 return s; 00532 } 00533 00534 TMPLR 00535 Seq<Real> solver_cffirst<Real,POL>::all_roots_separate() 00536 { 00537 Seq< Interval<Real> > ints; 00538 Seq<Real> sep; 00539 00540 ints= all_roots_isolate(); 00541 for (unsigned i=1; i<ints.size(); ++i) 00542 sep << (ints[i-1].M + ints[i].m)*Real(0.5) ; 00543 00544 return sep; 00545 } 00546 00547 //-------------------------------------------------------------------- 00548 template<class Ring> 00549 struct solver<Ring, CFfirstIsolate > { 00550 00551 typedef typename Ring::scalar_t base_t; 00552 00553 template<class Real, class POL> static Interval<Real> 00554 solve(const POL& p,const base_t& u,const base_t& v); 00555 00556 template<class Real, class POL> static Interval<Real> 00557 solve(const POL& p); 00558 }; 00559 00564 template<class Ring> 00565 template<class Real, class POL> 00566 Interval<Real> 00567 solver<Ring,CFfirstIsolate >::solve(const POL& p, 00568 const base_t & u, 00569 const base_t & v) { 00570 00571 interval_rep<POL> i(p,u,v); 00572 solver_cffirst<Real,POL> slv(i); 00573 00574 return slv.first_root_isolate(); 00575 } 00576 00580 template<class Ring> 00581 template<class Real, class POL> 00582 Interval<Real> 00583 solver<Ring,CFfirstIsolate >::solve(const POL& p) { 00584 00585 interval_rep<POL> i(p); 00586 solver_cffirst<Real,POL> slv(i); 00587 00588 return slv.first_root_isolate(); 00589 } 00590 00591 00592 //-------------------------------------------------------------------- 00593 template<class Ring> 00594 struct solver<Ring, CFfirstApproximate > { 00595 00596 typedef typename Ring::scalar_t base_t; 00597 00598 template<class Real, class POL> static Real 00599 solve(const POL& p, const base_t& u, const base_t& v); 00600 00601 template<class Real, class POL> static Real 00602 solve(const POL& p); 00603 }; 00604 00609 template<class Ring> 00610 template<class Real, class POL> 00611 Real 00612 00613 solver<Ring,CFfirstApproximate >::solve(const POL& p, 00614 const base_t& u, const base_t& v) { 00615 00616 00617 interval_rep<POL> i(p,u,v); 00618 solver_cffirst<Real,POL> slv(i); 00619 00620 return slv.first_root_approximate(); 00621 } 00622 00626 template<class Ring> 00627 template<class Real, class POL> 00628 Real 00629 solver<Ring,CFfirstApproximate >::solve(const POL& p) { 00630 00631 00632 interval_rep<POL> i(p); 00633 solver_cffirst<Real,POL> slv(i); 00634 00635 return slv.first_root_approximate(); 00636 } 00637 00638 00639 //-------------------------------------------------------------------- 00640 template<class Ring> 00641 struct solver<Ring, CFfirstFloor> { 00642 typedef typename Ring::Scalar base_t; 00643 00644 template<class Real, class POL> static Real 00645 solve(const POL& p, const base_t& u, const base_t& v); 00646 00647 template<class Real,class POL> static Real 00648 solve(const POL& p); 00649 }; 00650 00655 template<class Ring> 00656 template<class Real,class POL> 00657 Real 00658 solver<Ring,CFfirstFloor >::solve(const POL& p, 00659 const base_t& u, const base_t& v) { 00660 00661 interval_rep<POL> i(p,u,v); 00662 solver_cffirst<Real,POL> slv(i); 00663 00664 return slv.first_root_floor(); 00665 } 00666 00670 template<class Ring> 00671 template<class Real, class POL> 00672 Real 00673 solver<Ring,CFfirstFloor >::solve(const POL& p) { 00674 00675 interval_rep<POL> i(p); 00676 solver_cffirst<Real,POL> slv(i); 00677 00678 return slv.first_root_floor(); 00679 } 00680 00681 00682 //-------------------------------------------------------------------- 00683 template<class Ring> 00684 struct solver<Ring, CFallIsolate > { 00685 00686 typedef typename Ring::Scalar base_t; 00687 00688 template<class Real, class POL> static Seq<Interval<Real> > 00689 solve(const POL& p,const base_t& u,const base_t& v); 00690 00691 template<class Real,class POL> static Seq<Interval<Real> > 00692 solve(const POL& p); 00693 }; 00694 00698 template<class Ring> 00699 template<class Real, class POL> 00700 Seq<Interval<Real> > 00701 solver<Ring,CFallIsolate >::solve(const POL& p, 00702 const base_t& u, const base_t& v) { 00703 00704 interval_rep<POL> i(p,u,v); 00705 solver_cffirst<Real,POL> slv(i); 00706 00707 return slv.all_roots_isolate(); 00708 } 00709 00713 template<class Ring> 00714 template<class Real,class POL> 00715 Seq<Interval<Real> > 00716 solver<Ring,CFallIsolate >::solve(const POL& p) { 00717 00718 interval_rep<POL> i(p); 00719 solver_cffirst<Real,POL> slv(i); 00720 00721 return slv.all_roots_isolate(); 00722 } 00723 00724 00725 //-------------------------------------------------------------------- 00726 template<class Ring> 00727 struct solver<Ring, CFseparate > { 00728 00729 typedef typename Ring::Scalar base_t; 00730 00731 template<class Real,class POL> static Seq<Real> 00732 solve(const POL& p,const base_t& u,const base_t& v); 00733 00734 template<class Real, class POL> static Seq<Real> 00735 solve(const POL& p); 00736 }; 00737 00741 template<class Ring> 00742 template<class Real, class POL> 00743 Seq<Real> 00744 solver<Ring,CFseparate >::solve(const POL& p, 00745 const base_t& u, const base_t& v) { 00746 00747 interval_rep<POL> i(p,u,v); 00748 solver_cffirst<Real,POL> slv(i); 00749 00750 return slv.all_roots_separate(); 00751 } 00752 00756 template<class Ring> 00757 template<class Real,class POL> 00758 Seq<Real> 00759 solver<Ring,CFseparate >::solve(const POL& p) { 00760 00761 interval_rep<POL> i(p); 00762 solver_cffirst<Real,POL> slv(i); 00763 00764 return slv.all_roots_separate(); 00765 } 00766 00767 00768 //-------------------------------------------------------------------- 00769 template<class Ring> 00770 struct solver<Ring,CFdecide> { 00771 00772 template<class POL> static bool 00773 solve(const POL& p); 00774 }; 00775 00779 template<class Ring> 00780 template<class POL> 00781 bool 00782 solver<Ring,CFdecide>::solve(const POL& p) { 00783 00784 interval_rep<POL> i(p); 00785 solver_cffirst<QQ,POL> slv(i); 00786 00787 return ( slv.all_roots_isolate().size() ); 00788 } 00789 00790 00791 } //namespace realroot 00792 00793 #undef TMPL 00794 #undef TMPLR 00795 #undef NO_ROOT 00796 #undef N_ITER 00797 #endif // _realroot_SOLVER_FIRST_ROOT_CONFRAC_H