• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section:roots_noderiv Root Finding Without Derivatives]
2
3[h4 Synopsis]
4
5``
6#include <boost/math/tools/roots.hpp>
7``
8
9   namespace boost { namespace math {
10   namespace tools { // Note namespace boost::math::tools.
11   // Bisection
12   template <class F, class T, class Tol>
13   std::pair<T, T>
14      bisect(
15         F f,
16         T min,
17         T max,
18         Tol tol,
19         boost::uintmax_t& max_iter);
20
21   template <class F, class T, class Tol>
22   std::pair<T, T>
23      bisect(
24         F f,
25         T min,
26         T max,
27         Tol tol);
28
29   template <class F, class T, class Tol, class ``__Policy``>
30   std::pair<T, T>
31      bisect(
32         F f,
33         T min,
34         T max,
35         Tol tol,
36         boost::uintmax_t& max_iter,
37         const ``__Policy``&);
38
39   // Bracket and Solve Root
40   template <class F, class T, class Tol>
41   std::pair<T, T>
42      bracket_and_solve_root(
43         F f,
44         const T& guess,
45         const T& factor,
46         bool rising,
47         Tol tol,
48         boost::uintmax_t& max_iter);
49
50   template <class F, class T, class Tol, class ``__Policy``>
51   std::pair<T, T>
52      bracket_and_solve_root(
53         F f,
54         const T& guess,
55         const T& factor,
56         bool rising,
57         Tol tol,
58         boost::uintmax_t& max_iter,
59         const ``__Policy``&);
60
61  // TOMS 748 algorithm
62   template <class F, class T, class Tol>
63   std::pair<T, T>
64      toms748_solve(
65         F f,
66         const T& a,
67         const T& b,
68         Tol tol,
69         boost::uintmax_t& max_iter);
70
71   template <class F, class T, class Tol, class ``__Policy``>
72   std::pair<T, T>
73      toms748_solve(
74         F f,
75         const T& a,
76         const T& b,
77         Tol tol,
78         boost::uintmax_t& max_iter,
79         const ``__Policy``&);
80
81   template <class F, class T, class Tol>
82   std::pair<T, T>
83      toms748_solve(
84         F f,
85         const T& a,
86         const T& b,
87         const T& fa,
88         const T& fb,
89         Tol tol,
90         boost::uintmax_t& max_iter);
91
92   template <class F, class T, class Tol, class ``__Policy``>
93   std::pair<T, T>
94      toms748_solve(
95         F f,
96         const T& a,
97         const T& b,
98         const T& fa,
99         const T& fb,
100         Tol tol,
101         boost::uintmax_t& max_iter,
102         const ``__Policy``&);
103
104   // Termination conditions:
105   template <class T>
106   struct eps_tolerance;
107
108   struct equal_floor;
109   struct equal_ceil;
110   struct equal_nearest_integer;
111
112   }}} // boost::math::tools namespaces
113
114[h4 Description]
115
116These functions solve the root of some function ['f(x)] -
117['without the need for any derivatives of ['f(x)]].
118
119The `bracket_and_solve_root` functions use __root_finding_TOMS748
120by Alefeld, Potra and Shi that is asymptotically the most efficient known,
121and has been shown to be optimal for a certain classes of smooth functions.
122Variants with and without __policy_section are provided.
123
124Alternatively, __bisect is a simple __bisection_wikipedia routine which can be useful
125in its own right in some situations, or alternatively for narrowing
126down the range containing the root, prior to calling a more advanced
127algorithm.
128
129All the algorithms in this section reduce the diameter of the enclosing
130interval with the same asymptotic efficiency with which they locate the
131root.  This is in contrast to the derivative based methods which may ['never]
132significantly reduce the enclosing interval, even though they rapidly approach
133the root.  This is also in contrast to some other derivative-free methods
134(for example, Brent's method described at
135[@http://en.wikipedia.org/wiki/Brent%27s_method Brent-Dekker)]
136which only reduces the enclosing interval on the final step.
137Therefore these methods return a `std::pair` containing the enclosing interval found,
138and accept a function object specifying the termination condition.
139
140Three function objects are provided for ready-made termination conditions:
141
142* ['eps_tolerance] causes termination when the relative error in the enclosing
143interval is below a certain threshold.
144* ['equal_floor] and ['equal_ceil] are useful for certain statistical applications
145where the result is known to be an integer.
146* Other user-defined termination conditions are likely to be used
147only rarely, but may be useful in some specific circumstances.
148
149[section:bisect Bisection]
150
151   template <class F, class T, class Tol>
152   std::pair<T, T>
153      bisect(  // Unlimited iterations.
154         F f,
155         T min,
156         T max,
157         Tol tol);
158
159   template <class F, class T, class Tol>
160   std::pair<T, T>
161      bisect(  // Limited iterations.
162         F f,
163         T min,
164         T max,
165         Tol tol,
166         boost::uintmax_t& max_iter);
167
168   template <class F, class T, class Tol, class ``__Policy``>
169   std::pair<T, T>
170      bisect( // Specified policy.
171         F f,
172         T min,
173         T max,
174         Tol tol,
175         boost::uintmax_t& max_iter,
176         const ``__Policy``&);
177
178These functions locate the root using __bisection_wikipedia.
179
180`bisect` function arguments are:
181
182[variablelist
183[[f]  [A unary functor (or C++ lambda) which is the function ['f(x)] whose root is to be found.]]
184[[min] [The left bracket of the interval known to contain the root.]]
185[[max] [The right bracket of the interval known to contain the root.[br]
186        It is a precondition that ['min < max] and ['f(min)*f(max) <= 0],
187        the function raises an __evaluation_error if these preconditions are violated.
188        The action taken on error is controlled by the __Policy template argument: the default behavior is to
189        throw a ['boost::math::evaluation_error].  If the __Policy is changed to not throw
190        then it returns ['std::pair<T>(min, min)].]]
191[[tol]  [A binary functor (or C++ lambda) that specifies the termination condition: the function
192        will return the current brackets enclosing the root when ['tol(min, max)] becomes true.
193        See also __root_termination.]]
194[[max_iter][The maximum number of invocations of ['f(x)] to make while searching for the root.  On exit, this is updated to the actual number of invocations performed.]]
195]
196
197[optional_policy]
198
199[*Returns]: a pair of values ['r] that bracket the root so that:
200
201[:f(r.first) * f(r.second) <= 0]
202
203and either
204
205[:tol(r.first, r.second) == true]
206
207or
208
209[:max_iter >= m]
210
211where ['m] is the initial value of ['max_iter] passed to the function.
212
213In other words, it's up to the caller to verify whether termination occurred
214as a result of exceeding ['max_iter] function invocations (easily done by
215checking the updated value of ['max_iter] when the function returns), rather than
216because the termination condition ['tol] was satisfied.
217
218[endsect] [/section:bisect Bisection]
219
220[section:bracket_solve Bracket and Solve Root]
221
222   template <class F, class T, class Tol>
223   std::pair<T, T>
224      bracket_and_solve_root(
225         F f,
226         const T& guess,
227         const T& factor,
228         bool rising,
229         Tol tol,
230         boost::uintmax_t& max_iter);
231
232   template <class F, class T, class Tol, class ``__Policy``>
233   std::pair<T, T>
234      bracket_and_solve_root(
235         F f,
236         const T& guess,
237         const T& factor,
238         bool rising,
239         Tol tol,
240         boost::uintmax_t& max_iter,
241         const ``__Policy``&);
242
243`bracket_and_solve_root` is a convenience function that calls __root_finding_TOMS748 internally
244to find the root of ['f(x)].  It is generally much easier to use this function rather than __root_finding_TOMS748, since it
245does the hard work of bracketing the root for you.  It's bracketing routines are quite robust and will
246usually be more foolproof than home-grown routines, unless the function can be analysed to yield tight
247brackets.
248
249Note that this routine can only be used when:
250
251* ['f(x)] is monotonic in the half of the real axis containing ['guess].
252* The value of the initial guess must have the same sign as the root: the function
253will ['never cross the origin] when searching for the root.
254* The location of the root should be known at least approximately,
255if the location of the root differs by many orders of magnitude
256from ['guess] then many iterations will be needed to bracket the root in spite of
257the special heuristics used to guard against this very situation.  A typical example would be
258setting the initial guess to 0.1, when the root is at 1e-300.
259
260The `bracket_and_solve_root` parameters are:
261
262[variablelist
263[[f][A unary functor (or C++ lambda) that is the function whose root is to be solved.
264    ['f(x)] must be uniformly increasing or decreasing on ['x].]]
265[[guess][An initial approximation to the root.]]
266[[factor][A scaling factor that is used to bracket the root: the value
267         /guess/ is multiplied (or divided as appropriate) by /factor/
268         until two values are found that bracket the root.  A value
269         such as 2 is a typical choice for ['factor].
270         In addition ['factor] will be multiplied by 2 every 32 iterations:
271         this is to guard against a really very bad initial guess, typically these occur
272         when it's known the result is very large or small, but not the exact order
273         of magnitude.]]
274[[rising][Set to ['true] if ['f(x)] is rising on /x/ and /false/ if ['f(x)]
275         is falling on /x/.  This value is used along with the result
276         of /f(guess)/ to determine if /guess/ is
277         above or below the root.]]
278[[tol]   [A binary functor (or C++ lambda) that determines the termination condition for the search
279         for the root.  /tol/ is passed the current brackets at each step,
280         when it returns true then the current brackets are returned as the pair result.
281         See also __root_termination.]]
282[[max_iter] [The maximum number of function invocations to perform in the search
283            for the root.  On exit is set to the actual number of invocations performed.]]
284]
285
286[optional_policy]
287
288[*Returns]: a pair of values ['r] that bracket the root so that:
289
290[:f(r.first) * f(r.second) <= 0]
291
292and either
293
294[:tol(r.first, r.second) == true]
295
296or
297
298[:max_iter >= m]
299
300where ['m] is the initial value of ['max_iter] passed to the function.
301
302In other words, it's up to the caller to verify whether termination occurred
303as a result of exceeding ['max_iter] function invocations (easily done by
304checking the value of ['max_iter]  when the function returns), rather than
305because the termination condition ['tol] was satisfied.
306
307[endsect] [/section:bracket_solve Bracket and Solve Root]
308
309[section:TOMS748 Algorithm TOMS 748: Alefeld, Potra and Shi: Enclosing zeros of continuous functions]
310
311   template <class F, class T, class Tol>
312   std::pair<T, T>
313      toms748_solve(
314         F f,
315         const T& a,
316         const T& b,
317         Tol tol,
318         boost::uintmax_t& max_iter);
319
320   template <class F, class T, class Tol, class ``__Policy``>
321   std::pair<T, T>
322      toms748_solve(
323         F f,
324         const T& a,
325         const T& b,
326         Tol tol,
327         boost::uintmax_t& max_iter,
328         const ``__Policy``&);
329
330   template <class F, class T, class Tol>
331   std::pair<T, T>
332      toms748_solve(
333         F f,
334         const T& a,
335         const T& b,
336         const T& fa,
337         const T& fb,
338         Tol tol,
339         boost::uintmax_t& max_iter);
340
341   template <class F, class T, class Tol, class ``__Policy``>
342   std::pair<T, T>
343      toms748_solve(
344         F f,
345         const T& a,
346         const T& b,
347         const T& fa,
348         const T& fb,
349         Tol tol,
350         boost::uintmax_t& max_iter,
351         const ``__Policy``&);
352
353These functions implement TOMS Algorithm 748: it uses a mixture of
354cubic, quadratic and linear (secant) interpolation to locate the root of
355['f(x)].  The two pairs of functions differ only by whether values for ['f(a)] and
356['f(b)] are already available.
357
358Generally speaking it is easier (and often more efficient) to use __bracket_solve
359rather than trying to bracket the root yourself as this function requires.
360
361This function is provided rather than [@http://en.wikipedia.org/wiki/Brent%27s_method Brent's method] as it is known to be more
362efficient in many cases (it is asymptotically the most efficient known,
363and has been shown to be optimal for a certain classes of smooth functions).
364It also has the useful property of decreasing the bracket size
365with each step, unlike Brent's method which only shrinks the enclosing interval in the
366final step.  This makes it particularly useful when you need a result where the ends
367of the interval round to the same integer: as often happens in statistical applications,
368for example.  In this situation the function is able to exit after a much smaller
369number of iterations than would otherwise be possible.
370
371The __root_finding_TOMS748 parameters are:
372
373[variablelist
374[[f]   [A unary functor (or C++ lambda) that is the function whose root is to be solved.
375       f(x) need not be uniformly increasing or decreasing on ['x] and
376       may have multiple roots.  However, the bounds given must bracket a single root.]]
377[[a]   [The lower bound for the initial bracket of the root.]]
378[[b]   [The upper bound for the initial bracket of the root.
379       It is a precondition that ['a < b] and that ['a] and ['b]
380       bracket the root to find so that ['f(a) * f(b) < 0].]]
381[[fa]  [Optional: the value of ['f(a)].]]
382[[fb]  [Optional: the value of ['f(b)].]]
383[[tol] [A binary functor (or C++ lambda) that determines the termination condition for the search
384        for the root.  ['tol] is passed the current brackets at each step,
385        when it returns true, then the current brackets are returned as the result.
386        See also __root_termination.]]
387[[max_iter] [The maximum number of function invocations to perform in the search
388            for the root.  On exit, ['max_iter] is set to actual number of function
389            invocations used.]]
390]
391
392[optional_policy]
393
394`toms748_solve` returns: a pair of values ['r] that bracket the root so that:
395
396[:['f(r.first) * f(r.second) <= 0]]
397
398and either
399
400[:['tol(r.first, r.second) == true]]
401
402or
403
404[:['max_iter >= m]]
405
406where ['m] is the initial value of ['max_iter] passed to the function.
407
408In other words, it's up to the caller to verify whether termination occurred
409as a result of exceeding ['max_iter]  function invocations (easily done by
410checking the updated value of ['max_iter]
411against its previous value passed as parameter),
412rather than because the termination condition ['tol] was satisfied.
413
414[endsect] [/section:TOMS748 Algorithm TOMS 748: Alefeld, Potra and Shi: Enclosing zeros of continuous functions]
415
416[section:brent Brent-Decker Algorithm]
417
418The [@http://en.wikipedia.org/wiki/Brent%27s_method Brent-Dekker algorithm], although very well know,
419is not provided by this library as __root_finding_TOMS748 or
420its slightly easier to use variant __bracket_solve are superior and provide equivalent functionality.
421
422[endsect] [/section:brent Brent-Decker Algorithm]
423
424[section:root_termination Termination Condition Functors]
425
426   template <class T>
427   struct eps_tolerance
428   {
429      eps_tolerance();
430      eps_tolerance(int bits);
431      bool operator()(const T& a, const T& b)const;
432   };
433
434`eps_tolerance` is the usual termination condition used with these root finding functions.
435Its `operator()` will return true when the relative distance between ['a] and ['b]
436is less than four times the machine epsilon for T, or 2[super 1-bits], whichever is
437the larger.  In other words, you set ['bits] to the number of bits of precision you
438want in the result.  The minimal tolerance of ['four times the machine epsilon of type T] is
439required to ensure that we get back a bracketing interval, since this must clearly
440be at greater than one epsilon in size.  While in theory a maximum distance of twice
441machine epsilon is possible to achieve, in practice this results in a great deal of "thrashing"
442given that the function whose root is being found can only ever be accurate to 1 epsilon at best.
443
444   struct equal_floor
445   {
446      equal_floor();
447      template <class T> bool operator()(const T& a, const T& b)const;
448   };
449
450This termination condition is used when you want to find an integer result
451that is the ['floor] of the true root.  It will terminate as soon as both ends
452of the interval have the same ['floor].
453
454   struct equal_ceil
455   {
456      equal_ceil();
457      template <class T> bool operator()(const T& a, const T& b)const;
458   };
459
460This termination condition is used when you want to find an integer result
461that is the ['ceil] of the true root.  It will terminate as soon as both ends
462of the interval have the same ['ceil].
463
464   struct equal_nearest_integer
465   {
466      equal_nearest_integer();
467      template <class T> bool operator()(const T& a, const T& b)const;
468   };
469
470This termination condition is used when you want to find an integer result
471that is the /closest/ to the true root.  It will terminate as soon as both ends
472of the interval round to the same nearest integer.
473
474[endsect] [/section:root_termination Termination Condition Functors]
475
476[section:implementation Implementation]
477
478The implementation of the bisection algorithm is extremely straightforward
479and not detailed here.
480
481__TOMS748 is described in detail in:
482
483['Algorithm 748: Enclosing Zeros of Continuous Functions,
484G. E. Alefeld, F. A. Potra and Yixun Shi,
485ACM Transactions on Mathematica1 Software, Vol. 21. No. 3. September 1995.
486Pages 327-344.]
487
488The implementation here is a faithful translation of this paper into C++.
489
490[endsect] [/section:implementation Implementation]
491
492[endsect] [/section:roots_noderiv Root Finding Without Derivatives]
493
494[/
495  Copyright 2006, 2010, 2015 John Maddock and Paul A. Bristow.
496  Distributed under the Boost Software License, Version 1.0.
497  (See accompanying file LICENSE_1_0.txt or copy at
498  http://www.boost.org/LICENSE_1_0.txt).
499]
500