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