Developer documentation

solver_ucf.hpp
Go to the documentation of this file.
1 /********************************************************************
2  * Author(s): A. Mantzaflaris, GALAAD, INRIA
3  ********************************************************************/
4 #ifndef _realroot_SOLVER_FIRST_ROOT_CONFRAC_H
5 #define _realroot_SOLVER_FIRST_ROOT_CONFRAC_H
6 /********************************************************************/
7 
8 # include <realroot/Interval.hpp>
9 
10 # include <realroot/homography.hpp>
13 # include <stack>
14 # include <realroot/solver.hpp>
15 
16 # define NO_ROOT -1.0
17 # define TMPL template<class POL>
18 # define TMPLR template<class Real, class POL>
19 # define N_ITER 10000
20 
21 namespace mmx {
22 
23  struct CFfirstIsolate{};
25  struct CFfirstFloor{};
26  struct CFallIsolate{};
27  struct CFseparate{};
28  struct CFdecide{};
29 
30  //bit_size support for QQ
31 
32  // inline long bit_size(QQ q)
33  // {
34  // long n,d;
35  // n= bit_size( numerator(q) );
36  // d= bit_size(denominator(q) );
37  // return( n>d ? n : d ) ;
38  // }
39 
40 
41 /* ******************************************************** */
42 /* Represents the polynomial on an interval [u,v].
43  Keeps homography information to map [0,inf] back to [u,v].
44  Main operations are shift, contraction and reciprocal.
45  */
46 TMPL
48 {
49  typedef typename POL::scalar_t C;
50 
51  POL f;
52  homography<C> hg;
53 
54 public:
55 
57 
58  interval_rep(const POL p)
59  {
60  f = p;
61  hg = homography<C>() ;
62  }
63 
65  {
66  f = p;
67  hg = h;
68  }
69 
70 
71  interval_rep(const POL p, C u, C v )
72  {
73  f = p;
74  hg = homography<C>() ;
75 
76  shift_box ( u );
77  contract_box ( v-u );
79  //print();
80  }
81 
82  /* Access the equation */
83  POL inline poly() {return f;};
84  /* Access the homography */
85  homography<C> hom() { return hg; }
86 
87  /* Access the domain */
88  template<class Real>
90  {
91  Real l, r;
92  Interval<Real> s ;
93  //lim to 0
94  if ( hg.b!=0 && hg.d!=0 )
95  l= as<Real>(hg.b)/as<Real>(hg.d);
96  else if ( hg.d==0 )
97  l= 10000000;
98  else if ( hg.b==0 )
99  l= 0 ;
100  else
101  l= as<Real>(hg.a)/as<Real>(hg.c) ;
102  //lim to inf
103  if ( hg.a!=0 && hg.c!=0 )
104  r= as<Real>(hg.a)/as<Real>(hg.c);
105  else if ( hg.c==0 )
106  r=10000000;
107  else if ( hg.a==0 )
108  r= 0 ;
109  else
110  r= as<Real>(hg.b)/as<Real>(hg.d);
111 
112  if ( l<=r ) s= Interval<Real>(l,r);
113  else s= Interval<Real>(r,l);
114 
115  return s;
116  }
117 
118  /* Access the size of the domain */
119  template<class Real>
120  Real inline width()
121  {
122  return this->template domain<Real>().width();
123  }
124 
125  /* Access the point where t\in\RR_+ corresponds */
126  template<class Real>
127  Real inline point(C & t)
128  {
129  return ( as<Real>(hg.a)*as<Real>(t) + as<Real>(hg.b) ) /
130  ( as<Real>(hg.c)*as<Real>(t) + as<Real>(hg.d) ) ;
131  }
132 
133  C middle()
134  {
135  C t(hg.d / hg.c);
136 
137  if (t>0)
138  return ( t ) ;
139  else
140  return C(1);
141  }
142 
143  unsigned sign_var()
144  {
145  return sign_variation(f.begin(),f.end()) ;
146  }
147 
148 
149  // Shift the polynomial by t
150  void shift_box(const C& t)
151  {
152  int s, k,j, sz= f.size();
153 
154  for ( s = sz, j = 0; j <= s-2; j++ )
155  for( k = s-2; k >= j; k-- )
156  f[k] += t*f[k+1];
157 
158  //update homography
159  hg.shift_hom(t);
160  };
161 
162  // x = t*x
163  void contract_box(const C & t )
164  {
165  int s, sz= f.size();
166 
167  for ( s = 0 ; s < sz; ++s )
168  f[s] *= pow(t,s) ;
169 
170  //update homography
171  hg.contract_hom(t);
172  };
173 
174  // x = 1/x -- parameter t=1 unused for now
175  void reverse_box(const C & t=1 )
176  {
177  unsigned s, l= f.size()-1;
178 
179  for (s = 0 ; s <= l/2; s++ )
180  std::swap(f[s], f[l-s]);
181 
182  //update homography
183  hg.reciprocal_hom(t);
184  };
185 
186  // x = 1/(x+1) -- parameter t=1 unused for now
187  void inline reverse_and_shift_box(const C & t=1)
188  {
189  reverse_box(t);
190  shift_box (C(1));
191  };
192 
193  void print()
194  {
195  std::cout << "----------Interval---------------" << "\n" ;
196  std::cout << poly() << "\n" ;
197  std::cout<< "("<<hg.a <<"x + " << hg.b<<")/("<<hg.c<<"x+ "<<hg.d << ")"<<", sv:"<<sign_var() <<std::endl;
198  std::cout << domain() << "\n" ;
199  std::cout << "-------------------------------" << "\n" ;
200  }
201 
202 }; /* Interval_rep */
203 
204 
205 /* ******************************************************** */
206  /*
207  Solver interface
208  */
209  TMPLR
210  struct solver_cffirst {
211 
213  Real eps;
214 
216  ir = p;
217  eps= as<Real>(1e-7);
218  }
219 
222  Real first_root_approximate();
223  Real first_root_floor();
224 
228  };
229 
230  /*
231  Main routine:
232  Returns an "interval_rep" containing the minimum >0 root.
233  */
234  TMPLR
236  {
237  typedef interval_rep<POL> BOX;
238  std::stack<BOX * > uboxes;
239  typedef typename POL::scalar_t C;
240 
241  POL zero(0);
242  Interval<Real> mid(0);
243  BOX * b, * tmp;
244  POL p;
245  unsigned s, iters=0;
246 
248  AkritasBound<C> lb;
249  //HongBound<C> lb;
250  //Kioustelidis<C> lb;
251  //NISP<C> lb;
252  //Cauchy<C> lb;
253 
254  C lower;
255  b= new BOX(ir);
256  uboxes.push (b);
257 
258  while ( !uboxes.empty() && iters++ < N_ITER )
259 
260  {
261  b = uboxes.top() ;
262  p = b->poly() ;
263  uboxes.pop();
264 
265  if ( p==zero && (!uboxes.empty()) ) {
266  return *b;}
267 
268  s = b->sign_var() ;
269  I = b->template domain<Real>();
270 
271  if ( s==1 && (!uboxes.empty()) ) {
272  return *b;}
273 
274  if ( s > 0 )
275  {
276  if ( b->template width<Real>() < eps )
277  {std::cout<< "first_root: multiple root?"<<b->template domain<Real>() <<std::endl;}
278  else
279  {
280  lower= lb.lower_bound(p) ;
281  if ( lower!=0 )
282  {
283  if ( p( lower ) == 0 )
284  return *b;
285 
286  tmp= new BOX( *b ) ;
287  free(b);
288  tmp->shift_box( lower );
289  uboxes.push (tmp);
290  }
291  else
292  {
293  // right box
294  tmp = new BOX( *b ) ;
295  tmp->shift_box( 1 );
296  uboxes.push ( tmp );
297  //middle if needed
298  if ( p( Real(1) ) == Real(0) )
299  { tmp = new BOX(zero, b->hom() ) ;
300  uboxes.push ( tmp ); }
301  //left
302  tmp = new BOX( *b ) ;
303  tmp->reverse_and_shift_box( 1 );
304  tmp->reverse_box( 1 );
305  uboxes.push ( tmp );
306 
307  free(b);
308  }
309  }
310  }
311  }
312  /* -1 = No positive root */
313  return BOX(-1);
314  }
315 
316  /*
317  Returns a list of "interval_rep"s isolating the positive roots,
318  in increasing order.
319  */
320  TMPLR
322  {
323  typedef interval_rep<POL> BOX;
324  std::stack<BOX * > uboxes;
325  typedef typename POL::scalar_t C;
326 
327  Real ev(0);
328  Seq<interval_rep<POL> > sols;
329  POL zero(0);
330  Interval<Real> mid(0);
331  BOX * b, * tmp;
332  POL p;
333  unsigned s, iters=0;
334 
336  AkritasBound<C> lb;
337  //HongBound<C> lb;
338  //Kioustelidis<C> lb;
339  //NISP<C> lb;
340  //Cauchy<C> lb;
341 
342  C lower;
343  b= new BOX(ir);
344  uboxes.push (b);
345 
346  while ( !uboxes.empty() && iters++ < N_ITER )
347  {
348  b = uboxes.top() ;
349  p = b->poly() ;
350  uboxes.pop();
351 
352  if ( p==zero && (!uboxes.empty()) ) {
353  sols<< *b;}
354 
355  I = b->template domain<Real>();
356  // Interval<Real> ev= p( I ) ;
357  // if ( ev.m * ev.M > 0 ) continue;
358  s = b->sign_var() ;
359  if ( s==1 && (!uboxes.empty()) ) {
360  sols << *b; continue; }
361 
362  if ( s > 0 )
363  {
364  if ( (!uboxes.empty()) && b->template width<Real>() < eps*.1 )
365  {std::cout<<
366  "all_roots: multiple root?"<<b->template domain<Real>() <<std::endl;
367  std::cout<< b->poly()<<" , "<<b->template width<Real>()<<std::endl;
368  std::cout<<"source: "<<ir.poly()<<std::endl;
369 
370  }
371  else
372  {
373  lower= lb.lower_bound(p) ;
374  if ( lower!=0 )
375  {
376 
377  let::assign(ev,lower);
378  if ( p(ev) == 0 )
379  sols<< *b;
380 
381  tmp= new BOX( *b ) ;
382  free(b);
383  tmp->shift_box( lower );
384  uboxes.push (tmp);
385  }
386  else
387  {
388  // right box
389  tmp = new BOX( *b ) ;
390  tmp->shift_box( 1 );
391  uboxes.push ( tmp );
392  //middle if needed
393  ev=1;
394  if ( p( ev ) == Real(0) )
395  { tmp = new BOX(zero, b->hom() ) ;
396  uboxes.push ( tmp ); }
397  //left
398  tmp = new BOX( *b ) ;
399  tmp->reverse_and_shift_box( 1 );
400  tmp->reverse_box( 1 );
401  uboxes.push ( tmp );
402 
403  free(b);
404  }
405  }
406  }
407  }
408  return sols;
409  }
410 
411  /*
412  Return isolation box of the first positive root, [-1,-1] if none exists.
413  */
414  TMPLR
416  {
417  interval_rep<POL> a( first_root() );
418  typename POL::scalar_t t(1);
419 
420  if ( a.poly()== POL(-1) )
421  return (0);
422  else
423  if (a.poly()==POL(0) )
424  return( a.template point<Real>(t) );
425  else
426  return ( a.template domain<Real>() );
427  }
428 
429  TMPLR
431  {
432  typedef interval_rep<POL> BOX;
433  typedef typename POL::scalar_t C;
434  BOX * l, * r= new BOX( first_root() ) ;
435  C t(1);
436 
437  if ( r->poly()== POL(-1) )
438  return (0);
439  else
440  if (r->poly()==POL(0) )
441  return( r->template point<Real>(t) );
442  else
443  {
444  /* Approximate */
445  while ( r->template width<Real>() > eps )
446  {
447  t= r->middle();
448 
449  if ( r->poly()( t ) == 0 ) return( r->template point<Real>(t) );
450  l= new BOX( *r) ;
451  l->shift_box( t );
452 
453  if ( l->sign_var() )
454  {
455  free(r);
456  r=l;
457  continue;
458  }
459  else
460  {
461  free(l);
462  r->contract_box(t);
463  r->reverse_and_shift_box(1);
464  r->reverse_box(1);
465  }
466  }
467 
468  return ( r->template domain<Real>() );
469  }
470  }
471 
472  TMPLR
474  {
475  typedef interval_rep<POL> BOX;
476  typedef typename POL::scalar_t C;
477 
478  BOX * l, * r= new BOX( first_root() ) ;
480  C t(1);
481  if ( r->poly()== POL(-1) )
482  return (0);
483  else
484  if (r->poly()==POL(0) )
485  return( r->template point<Real>(t) );
486  else
487  {
488 
489  I= r->template domain<Real>();
490  if ( r->poly() == POL(0) ) return as<Real> (floor(as<double>(r->template point<Real>(t))) );
491  while ( rfloor(I.m)!=rfloor(I.M) )
492  {
493  t= r->middle();
494  if ( r->poly()( t ) == 0 ) return as<Real>( floor(as<double>(r->template point<Real>(t))) );
495 
496  l= new BOX( *r) ;
497  l->shift_box( t );
498 
499  if ( l->sign_var() )
500  {
501  free(r);
502  r=l;
503  I= r->template domain<Real>();
504  continue;
505  }
506  else
507  {
508  free(l);
509  r->reverse_and_shift_box();
510  r->reverse_box();
511  I= r->template domain<Real>();
512  }
513  }
514  }
515  return as<Real>( floor(as<double>(I.m)) );
516  }/*first_root_floor*/
517 
518  TMPLR
520  {
521  Seq<interval_rep<POL> > a( all_roots() );
522  Seq<Interval<Real> > s;
523  typename POL::scalar_t t(1);
524 
525  for ( unsigned i=0; i<a.size(); ++i)
526  if (a[i].poly()==POL(0) )
527  s<< Interval<Real>(a[i].template point<Real>(t) );
528  else
529  s<< a[i].template domain<Real>();
530 
531  return s;
532  }
533 
534  TMPLR
536  {
537  Seq< Interval<Real> > ints;
538  Seq<Real> sep;
539 
540  ints= all_roots_isolate();
541  for (unsigned i=1; i<ints.size(); ++i)
542  sep << (ints[i-1].M + ints[i].m)*Real(0.5) ;
543 
544  return sep;
545  }
546 
547 //--------------------------------------------------------------------
548 template<class Ring>
549 struct solver<Ring, CFfirstIsolate > {
550 
551  typedef typename Ring::scalar_t base_t;
552 
553  template<class Real, class POL> static Interval<Real>
554  solve(const POL& p,const base_t& u,const base_t& v);
555 
556  template<class Real, class POL> static Interval<Real>
557  solve(const POL& p);
558 };
559 
564 template<class Ring>
565 template<class Real, class POL>
568 const base_t & u,
569 const base_t & v) {
570 
571  interval_rep<POL> i(p,u,v);
573 
574  return slv.first_root_isolate();
575 }
576 
580 template<class Ring>
581 template<class Real, class POL>
584 
585  interval_rep<POL> i(p);
587 
588  return slv.first_root_isolate();
589 }
590 
591 
592 //--------------------------------------------------------------------
593  template<class Ring>
594  struct solver<Ring, CFfirstApproximate > {
595 
596  typedef typename Ring::scalar_t base_t;
597 
598  template<class Real, class POL> static Real
599  solve(const POL& p, const base_t& u, const base_t& v);
600 
601  template<class Real, class POL> static Real
602  solve(const POL& p);
603 };
604 
609  template<class Ring>
610  template<class Real, class POL>
611  Real
612 
614  const base_t& u, const base_t& v) {
615 
616 
617  interval_rep<POL> i(p,u,v);
619 
620  return slv.first_root_approximate();
621 }
622 
626  template<class Ring>
627  template<class Real, class POL>
628  Real
630 
631 
632  interval_rep<POL> i(p);
634 
635  return slv.first_root_approximate();
636 }
637 
638 
639 //--------------------------------------------------------------------
640  template<class Ring>
641  struct solver<Ring, CFfirstFloor> {
642  typedef typename Ring::Scalar base_t;
643 
644  template<class Real, class POL> static Real
645  solve(const POL& p, const base_t& u, const base_t& v);
646 
647  template<class Real,class POL> static Real
648  solve(const POL& p);
649 };
650 
655  template<class Ring>
656  template<class Real,class POL>
657  Real
659  const base_t& u, const base_t& v) {
660 
661  interval_rep<POL> i(p,u,v);
663 
664  return slv.first_root_floor();
665 }
666 
670  template<class Ring>
671  template<class Real, class POL>
672  Real
674 
675  interval_rep<POL> i(p);
677 
678  return slv.first_root_floor();
679 }
680 
681 
682 //--------------------------------------------------------------------
683  template<class Ring>
684  struct solver<Ring, CFallIsolate > {
685 
686  typedef typename Ring::Scalar base_t;
687 
688  template<class Real, class POL> static Seq<Interval<Real> >
689  solve(const POL& p,const base_t& u,const base_t& v);
690 
691  template<class Real,class POL> static Seq<Interval<Real> >
692  solve(const POL& p);
693 };
694 
698  template<class Ring>
699  template<class Real, class POL>
702  const base_t& u, const base_t& v) {
703 
704  interval_rep<POL> i(p,u,v);
706 
707  return slv.all_roots_isolate();
708 }
709 
713  template<class Ring>
714  template<class Real,class POL>
717 
718  interval_rep<POL> i(p);
720 
721  return slv.all_roots_isolate();
722 }
723 
724 
725 //--------------------------------------------------------------------
726  template<class Ring>
727  struct solver<Ring, CFseparate > {
728 
729  typedef typename Ring::Scalar base_t;
730 
731  template<class Real,class POL> static Seq<Real>
732  solve(const POL& p,const base_t& u,const base_t& v);
733 
734  template<class Real, class POL> static Seq<Real>
735  solve(const POL& p);
736 };
737 
741  template<class Ring>
742  template<class Real, class POL>
743  Seq<Real>
745  const base_t& u, const base_t& v) {
746 
747  interval_rep<POL> i(p,u,v);
749 
750  return slv.all_roots_separate();
751 }
752 
756  template<class Ring>
757  template<class Real,class POL>
758  Seq<Real>
760 
761  interval_rep<POL> i(p);
763 
764  return slv.all_roots_separate();
765 }
766 
767 
768 //--------------------------------------------------------------------
769  template<class Ring>
770  struct solver<Ring,CFdecide> {
771 
772  template<class POL> static bool
773  solve(const POL& p);
774 };
775 
779  template<class Ring>
780  template<class POL>
781  bool
783 
784  interval_rep<POL> i(p);
785  solver_cffirst<QQ,POL> slv(i);
786 
787  return ( slv.all_roots_isolate().size() );
788 }
789 
790 
791 } //namespace realroot
792 
793 #undef TMPL
794 #undef TMPLR
795 #undef NO_ROOT
796 #undef N_ITER
797 #endif // _realroot_SOLVER_FIRST_ROOT_CONFRAC_H
Real first_root_floor()
Definition: solver_ucf.hpp:473
void reciprocal_hom(const real &t)
Definition: homography.hpp:26
void reverse_box(const C &t=1)
Definition: solver_ucf.hpp:175
Sequence of terms with reference counter.
Definition: Seq.hpp:28
T pow(const T &a, int i)
Definition: binomials.hpp:12
Definition: solver_ucf.hpp:26
const C & b
Definition: Interval_glue.hpp:25
Definition: univariate_bounds.hpp:409
Definition: solver_ucf.hpp:24
#define BOX
Definition: solver_mv_monomial.hpp:35
Real width()
Definition: solver_ucf.hpp:120
C middle()
Definition: solver_ucf.hpp:133
const Interval & I
Definition: Interval_glue.hpp:49
static Solutions solve(const POL &p)
Definition: solver.hpp:75
MP swap(const MP &P, int var_i, int var_j)
Definition: sparse_monomials.hpp:988
interval_rep(const POL p, C u, C v)
Definition: solver_ucf.hpp:71
real a
Definition: homography.hpp:17
void shift_box(const C &t)
Definition: solver_ucf.hpp:150
Real eps
Definition: solver_ucf.hpp:213
void contract_box(const C &t)
Definition: solver_ucf.hpp:163
Ring::scalar_t base_t
Definition: solver_ucf.hpp:596
Definition: solver_ucf.hpp:23
void print()
Definition: solver_ucf.hpp:193
Definition: solver_ucf.hpp:28
Definition: fatarcs.hpp:23
Ring::Scalar base_t
Definition: solver_ucf.hpp:642
Definition: solver_ucf.hpp:47
Seq< Real > all_roots_separate()
Definition: solver_ucf.hpp:535
interval_rep(const POL p, homography< C > h)
Definition: solver_ucf.hpp:64
interval_rep(const POL p)
Definition: solver_ucf.hpp:58
#define TMPL
Definition: solver_ucf.hpp:17
real c
Definition: homography.hpp:17
size_type size() const
Definition: Seq.hpp:166
Seq< Interval< Real > > all_roots_isolate()
Definition: solver_ucf.hpp:519
Real point(C &t)
Definition: solver_ucf.hpp:127
Definition: solver_ucf.hpp:25
static RT lower_bound(const Poly &f)
Definition: univariate_bounds.hpp:413
homography< C > hom()
Definition: solver_ucf.hpp:85
Ring::Scalar base_t
Definition: solver_ucf.hpp:686
Definition: solver.hpp:68
Interval< Real > first_root_isolate()
Definition: solver_ucf.hpp:415
void contract_hom(const real &t)
Definition: homography.hpp:29
Ring::scalar_t base_t
Definition: solver_ucf.hpp:551
void shift_hom(const real &t)
Definition: homography.hpp:23
T lower(const Interval< T, r > &x)
Definition: Interval_fcts.hpp:87
TMPL POL
Definition: polynomial_dual.hpp:74
unsigned sign_var()
Definition: solver_ucf.hpp:143
Definition: solver_ucf.hpp:27
Seq< interval_rep< POL > > all_roots()
Definition: solver_ucf.hpp:321
Interval< Real > domain()
Definition: solver_ucf.hpp:89
#define Scalar
Definition: polynomial_operators.hpp:12
real b
Definition: homography.hpp:17
#define N_ITER
Definition: solver_ucf.hpp:19
Generic class for intervals.
Definition: Interval.hpp:44
T m
Definition: Interval.hpp:52
solver_cffirst(interval_rep< POL > p)
Definition: solver_ucf.hpp:215
interval_rep< POL > first_root()
Definition: solver_ucf.hpp:235
double C
Definition: solver_mv_fatarcs.cpp:16
Real first_root_approximate()
Definition: solver_ucf.hpp:430
unsigned sign_variation(Iterator b, Iterator e)
Definition: sign_variation.hpp:27
POL poly()
Definition: solver_ucf.hpp:83
Definition: solver_ucf.hpp:210
void assign(A &a, const B &b)
Generic definition of the assignement function.
Definition: assign.hpp:97
Ring::Scalar base_t
Definition: solver_ucf.hpp:729
Definition: array.hpp:12
double rfloor(double x)
Definition: scalar.hpp:535
interval_rep()
Definition: solver_ucf.hpp:56
#define TMPLR
Definition: solver_ucf.hpp:18
real d
Definition: homography.hpp:17
interval_rep< POL > ir
Definition: solver_ucf.hpp:212
void reverse_and_shift_box(const C &t=1)
Definition: solver_ucf.hpp:187
T M
Definition: Interval.hpp:52
Home