realroot_doc 0.1.1
|
00001 /******************************************************************** 00002 * Author(s): A. Mantzaflaris, GALAAD, INRIA 00003 ********************************************************************/ 00004 00005 #ifndef _realroot_SOLVE_MV_CONFRAC_BOXREP_H 00006 #define _realroot_SOLVE_MV_CONFRAC_BOXREP_H 00007 /********************************************************************/ 00008 00010 # include <realroot/ring.hpp> 00011 # include <realroot/polynomial_tensor.hpp> 00013 00014 00015 00016 # include <realroot/polynomial.hpp> 00017 # include <realroot/homography.hpp> 00018 # include <realroot/sign_variation.hpp> 00019 # include <realroot/Interval.hpp> 00020 # include <stack> 00021 00022 # include <realroot/solver_ucf.hpp> 00023 # include <realroot/solver_uv_bspline.hpp> 00024 00025 // # include <realroot/solver_mv_monomial_tests.hpp> 00026 00027 # define DPOL polynomial<double,with<MonomialTensor> > 00028 00029 # define INFO 1 00030 //# define DIVISION 00031 # define TODOUBLE as<double> 00032 00033 00034 //==================================================================== 00035 namespace mmx { 00036 //==================================================================== 00037 namespace realroot { 00038 00040 template<class POL> 00041 class box_rep 00042 { 00043 typedef typename POL::scalar_t C; 00044 typedef Seq<POL *> system_t; 00045 typedef std::stack<box_rep<POL> *> STACK; 00046 /*----------------------------------------------*/ 00047 00048 unsigned dim; 00049 homography_mv<C> hg; // Homography 00050 //homography_mv<int> hg; // Homography 00051 00052 00053 public: 00054 00055 //int td; 00056 Seq<POL> S; // System 00057 00058 void inline update_data() 00059 { 00060 00061 //C t; 00062 00063 // scale coefficients 00064 #ifdef DIVISION 00065 for( unsigned i=0; i<S.size(); i++ ){ 00066 t= *std::max_element( (S[i]).begin(), (S[i]).end() ); 00067 S[i]= S[i]/t; 00068 } 00069 #endif 00070 00071 // Precondition 00072 Seq<double> c= this->point( this->middle() ) ; 00073 //double *fc, *jc, *ijc; 00074 Seq<POL> S1= S; 00075 00076 // DPOL * J= jacobian(S1); 00077 00078 // jc= eval_poly_matrix( c, J, dim); // Jacobian evaluated on c 00079 // ijc= new double[dim*dim]; 00080 // linear::LUinverse(ijc, jc, dim); 00081 00082 // for( unsigned i=0; i<dim; i++ ){ 00083 // S[i]=0; 00084 // for( unsigned j=0; j<dim; j++ ) 00085 // S[i] += ijc[i*dim+j] * S1[j] ; 00086 // } 00087 } 00088 00089 box_rep() {}; 00090 00091 box_rep(Seq<POL>& sys, homography_mv<C>& h) 00092 { 00093 hg = h ; 00094 dim= h.size(); 00095 S= sys; 00096 00097 update_data(); 00098 }; 00099 00100 //point of subdivision in i-direction 00101 box_rep( box_rep<POL> b, int i) 00102 { 00103 dim= b.nbvar(); 00104 hg = b.homography(); 00105 00106 hg.shift_hom(b.middle(i) ,i); 00107 hg.colapse(); 00108 00109 S= b.system(); 00110 }; 00111 00112 00113 box_rep( Seq<POL>& sys, unsigned d) 00114 { 00115 dim=d; 00116 hg = homography_mv<C>(dim) ; 00117 //hg = homography_mv<int>(dim) ; 00118 S= sys; 00119 } 00120 00121 //Destroy 00122 ~box_rep() {}; 00123 00124 void restrict( Seq<Interval<C> > & dom0 ) 00125 { 00126 //Seq<Interval<int> > dom; 00127 //let::assign(dom,dom0); 00128 00129 unsigned i,j; 00130 00131 for (i=0; i!=dim; i++) 00132 { 00133 hg.shift_hom ( dom0[i].m , i ); 00134 hg.contract_hom ( dom0[i].width(), i ); 00135 hg.reciprocal_hom( 1 , i ); 00136 hg.shift_hom ( 1 , i ); 00137 hg.reciprocal_hom( 1 , i );//mirror again 00138 for (j=0; j!=S.size(); j++) 00139 { 00140 shift ( S[j].rep(), dom0[i].m , i); 00141 contraction( S[j].rep(), dom0[i].width(), i); 00142 reciprocal ( S[j].rep(), i); 00143 shift ( S[j].rep(), C(1), i); 00144 reciprocal ( S[j].rep(), i);//mirror again 00145 } 00146 } 00147 update_data(); 00148 } 00149 00151 inline Seq<POL> system() { return S; } 00152 inline homography_mv<C> homography() { return this->hg; } 00153 inline POL system(unsigned i) { return S[i]; } 00154 inline unsigned nbvar() { return dim; } 00155 inline unsigned nbpol() { return S.size(); } 00156 00157 template<class FT> 00158 FT volume() 00159 { 00160 Seq<Interval<FT> > s; 00161 FT v(1); 00162 00163 s= domain<FT>(); 00164 00165 for (unsigned i=0; i!=s.size(); i++ ) 00166 v *= s[i].width(); 00167 00168 return v; 00169 } 00170 00171 template<class C> 00172 inline int signof_det(DPOL **p) 00173 { 00174 00175 return p[0]; 00176 } 00177 00178 template<class C> 00179 int** submatrix(C **matrix, int order, int i, int j) 00180 { 00181 00182 C **subm; 00183 int p, q; // Indexes for matrix 00184 int a = 0, b; // Indexes for subm 00185 subm = new int* [order - 1]; 00186 00187 for(p = 0; p < order; p++) { 00188 if(p==i) continue; //Skip ith row 00189 subm[a] = new C[order - 1]; 00190 00191 b = 0; 00192 00193 for(q = 0; q< order; q++) { 00194 if(q==j) continue; //Skip jth column 00195 subm[a][b++] = matrix[p][q]; 00196 } 00197 a++; //Increment row index 00198 } 00199 return subm; 00200 } 00201 00202 // Compute matrix determinant, recursively 00203 template<class C> 00204 C det(C **matrix, int order) 00205 { 00206 if(order == 1) 00207 return **matrix; // Matrix is of order one 00208 00209 int i; 00210 C ev(0); 00211 for(i = 0; i < order; i++) 00212 ev += (i%2==0?1:-1)* matrix[i][0] * det(submatrix(matrix, order, i, 0), order - 1); 00213 return ev; 00214 } 00215 00216 00217 inline int signof(DPOL * p) 00218 { 00219 00220 Interval<double> ev; 00221 //int dim= p->nbvar(); 00222 00223 tensor::eval( ev , p->rep() , 00224 this->template domain<double>() , dim ); 00225 00226 if (ev< .1e-15) return (0); 00227 return (ev>0?1:-1); 00228 } 00229 00230 00231 //inline int tdeg() { return td ; } 00232 homography_mv<C> hom() { return hg; } 00233 POL system(const int i) { return S[i]; } 00234 00235 template<class FT> 00236 Seq<Interval<FT> > domain() 00237 { 00238 FT l, r; 00239 Seq<Interval<FT> > s ; 00240 00241 for ( unsigned i=0; i!=dim; ++i ) 00242 { 00243 //lim to 0 00244 if ( hg[i].b!=0 && hg[i].d!=0 ) 00245 l= as<FT>(hg[i].b)/as<FT>(hg[i].d); 00246 else if ( hg[i].d==0 ) 00247 l= 10000000; 00248 else if ( hg[i].b==0 ) 00249 l= 0 ; 00250 else 00251 l= as<FT>(hg[i].a)/as<FT>(hg[i].c) ; 00252 00253 //lim to inf 00254 if ( hg[i].a!=0 && hg[i].c!=0 ) 00255 r= as<FT>(hg[i].a)/as<FT>(hg[i].c); 00256 else if ( hg[i].c==0 ) 00257 r=10000000; 00258 else if ( hg[i].a==0 ) 00259 r= 0 ; 00260 else 00261 r= as<FT>(hg[i].b)/as<FT>(hg[i].d); 00262 00263 if ( l<=r ) s << Interval<FT>(l,r); 00264 else s << Interval<FT>(r,l); 00265 } 00266 return s; 00267 } 00268 00269 Seq<C> middle() 00270 { 00271 Seq<C> m; 00272 for ( unsigned i=0; i!=dim; ++i ) 00273 m << as<C>( floor( as<double>(hg[i].d/hg[i].c) )) ; //floor 00274 return (m); 00275 } 00276 00277 C middle(int i) 00278 { 00279 C t; 00280 t= as<C>( floor( as<double>(hg[i].d/hg[i].c) )); //floor 00281 //if ( t==C(0) ) t=t+1; 00282 return (t+1); 00283 } 00284 00285 00286 template<class FT> 00287 Seq<FT> point(Seq<FT> t) 00288 { 00289 assert( t.size()==dim ); 00290 Seq<FT> m; 00291 for ( unsigned i=0; i!=dim; ++i ) 00292 m << ( as<FT>(hg[i].a)*(t[i]) + as<FT>(hg[i].b) ) / 00293 ( as<FT>(hg[i].c)*(t[i]) + as<FT>(hg[i].d) ) ; 00294 return m; 00295 } 00296 00297 Seq<C> subdiv_center(const unsigned& i) 00298 { 00299 Seq<C> tt; 00300 // Seq<double> t; 00301 tt.resize( dim ); 00302 tt[i]= this->middle(i); 00303 00304 return tt; 00305 } 00306 00307 Seq<double> subdiv_point(const unsigned& i) 00308 { 00309 return this->template point<double>(this->subdiv_center(i)); 00310 } 00311 00312 template<class FT> inline 00313 Seq<FT> eval(Seq<FT> t) 00314 { 00315 assert( t.size()==dim ); 00316 Seq<FT> res; 00317 FT ev; 00318 for ( unsigned i=0; i!=S.size() ; ++i ) 00319 { 00320 tensor::eval( ev , S[i].rep(), t, dim ); 00321 res<< ev; 00322 } 00323 return res; 00324 } 00325 00326 //template<class FT> 00327 inline bool is_root(Seq<C> t) 00328 { 00329 assert( t.size()==dim ); 00330 C ev; 00331 for ( unsigned i=0; i!=S.size() ; ++i ) 00332 { 00333 tensor::eval( ev , S[i].rep() , t , dim ); 00334 if ( ev != 0 ) 00335 return false; 00336 } 00337 return true; 00338 } 00339 00340 00342 bool reduce_domain() 00343 { 00344 C lb; 00345 unsigned i; 00346 bool flag= false; // true iff reduction takes place 00347 00348 Seq<C> track; 00349 00350 //Compute lower bound and shift system 00351 for ( i=0; i<dim ;++i) // for all vars 00352 { 00353 lb= l_bound(i); 00354 track<< lb; 00355 if ( lb!=0 ) 00356 { 00357 this->shift_box(lb,i); 00358 update_data(); 00359 flag= true; 00360 } 00361 } 00362 return flag; 00363 }; 00364 00366 C l_bound( const int v ) 00367 { 00368 C l(0) ; 00369 unsigned i; 00370 POL m0, m1 ; 00371 00372 for (i=0; i!=S.size(); ++i ) // for all polys 00373 { 00374 m1= maxs( & S[i] , v); 00375 m0= mins( & S[i] , v); 00376 //std::cout<< m1<< " , "<< m0 << std::endl; 00377 00378 if ( m0( C(0) ) > 0 ) 00379 l= solver<ring<C,MonomialTensor>, CFfirstFloor>::template solve<C>(m0); 00380 // l= as<C>( solver<ring<double,Bernstein>, Bspline>::first_root(m0) ); 00381 else if ( m1( C(0) ) < 0 ) 00382 l= solver<ring<C,MonomialTensor>, CFfirstFloor>::template solve<C>(m1); 00383 // l= as<C>( solver<ring<double,Bernstein>, Bspline>::first_root(m1) ); 00384 } 00385 return l; 00386 }; 00387 00388 00389 POL mins( POL * f, int v) 00390 { 00391 POL h(0,f->rep().szs()[v]-1,0) ;//var is always x0 00392 tensor::mins(h.rep(), f->rep(), v ); 00393 return h; 00394 }; 00395 00396 00397 POL maxs( POL * f, int v) 00398 { 00399 POL h(0,f->rep().szs()[v]-1,0) ;//var is always x0 00400 tensor::maxs(h.rep(), f->rep(), v ); 00401 return h; 00402 }; 00403 00404 00406 void subdivide( STACK & stck ) 00407 { 00408 int i; 00409 Seq<int> ind(dim); 00410 box_rep * b; 00411 00412 for (;;) 00413 { 00414 // copy box 00415 b = new box_rep( *this ) ; 00416 00417 // transform box 00418 for (i = 0; i < dim ; ++i) // for all vars 00419 if ( ind[i] ) 00420 b->shift_box(1,i); 00421 else 00422 b->reverse_and_shift_box(i); 00423 b->update_data(); 00424 00425 // push box in stack 00426 stck.push ( b ); 00427 00428 // next 00429 for (i = 0; i < dim ; ++i) 00430 if (++ind[i] <2 ) break; else ind[i]=0 ; 00431 if (i == dim ) break; 00432 } 00433 }; 00434 00435 00437 void safe_split(const int &v, C m=C(1) ) 00438 { 00439 box_rep * b; 00440 00441 b = new box_rep( *this ) ; 00442 00443 // evaluate polys at x_v=m 00444 00445 //check sign 00446 }; 00447 00448 00449 00451 void subdivide( const int &v, STACK & stck, C m=C(1) ) 00452 { 00453 box_rep * b; 00454 00455 // right box 00456 b = new box_rep( *this ) ; 00457 b->shift_box( m ,v); 00458 b->update_data(); 00459 stck.push ( b ); 00460 00461 // left box 00462 b = new box_rep( *this ) ; 00463 b->contract_box(m,v); 00464 b->reverse_and_shift_box(v); 00465 //b->reverse_box( v); // produces thin boxes 00466 b->update_data(); 00467 stck.push ( b ); 00468 }; 00469 00471 void subdivide( const int &v, C & m, STACK & stck ) 00472 { 00473 box_rep * b; 00474 box_rep tmp(*this); 00475 00476 // left box 00477 b = new box_rep( tmp ) ; 00478 b->contract_box( m ,v); 00479 b->reverse_and_shift_box(v); 00480 b->reverse_box( v); //mirror back 00481 b->update_data(); 00482 stck.push ( b ); 00483 00484 // right box 00485 b = new box_rep( tmp ) ; 00486 b->shift_box( m, v); 00487 b->update_data(); 00488 stck.push ( b ); 00489 }; 00490 00492 void shift_box(const C& t, const int & v = 0) 00493 { 00494 unsigned i; 00495 00496 for (i = 0; i < S.size() ; ++i) //for all polys do x=x+1 00497 shift( S[i].rep() , t, v); 00498 00499 //update homography 00500 hg.shift_hom(t,v); 00501 }; 00502 00504 void contract_box(const C & t, const int & v ) 00505 { 00506 unsigned i; 00507 00508 for (i = 0; i < S.size() ; ++i) 00509 contraction( S[i].rep() , t, v); 00510 00511 //update homography 00512 hg.contract_hom(t,v); 00513 }; 00514 00515 // x_v = 1/x_v 00516 void reverse_box(const int & v ) 00517 { 00518 for (unsigned i = 0; i < S.size() ; ++i) //for all polys 00519 reciprocal( S[i].rep() , v); 00520 00521 //update homography 00522 hg.reciprocal_hom(1,v); 00523 }; 00524 00525 // x_v = 1/(x_v +1) 00526 void reverse_and_shift_box(const int & v ) 00527 { 00528 for (unsigned i = 0; i < S.size() ; ++i) //for all polys 00529 { 00530 reciprocal( S[i].rep() , v); 00531 shift ( S[i].rep() ,C(1), v); 00532 } 00533 00534 //update homography 00535 hg.reciprocal_hom(1,v); 00536 hg.shift_hom (1,v); 00537 }; 00538 00539 00540 bool inline miranda_test(const int i,const int j) 00541 { 00542 POL u,l; 00543 00544 tensor::face(l, S[i], j, 0); 00545 tensor::face(u, S[i], j, 1); 00546 00547 return ( no_variation(l) && 00548 no_variation(u) && 00549 (l[0]>0)!=(u[0]>0) ); 00550 }; 00551 00553 // assumes a square system for now 00554 template<class FT> 00555 bool include1(DPOL * J) 00556 { 00557 Interval<double> ev; 00558 unsigned i,j,c,r ; 00559 POL u,l; 00560 00561 bool t[dim][dim]; 00562 00563 tensor::eval( ev , J->rep() , 00564 this->template domain<double>() , dim ); 00565 if ( ev.m*ev.M < 0 ) 00566 return false; 00567 00568 for (i=0; i!=dim;++i) 00569 for (j=0; j!=dim;++j) 00570 t[i][j]= miranda_test(i,j); 00571 00572 c=0; 00573 for (i=0; i!=dim;++i) 00574 for (j=0; j!=dim;++j) 00575 if (t[i][j]==true) 00576 { 00577 c++; break; 00578 } 00579 if (c<dim) return false; 00580 00581 c=0; 00582 for (i=0; i!=dim;++i) 00583 for (j=0; j!=dim;++j) 00584 if (t[j][i]==true) 00585 { 00586 c++; break; 00587 } 00588 if (c<dim) return false; 00589 00590 // std::cout<<"INCLUDE. ev="<<ev<<", c="<<c <<std::endl; 00591 00592 return true; 00593 }; 00594 00596 bool include2(DPOL * J) 00597 { 00598 Interval<double> ev; 00599 00600 tensor::eval( ev , J->rep() , 00601 this->domain<double>(), dim ); 00602 00603 // if ( this->width<double>() > 0.001 ) 00604 if ( ev.m*ev.M < 0 ) 00605 return false; 00606 00607 //td= this->topological_degree_2d<double>(); 00608 //if ( (td==-1 || td==1) ) 00609 //{ std::cout<<"INCLUDE. ev="<<ev<<", td="<<td <<std::endl; 00610 //this->print(); } 00611 00612 return ( 0 ); 00613 } 00614 00616 bool include3(DPOL * J) 00617 { 00618 //evaluate df_i(B) of the box = M_i 00619 // check if -Ji(c)*f(c) + (I-Ji(c)*M)*B 00620 // is contaied in B. 00621 00622 Interval<double> ev; 00623 00624 tensor::eval( ev , J->rep() , 00625 this->domain<double>(), dim ); 00626 00627 // if ( this->width<double>() > 0.001 ) 00628 if ( ev.m*ev.M < 0 ) 00629 return false; 00630 00631 //td= this->topological_degree_2d<double>(); 00632 //if ( (td==-1 || td==1) ) 00633 //{ std::cout<<"INCLUDE. ev="<<ev<<", td="<<td <<std::endl; 00634 //this->print(); } 00635 00636 return ( 0 ); 00637 } 00638 00639 00641 template<class FT> 00642 bool exclude1( Seq<POL *>& S0) 00643 { 00644 Interval<FT> ev; 00645 Seq<Interval<FT> > dom; 00646 dom= domain<FT>(); 00647 00648 for (unsigned i=0; i!=nbpol(); ++i) 00649 { 00650 tensor::eval( ev , S0[i]->rep(), 00651 dom , dim ); 00652 if ( ev.m*ev.M > 0 ) 00653 { 00654 // std::cout<<i<<" ev"<< 00655 // dom<<"\nf= "<< *(S0[1])<< 00656 // "\n f([])= " <<ev<<std::endl; 00657 // if (td!=0) 00658 // std::cout<<"!!!!!!----td: "<<td <<std::endl; 00659 return true; 00660 } 00661 00662 } 00663 return false; 00664 }; 00665 00667 template<class FT> 00668 inline FT width() 00669 { 00670 unsigned i; 00671 FT m=this->width<FT>(i); 00672 00673 return m; 00674 }; 00675 00677 template<class FT> 00678 FT width(unsigned & t) 00679 { 00680 unsigned i; 00681 FT w; 00682 Seq<Interval<FT> > s ; 00683 00684 s= domain<FT>(); 00685 w= s[0].width(); t= 0; 00686 00687 for ( i=0; i!=s.size(); ++i ) 00688 if ( s[i].width() > w) 00689 { w=s[i].width() ; t=i; } 00690 00691 return w; 00692 }; 00693 00694 POL lface(const int & i, const int & v) 00695 { 00696 POL t; 00697 00698 tensor::face(t, S[i], v , 0 ); 00699 rename_var( t.rep() , 1-v, 0 ) ; //1-v works for 2D only 00700 00701 return t; 00702 }; 00703 00704 POL rface(const int & i, const int & v) 00705 { 00706 POL tmp; 00707 tensor::face(tmp, S[i], v , 1 ); 00708 rename_var( tmp.rep() , 1-v, 0 ) ; //1-v works for 2D only 00709 00710 return tmp; 00711 }; 00712 00713 void print() 00714 { 00715 std::cout << "-------------Box---------------" << "\n" ; 00716 std::cout << system() << "\n"; 00717 for (unsigned i=0; i!=dim;++i) 00718 std::cout<< "("<<hg[i].a <<"x + " << hg[i].b<<")/("<<hg[i].c<<"x+ "<<hg[i].d << ")"<<std::endl; ; 00719 //std::cout<<"td="<<tdeg()<<std::endl; 00720 // std::cout << this->template domain<QQ>()<<"\n" ; 00721 std::cout << this->template domain<double>()<<"\n" ; 00722 std::cout << "-------------------------------" << "\n" ; 00723 }; 00724 00725 00726 };// box_rep 00727 00728 } //namespace realroot 00729 } //namespace mmx 00730 00731 # undef DPOL 00732 #endif