realroot_doc 0.1.1
|
00001 /******************************************************************** 00002 * Author(s): A. Mantzaflaris, GALAAD, INRIA 00003 ********************************************************************/ 00004 00005 # pragma once 00006 /********************************************************************/ 00007 00009 # include <realroot/ring.hpp> 00010 # include <realroot/polynomial_tensor.hpp> 00012 00013 # include <realroot/polynomial.hpp> 00014 # include <realroot/homography.hpp> 00015 # include <realroot/sign_variation.hpp> 00016 # include <realroot/Interval.hpp> 00017 //# include <linalg/matrix.hpp> 00018 # include <stack> 00019 00020 # include <realroot/solver_ucf.hpp> 00021 # include <realroot/solver_uv_bspline.hpp> 00022 00023 00024 # define TMPL template<class POL> 00025 # define DPOL polynomial<double,with<MonomialTensor> > 00026 # define BOX box_rep<POL> 00027 00028 # define INFO 1 00029 # define TODOUBLE as<double> 00030 00031 //==================================================================== 00032 namespace mmx { 00033 //==================================================================== 00034 namespace realroot { 00035 00036 template<class POL, class FT> int topological_degree_2d(BOX* b); 00037 00038 00039 //Jacobian 00040 00041 TMPL 00042 inline DPOL * jacobian(Seq<POL*>& S0) 00043 { 00044 int n=S0.size(); 00045 DPOL * jac;//[n*n]; 00046 POL df; 00047 jac= new DPOL [n*n]; 00048 00049 for( int i=0;i<n;i++) 00050 { 00051 for( int k=0;k<n;k++) 00052 { 00053 df= diff( *(S0[i]),k); 00054 let::assign( jac[i*n+k] , df); 00055 } 00056 00057 } 00058 return jac; 00059 } 00060 00061 00062 template<class T> inline 00063 void precondition (Seq<T> val, DPOL * mat, int n) 00064 { 00065 int m(val.size()); 00066 T *ev;//[m*n]; 00067 ev= new T [m*n]; 00068 00069 for( int i=0;i<m;i++) 00070 { 00071 for( int k=0;k<n;k++) 00072 { 00073 tensor::eval( ev[i*m+k] , mat[i*m+k].rep(), 00074 val , m ); 00075 } 00076 } 00077 return ev; 00078 } 00079 00080 00081 00082 00083 template<class T> inline 00084 T * eval_poly_matrix(Seq<T> val, DPOL * mat, int n) 00085 { 00086 int m(val.size()); 00087 T *ev;//[m*n]; 00088 ev= new T [m*n]; 00089 00090 for( int i=0;i<m;i++) 00091 { 00092 for( int k=0;k<n;k++) 00093 { 00094 tensor::eval( ev[i*m+k] , mat[i*m+k].rep(), 00095 val , m ); 00096 } 00097 } 00098 return ev; 00099 } 00100 00101 template<class T> inline 00102 int signof_det(T *mat,const int& n) 00103 { // mat= double[n*n] 00104 double ev; 00105 ev= det(mat,n); 00106 00107 if (ev< .1e-15) return (0); 00108 return (ev>0?1:-1); 00109 } 00110 00111 template<class T> 00112 T* submatrix(T *matrix, int order, int i, int j) 00113 { 00114 int n=order-1; 00115 T * subm;//[n*n]; 00116 int p, q; // Indexes for matrix 00117 int a = 0, b; // Indexes for subm 00118 subm = new T [n*n]; 00119 00120 for(p = 0; p < order; p++) { 00121 if(p==i) continue; //Skip ith row 00122 00123 b = 0; 00124 00125 for(q = 0; q < order; q++) { 00126 if(q==j) continue; //Skip jth column 00127 subm[a*order + b++] = matrix[p*order+q]; 00128 } 00129 a++; //Increment row index 00130 } 00131 return subm; 00132 } 00133 00134 // Compute matrix determinant, recursively 00135 template<class T> 00136 T det(T *mat, int order) 00137 { 00138 if(order == 1) 00139 return mat[0]; // Matrix is of order one 00140 int i; 00141 T ev(0); 00142 00143 for(i = 0; i < order; i++) 00144 { 00145 //std::cout<<"entering"<<order<<",i="<<i <<std::endl; 00146 ev += T(i%2==0?1:-1)* mat[i*order] * det(submatrix(mat, order, i, 0), order - 1); 00147 00148 //std::cout<<"OK, ("<<order<<" "<<i<<")"<<std::endl; 00149 } 00150 return ev; 00151 } 00152 00153 00154 // 00155 template<class FT> 00156 inline int signof(DPOL * p, Seq<FT> t) 00157 { 00158 00159 Interval<double> ev; 00160 //int dim= p->nbvar(); 00161 00162 tensor::eval( ev , p->rep() , 00163 t , t.size() ); 00164 00165 if (ev< .1e-10) return (0); 00166 return (ev>0?1:-1); 00167 } 00168 00169 00170 /* 00171 template<class C> 00172 inline bool is_root(Seq<C> t) 00173 { 00174 assert( t.size()==dim ); 00175 C ev; 00176 for ( unsigned i=0; i!=S.size() ; ++i ) 00177 { 00178 tensor::eval( ev , S[i].rep() , t , dim ); 00179 if ( ev != 0 ) 00180 return false; 00181 } 00182 return true; 00183 } 00184 */ 00185 00186 TMPL 00187 bool inline miranda_test(Seq<POL>& S,const int i,const int j) 00188 { 00189 POL u,l; 00190 00191 tensor::face(l, S[i], j, 0); 00192 tensor::face(u, S[i], j, 1); 00193 //std::cout<<"l="<<l<<",u="<<u<<std::endl; 00194 00195 return ( no_variation(l) && 00196 no_variation(u) && 00197 (l[0]>0)!=(u[0]>0) ); 00198 }; 00199 00201 // assumes a square system for now 00202 template<class POL> 00203 bool include1(BOX* b, DPOL * J) 00204 { 00205 Interval<double> ev(0); 00206 Interval<double> * m; 00207 unsigned i,j,c; //,r ; 00208 POL u,l; 00209 Seq<POL> SS= b->system(); 00210 unsigned dim= b->nbvar(); 00211 00212 bool t[dim][dim]; 00213 00214 m= eval_poly_matrix( b->template domain<double>() ,J,dim); 00215 00216 // std::cout<<"Ok " <<std::endl; 00217 // double dm[9]; 00218 // for(i = 0; i < 9; i++) 00219 // { dm[i]= m[i].M; 00220 // std::cout<<"dm["<<i<<"]="<<dm[i] <<std::endl; 00221 // } 00222 // ev= det(dm,dim); 00223 // std::cout<<"Ok ="<<ev <<std::endl; 00224 00225 // for(i = 0; i < 9; i++) 00226 // std::cout<<"m["<<i<<"]="<<m[i] <<std::endl; 00227 00228 // std::cout<<"SUB "<<std::endl; 00229 // ev= det(submatrix(m, 3, 2, 0), 2); 00230 // std::cout<<"FULL "<<std::endl; 00231 00232 ev=det(m,dim); 00233 00234 if ( ev.m*ev.M < 0 ) 00235 return false; 00236 00237 for (i=0; i!=dim;++i) 00238 for (j=0; j!=dim;++j){ 00239 t[i][j]= miranda_test(SS,i,j); 00240 //std::cout<<"mir("<<i<<","<<j<<")="<< t[i][j] <<std::endl; 00241 } 00242 00243 c=0; 00244 for (i=0; i!=dim;++i) 00245 for (j=0; j!=dim;++j) 00246 if (t[i][j]==true) 00247 { 00248 c++; break; 00249 } 00250 if (c<dim) return false; 00251 00252 c=0; 00253 for (i=0; i!=dim;++i) 00254 for (j=0; j!=dim;++j) 00255 if (t[j][i]==true) 00256 { 00257 c++; break; 00258 } 00259 if (c<dim) return false; 00260 00261 //std::cout<<"INCLUDE. ev="<<ev<<", c="<<c <<"*dim:"<<dim <<std::endl; 00262 return true; 00263 }; 00264 00266 TMPL 00267 bool include2(BOX* b,DPOL * J) 00268 { 00269 Interval<double> ev; 00270 Interval<double> * m; 00271 00272 //Seq<POL> SS= b->system(); 00273 unsigned dim= b->nbvar(); 00274 00275 // Check Jacobian's sign 00276 m= eval_poly_matrix( b->template domain<double>() ,J,dim); 00277 ev= det(m,dim); 00278 if ( ev.m*ev.M < 0 ) 00279 return false; 00280 00281 int td= topological_degree_2d<POL, double>(b); 00282 00283 //if ( (td==-1 || td==1) ) 00284 //{ std::cout<<"INCLUDE. ev="<<ev<<", td="<<td <<std::endl; 00285 //this->print(); } 00286 00287 return ( (td==-1 || td==1) ); 00288 } 00289 00291 template<class POL> 00292 bool include3(BOX* b,DPOL * J, Seq<POL*>& S0) 00293 { 00294 double *fc, *jc, *ijc; 00295 Interval<double> ev, *jb, *m; 00296 Seq<double> c= b->point( b->middle() ) ; 00297 Seq<Interval<double> > bx; 00298 unsigned i,j,n= b->nbvar(); 00299 DPOL tmp; 00300 00301 fc= new double[n]; // system S0 evaluated on c 00302 for(i=0; i< n;i++ ) 00303 { 00304 let::assign(tmp, *S0[i]) ; 00305 tensor::eval( fc[i] , tmp.rep(), c , n ); 00306 } 00307 bx= b->template domain<double>(); // box 00308 jc= eval_poly_matrix( c, J, n); // Jacobian evaluated on c 00309 ijc= new double[n*n]; 00310 linear::LUinverse(ijc, jc, n); // Inverse of above 00311 jb= eval_poly_matrix( bx, J, n); // Jacobian evaluated on box 00312 00313 m= new Interval<double>[n*n]; 00314 for(i=0; i< n;i++ ) 00315 for(j=0; j< n;j++ ) 00316 m[i*n+j] += ijc[i*n+j]*jb[j*n+i]; 00317 free(jb); 00318 00319 // check if -im*fc + (I-im*jb)*bx is inside bx. 00320 00321 for(i=0; i< n;i++ ) 00322 { 00323 bx[i]= bx[i]- c[i]; 00324 ev= bx[i]; 00325 for(j=0; j<n; j++ ) 00326 { 00327 ev+= -ijc[i*n+j]*fc[j] - m[i*n+j] *bx[i]; 00328 } 00329 // std::cout<<ev<<" --- "<<bx[i]<<std::endl; 00330 if ( ev.m < bx[i].m || 00331 ev.M > bx[i].M ) 00332 { 00333 // std::cout<<ev<<" not in "<<bx[i]<<std::endl; 00334 return false; 00335 } 00336 } 00337 // std::cout<<"found root in "<<bx<< "(ev="<<ev<<")"<<std::endl; 00338 return ( true ); 00339 } 00340 00341 00343 template<class POL> 00344 bool exclude1(BOX*b, Seq<POL *>& S0) 00345 { 00346 Interval<double> ev; 00347 Seq<Interval<double> > dom; 00348 dom= b->template domain<double>(); 00349 DPOL tmp; 00350 00351 for (unsigned i=0; i!=b->nbpol(); ++i) 00352 { 00353 let::assign(tmp, *S0[i] ); 00354 tensor::eval( ev , tmp.rep(), 00355 dom , b->nbvar() ); 00356 if ( ev.m*ev.M > 0 ) 00357 { 00358 // std::cout<<i<<" ev"<< 00359 // dom<<"\nf= "<< *(S0[1])<< 00360 // "\n f([])= " <<ev<<std::endl; 00361 // if (td!=0) 00362 // std::cout<<"!!!!!!----td: "<<td <<std::endl; 00363 return true; 00364 } 00365 00366 } 00367 return false; 00368 }; 00369 00370 00372 TMPL 00373 bool exclude2(BOX* b,DPOL * J) 00374 { 00375 Interval<double> ev; 00376 Interval<double> * m; 00377 00378 //Seq<POL> SS= b->system(); 00379 unsigned dim= b->nbvar(); 00380 00381 // Check Jacobian's sign 00382 m= eval_poly_matrix( b->template domain<double>() ,J,dim); 00383 ev= det(m,dim); 00384 if ( ev.m*ev.M < 0 ) 00385 return false; 00386 00387 int td= topological_degree_2d<POL, double>(b); 00388 00389 return ( td==0 ); 00390 } 00391 00392 TMPL 00393 inline bool exclude3(BOX* b) 00394 { 00395 Seq<POL> S= b->system(); 00396 for (unsigned i=0; i!=b->nbpol(); ++i) 00397 if ( no_variation( S[i]) ) 00398 return true; 00399 return false; 00400 } 00401 00403 TMPL 00404 inline bool no_variation(POL & p) 00405 { 00406 return !has_sign_variation(p.begin(),p.end()) ; 00407 }; 00408 00409 00410 //==================================================================== 00411 // ---------------------- Topological degree in 2d ------------------- 00412 //==================================================================== 00413 00415 template<class FT> 00416 inline int sgn(FT a ) 00417 { 00418 if (a==FT(0) ) return 0; 00419 return ( (a>0) ? 1 : -1 ); 00420 } 00421 00423 template<class POL, class FT> 00424 int inline sgn(POL & f, FT a ) 00425 { 00426 if (a==FT(-1) ) 00427 return sgn ( f[ f.rep().szs()[0]-1 ]); 00428 else 00429 return sgn ( f(a) ); 00430 }; 00431 00432 //template<class POL, class FT> 00433 template<class POL, class FT> 00434 int topological_degree_2d(BOX* b) 00435 { 00436 /*-1=inf*/ 00437 typedef typename POL::scalar_t C; 00438 00439 assert( b->nbvar() ==2 ); 00440 Seq<FT> p; 00441 Seq<FT> tmp; 00442 unsigned ev1(0), ev2(0), ev3(0), ev4(0); 00443 FT p1[2],p2[2]; 00444 int tdeg; 00445 unsigned i; 00446 00447 POL fl0, fr0,fl1,fr1, s, 00448 gl0, gr0,gl1,gr1 ; 00449 00450 fl0=b->lface(0,1); gl0=b->lface(1,1); 00451 fr0=b->rface(0,1); gr0=b->rface(1,1); 00452 fl1=b->lface(0,0); gl1=b->lface(1,0); 00453 fr1=b->rface(0,0); gr1=b->rface(1,0); 00454 00455 s= fl0 * gl0 ; 00456 p<< FT(0);p << FT(0) ; 00457 tmp= solver<ring<C,MonomialTensor>, CFseparate>::template solve<FT>(s); 00458 for (i=0;i< tmp.size(); ++i ) 00459 p<< tmp[i] << FT(0) ; 00460 00461 s= fr1 * gr1; 00462 p<< FT(-1);p << FT(0); 00463 tmp= solver<ring<C,MonomialTensor>, CFseparate>::template solve<FT>(s); 00464 for (i=0;i< tmp.size(); ++i ) 00465 p<< FT(-1) << tmp[i]; 00466 00467 s= fr0 * gr0 ; 00468 p<< FT(-1);p << FT(-1) ; 00469 tmp= solver<ring<C,MonomialTensor>, CFseparate>::template solve<FT>(s); 00470 for (i=0;i< tmp.size(); ++i ) 00471 p<< tmp[i] << FT(-1) ; 00472 00473 s= fl1 * gl1 ; 00474 p<< FT(0);p << FT(-1) ; 00475 tmp= solver<ring<C,MonomialTensor>, CFseparate>::template solve<FT>(s); 00476 for (i=0;i< tmp.size(); ++i ) 00477 p<< FT(0) << tmp[i] ; 00478 00479 p<< FT(0);p << FT(0) ; 00480 00481 tdeg= 0; 00482 for (i=0; i<p.size()-3; i+=2) 00483 { 00484 p1[0]= p[i] ;p1[1]=p[i+1]; 00485 p2[0]= p[i+2];p2[1]=p[i+3]; 00486 00487 if (p1[1]==FT(0) && p2[1]==FT(0)){ 00488 ev1= sgn( fl0, p1[0] ); 00489 ev3= sgn( fl0, p2[0] ); 00490 ev4= sgn( gl0, p1[0] ); 00491 ev2= sgn( gl0, p2[0] ); 00492 }else 00493 if (p1[0]==FT(-1) && p2[0]==FT(-1)){ 00494 ev1= sgn( fr1, p1[1] ); 00495 ev3= sgn( fr1, p2[1] ); 00496 ev4= sgn( gr1, p1[1] ); 00497 ev2= sgn( gr1, p2[1] ); 00498 }else 00499 if (p1[1]==FT(-1) && p2[1]==FT(-1)){ 00500 ev1= sgn( fr0, p1[0] ); 00501 ev3= sgn( fr0, p2[0] ); 00502 ev4= sgn( gr0, p1[0] ); 00503 ev2= sgn( gr0, p2[0] ); 00504 }else 00505 if (p1[0]==FT(0) && p2[0]==FT(0)){ 00506 ev1= sgn( fl1, p1[1] ); 00507 ev3= sgn( fl1, p2[1] ); 00508 ev4= sgn( gl1, p1[1] ); 00509 ev2= sgn( gl1, p2[1] ); 00510 } 00511 else 00512 std::cout<< "TROUBLE!"<<std::endl; 00513 00514 tdeg+= ( (ev1)*(ev2) - (ev3)*(ev4) ); 00515 } 00516 return (tdeg/8); 00517 } 00518 00519 00520 } //namespace realroot 00521 } //namespace mmx 00522 00523 # undef DPOL 00524