Developer documentation

solver_uv_interval_newton.hpp
Go to the documentation of this file.
1 /*******************************************************************
2  * This file is part of the source code of the realroot kernel.
3  * Description: The Interval Newton method to approximate a root of a
4  * polynomial given an initial interval that contains it.
5  * Author(s):
6  * G. Tzoumas <geotz@di.uoa.gr>
7  * Department of Informatics and Telecommunications
8  * University of Athens (Greece).
9  ********************************************************************/
10 #ifndef _realroot_solve_inewton_hpp_
11 #define _realroot_solve_inewton_hpp_
12 
21 //#include <numerix/interval.hpp>
22 //#include <realroot/Interval.hpp>
24 #include <realroot/Seq.hpp>
25 
26 namespace mmx {
27 
28 /* // perhaps it might come handy in the future -- I leave it in comments
29  namespace inewton {
30 
31  template<class C> struct IntervalTraits { };
32 
33  template<> template<class B> struct IntervalTraits<Interval<B> > {
34  typedef Interval<B> interval_type;
35  typedef B boundary_type;
36 
37  static inline boundary_type upper(const interval_type& x) { return x.upper(); }
38  static inline boundary_type lower(const interval_type& x) { return x.lower(); }
39  static inline boundary_type width(const interval_type& x) { return x.width(); }
40  static inline boundary_type median(const interval_type& x) { return x; }
41  static inline int sign(const interval_type& x) { return ::mmx::sign(x); }
42  static inline bool intersect(interval_type &r, const interval_type &a, const interval_type &b) {
43  return ::mmx::intersect(r, a, b);
44  }
45  };
46 
47  template<> template<class B> struct IntervalTraits<interval<B> > {
48  typedef interval<B> interval_type;
49  typedef B boundary_type;
50 
51  static inline boundary_type upper(const interval_type& x) { return ::mmx::upper(x); }
52  static inline boundary_type lower(const interval_type& x) { return ::mmx::lower(x); }
53  static inline boundary_type width(const interval_type& x) { return upper(x)-lower(x); }
54  static inline boundary_type median(const interval_type& x) { return ::mmx::center(x); }
55  static inline int sign(const interval_type& x) { return ::mmx::sign(x); }
56  static inline bool intersect(interval_type &r, const interval_type &a, const interval_type &b) {
57  if ((upper(a) < lower(b)) || (lower(a) > upper(b))) return false;
58  r = interval_type(std::max(lower(a), lower(b)), std::min(upper(a), upper(b)));
59  return true;
60  }
61  };
62 
63  } */
64 
65  template<class INT, class CT> struct interval_newton
66  {
68  typedef typename INT::boundary_type BT;
69 
70  static inline BT width(const INT& x) { return mmx::upper(x) - mmx::lower(x); }
71  static inline BT median(const INT& x) { return mmx::lower(x) + width(x)/BT(2); }
72  static bool singleton(const INT& x) { return mmx::lower(x) == mmx::upper(x); }
73 
74  static INT bisection_iteration(const polynomial& p, const INT approx, int& status_)
75  {
76  BT x = median(approx);
77  INT lval, rval, mval;
78  lval = p(INT(mmx::lower(approx)));
79  rval = p(INT(mmx::upper(approx)));
80  mval = p(INT(x));
81  // std::cerr << lval << ' ' << rval << ' ' << mval << ' ' << x << std::endl;
82  // assert( mmx::sign(lval)*mmx::sign(rval) <= 0 );
83 
84  status_ = 0;
85  if (mval == 0) return INT(x);
86  if (lval == 0) return INT(mmx::lower(approx));
87  if (rval == 0) return INT(mmx::upper(approx));
88 
89  if (mmx::sign(lval) == 0 || mmx::sign(rval) == 0) {
90  status_ = -3; return approx;
91  }
92 
93  if (mmx::sign(lval) == mmx::sign(rval)) {
94  status_ = -1; return approx;
95  }
96 
97  if (mmx::sign(mval) == 0) return approx;
98 
99  if (mmx::sign(lval) == mmx::sign(mval)) return INT(x,mmx::upper(approx));
100  return INT(mmx::lower(approx), x);
101  }
102 
103  /*
104  status:
105  -4 = no convergence (should not happen!)
106  -3 = precision not enough
107  -2 = no root exists
108  -1 = no root found (cannot guarantee existence)
109  0 = root found (cannot guarantee uniqueness)
110  1 = unique root found
111  */
112  // caution with coeffs including zero!
113  static INT newton_iteration(const polynomial& p, const polynomial& dp,
114  INT approx, BT delta_, int& status_)
115  {
116  INT slope, testapprox, newapprox, ver;
117  BT oldw = width(approx);
118  BT neww;
119  int z;
120 
121 #ifdef INEWTONDEBUG
122  int i = 0;
123 #endif
124 
125  INT lval, rval;
126 
127  lval = p(INT(mmx::lower(approx)));
128  rval = p(INT(mmx::upper(approx)));
129 #ifdef INEWTONDEBUG
130  std::cerr << "approx = " << approx << " lval = " << lval << " rval = " << rval << std::endl;
131 #endif
132  if (lval == 0) { status_ = 0; return INT(mmx::lower(approx)); }
133  if (rval == 0) { status_ = 0; return INT(mmx::upper(approx)); }
134  if (mmx::sign(lval) == 0 || mmx::sign(rval) == 0) {
135  status_ = -3; return approx;
136  }
137 
138  status_ = 0;
139  slope = dp(approx);
140 
141 #ifdef INEWTONDEBUG
142  std::cerr << "slope = " << slope << width(slope) << std::endl;
143 #endif
144 
145  z = mmx::sign(slope);
146  if (mmx::sign(lval) == mmx::sign(rval)) {
147  if (z == 0) status_ = -1; else status_ = -2;
148  return approx;
149  }
150 
151 #ifdef INEWTONDEBUG
152  std::cerr << "solving " << p << std::endl;
153 #endif
154 
155  /* INTERVAL NEWTON MAIN LOOP */
156  while (1) {
157  // should we always do simple bisection with intervals of length >= 1 ?
158  // if (oldw >= 1 || z == 0) {
159 
160  // slope contains zero
161  if (z == 0) {
162  approx = bisection_iteration(p, approx, status_);
163  neww = width(approx);
164 #ifdef INEWTONDEBUG
165  i++;
166  std::cerr << '(' << i << ") bisect: " << approx << ' ' << neww << std::endl;
167 #endif
168  if (status_ < 0) return approx;
169  if (neww < delta_) break;
170  assert(neww <= oldw);
171  if (neww == oldw) break;
172  oldw = neww;
173 
174  } else {
175  // slope doesn't contain zero
176 
177  BT x = median(approx);
178  if (x == mmx::lower(approx) || x == mmx::upper(approx)) break;
179 #ifdef INEWTONDEBUG
180  std::cerr << "mid = " << x << " mid_INT = " << INT(x) << std::endl;
181  std::cerr << "p(x) = " << p(INT(x)) << std::endl;
182  std::cerr << "p'(approx) = " << dp(approx) << std::endl;
183  std::cerr << "p/p' = " << INT(p(INT(x))/dp(approx)) << std::endl;
184 #endif
185  testapprox = INT(x) - INT(p(INT(x))/dp(approx)); // Newton approximation
186 
187 #ifdef INEWTONDEBUG
188  i++;
189 #endif
190  if (mmx::intersect(newapprox, testapprox, approx)) {
191 #ifdef INEWTONDEBUG
192  std::cerr <<"new =" << newapprox << " test = " << testapprox << " old = " << approx << std::endl;
193 #endif
194  neww = width(newapprox);
195 
196  // new approximation SHOULD contain the root
197  // if you want to verify, use the debugging code below
198 #ifdef INEWTONDEBUG
199  INT ver = p(newapprox);
200  if (ver != INT(0)) {
201  assert (mmx::sign(ver) == 0);
202  }
203 
204  std::cerr << '(' << i << ") Newton: " << newapprox << ' ' << neww << std::endl;
205 #endif
206  //if (Float(2)*neww >= oldw) break;
207  if (neww >= oldw) break;
208  approx = newapprox;
209  if (neww < delta_) break;
210  oldw = neww;
211  } else {
212  // no convergence
213  status_ = -4;
214  return approx;
215  }
216  }
217  slope = dp(approx);
218 #ifdef INEWTONDEBUG
219  std::cerr << "slope = " << slope << width(slope) << std::endl;
220 #endif
221  z = mmx::sign(slope);
222  }
223  if (mmx::sign(dp(approx)) != 0) status_ = 1;
224 #ifdef INEWTONDEBUG
225  std::cerr << "iters = " << i << std::endl;
226 #endif
227  return approx;
228  }
229 
230  };
231 
232  template<class INT, class C> struct IntervalNewton
233  {
235  typedef typename INT::boundary_type BT;
237 
239  BT delta;
240  int status;
241 
242  IntervalNewton(INT approx_, BT delta_ = 0): initial_approx(approx_), delta(delta_), status(0) { };
243 
244  };
245 
246  template<class C, class M> struct solver_of;
247 
248  template<class C, class IT>
249  struct solver_of<C,IntervalNewton<IT,C> > {
250  typedef IT Cell;
253  };
254 
255  template<class POL, class IT>
258  {
259  typedef typename POL::coeff_t coeff_t;
260  typedef typename IntervalNewton<IT,coeff_t>::solver_t solver_t;
262 
263  POL df = diff(f);
264  sol << solver_t::newton_iteration(f, df, s.initial_approx, s.delta, s.status);
265 
266  return sol;
267  }
268 
269 
270 } //namespace mmx
271 #endif // _realroot_solve_inewton_hpp_
Sequence of terms with reference counter.
Definition: Seq.hpp:28
TMPL Polynomial diff(const Polynomial &pol, int v)
Multivariate Polynomial Differentiation.
Definition: polynomial_fcts.hpp:99
std::vector< C > approx(polynomial< C, with< Bernstein > > poly, std::vector< C > ep1, std::vector< C > ep2, int MTH)
Definition: fatarcs_fcts.hpp:276
static INT bisection_iteration(const polynomial &p, const INT approx, int &status_)
Definition: solver_uv_interval_newton.hpp:74
ring< CT, MonomialTensor >::Polynomial polynomial
Definition: solver_uv_interval_newton.hpp:67
T upper(const Interval< T, r > &x)
Definition: Interval_fcts.hpp:89
INT::boundary_type BT
Definition: solver_uv_interval_newton.hpp:235
IT Cell
Definition: solver_uv_interval_newton.hpp:250
static BT median(const INT &x)
Definition: solver_uv_interval_newton.hpp:71
Definition: solver_uv_interval_newton.hpp:65
bool intersect(Interval< T, r > &result, const Interval< T, r > &a, const Interval< T, r > &b)
Definition: Interval_fcts.hpp:150
Seq< typename ContFrac< NT, LB >::root_t > solve(const typename ContFrac< NT >::Poly &f, ContFrac< NT, LB >)
Definition: contfrac.hpp:164
static INT newton_iteration(const polynomial &p, const polynomial &dp, INT approx, BT delta_, int &status_)
Definition: solver_uv_interval_newton.hpp:113
static bool singleton(const INT &x)
Definition: solver_uv_interval_newton.hpp:72
INT initial_approx
Definition: solver_uv_interval_newton.hpp:238
IntervalNewton(INT approx_, BT delta_=0)
Definition: solver_uv_interval_newton.hpp:242
interval_newton< INT, C > solver_t
Definition: solver_uv_interval_newton.hpp:234
INT::boundary_type BT
Definition: solver_uv_interval_newton.hpp:68
BT delta
Definition: solver_uv_interval_newton.hpp:239
Seq< IT > Solutions
Definition: solver_uv_interval_newton.hpp:252
Definition: polynomial.hpp:37
T lower(const Interval< T, r > &x)
Definition: Interval_fcts.hpp:87
TMPL POL
Definition: polynomial_dual.hpp:74
IntervalNewton< IT, C > Strategy
Definition: solver_uv_interval_newton.hpp:251
Seq< INT > solutions_t
Definition: solver_uv_interval_newton.hpp:236
Definition: solver.hpp:61
int status
Definition: solver_uv_interval_newton.hpp:240
double C
Definition: solver_mv_fatarcs.cpp:16
int sign(const QQ &a)
Definition: GMP.hpp:60
Definition: solver_uv_interval_newton.hpp:232
static BT width(const INT &x)
Definition: solver_uv_interval_newton.hpp:70
Definition: array.hpp:12
#define assert(expr, msg)
Definition: shared_object.hpp:57
Home