realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/solver_mv_monomial_tests.hpp
Go to the documentation of this file.
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