bpp-core  2.2.0
BrentOneDimension.cpp
Go to the documentation of this file.
1 //
2 // File: BrentOneDimension.cpp
3 // Created by: Julien Dutheil
4 // Created on: Mon Nov 17 11:45:58 2003
5 //
6 
7 /*
8 Copyright or © or Copr. CNRS, (November 17, 2004)
9 
10 This software is a computer program whose purpose is to provide classes
11 for numerical calculus.
12 
13 This software is governed by the CeCILL license under French law and
14 abiding by the rules of distribution of free software. You can use,
15 modify and/ or redistribute the software under the terms of the CeCILL
16 license as circulated by CEA, CNRS and INRIA at the following URL
17 "http://www.cecill.info".
18 
19 As a counterpart to the access to the source code and rights to copy,
20 modify and redistribute granted by the license, users are provided only
21 with a limited warranty and the software's author, the holder of the
22 economic rights, and the successive licensors have only limited
23 liability.
24 
25 In this respect, the user's attention is drawn to the risks associated
26 with loading, using, modifying and/or developing or reproducing the
27 software by the user in light of its specific status of free software,
28 that may mean that it is complicated to manipulate, and that also
29 therefore means that it is reserved for developers and experienced
30 professionals having in-depth computer knowledge. Users are therefore
31 encouraged to load and test the software's suitability as regards their
32 requirements in conditions enabling the security of their systems and/or
33 data to be ensured and, more generally, to use and operate it in the
34 same conditions as regards security.
35 
36 The fact that you are presently reading this means that you have had
37 knowledge of the CeCILL license and that you accept its terms.
38 */
39 
40 #include "BrentOneDimension.h"
42 #include "../NumTools.h"
43 #include "../NumConstants.h"
44 #include "../../Text/TextTools.h"
45 
46 using namespace bpp;
47 
48 /******************************************************************************/
49 
51 {
52  callCount_++;
53  if (callCount_ <= burnin_) return false;
54  const BrentOneDimension* bod = dynamic_cast<const BrentOneDimension *>(optimizer_);
55  return getCurrentTolerance() <= (bod->tol2 - 0.5 * (bod->b - bod->a));
56 }
57 
58 /******************************************************************************/
59 
61 {
62  // NRC Test for done:
63  const BrentOneDimension* bod = dynamic_cast<const BrentOneDimension *>(optimizer_);
64  return NumTools::abs(bod->x - bod->xm);
65 }
66 
67 /******************************************************************************/
68 
70  AbstractOptimizer(function),
71  a(0), b(0), d(0), e(0), etemp(0), fu(0), fv(0), fw(0), fx(0), p(0), q(0), r(0), tol1(0), tol2(0),
72  u(0), v(0), w(0), x(0), xm(0), _xinf(0), _xsup(0), isInitialIntervalSet_(false)
73 {
77 }
78 
79 /******************************************************************************/
80 
81 double BrentOneDimension::ZEPS = 1.0e-10;
82 
83 /******************************************************************************/
84 
86 {
87  if (params.size() != 1)
88  throw Exception("BrentOneDimension::init(). This optimizer only deals with one parameter.");
89 
90  // Bracket the minimum.
91  Bracket bracket = OneDimensionOptimizationTools::bracketMinimum(_xinf, _xsup, getFunction(), getParameters());
92  if (getVerbose() > 0)
93  {
94  printMessage("Initial bracketing:");
95  printMessage("A: x = " + TextTools::toString(bracket.a.x) + ", f = " + TextTools::toString(bracket.a.f));
96  printMessage("B: x = " + TextTools::toString(bracket.b.x) + ", f = " + TextTools::toString(bracket.b.f));
97  printMessage("C: x = " + TextTools::toString(bracket.c.x) + ", f = " + TextTools::toString(bracket.c.f));
98  }
99 
100  // This will be the distance moved on the step before last.
101  e = 0.0;
102 
103  // a and b must be in ascending order, but input abscissa need not be.
104  a = (bracket.a.x < bracket.c.x ? bracket.a.x : bracket.c.x);
105  b = (bracket.a.x > bracket.c.x ? bracket.a.x : bracket.c.x);
106  // Initializations...
107  fw = fv = fx = getFunction()->f(getParameters());
108  if (fx < bracket.b.f)
109  {
110  //We don't want to lose our initial guess!
111  x = w = v = bracket.b.x = getParameters()[0].getValue();
112  }
113  else
114  {
115  x = w = v = bracket.b.x;
116  getParameter_(0).setValue(x);
117  fw = fv = fx = getFunction()->f(getParameters());
118  }
119 }
120 
121 /******************************************************************************/
122 
123 void BrentOneDimension::setInitialInterval(double inf, double sup)
124 {
125  if(sup > inf)
126  {
127  _xinf = inf; _xsup = sup;
128  }
129  else
130  {
131  _xinf = sup; _xsup = inf;
132  }
133  isInitialIntervalSet_ = true;
134 }
135 
136 /******************************************************************************/
137 
139 {
140  xm = 0.5 * (a + b);
141  tol2 = 2.0 * (tol1 = getStopCondition()->getTolerance() * NumTools::abs(x) + ZEPS);
142 
143  if(NumTools::abs(e) > tol1)
144  {
145  r = (x - w) * (fx - fv);
146  q = (x - v) * (fx - fw);
147  p = (x - v) * q - (x - w) * r;
148  q = 2.0 * (q - r);
149  if (q > 0.0) p = -p;
150  q = NumTools::abs(q);
151  etemp = e;
152  e = d;
153  if (NumTools::abs(p) >= NumTools::abs(0.5 * q * etemp) || p <= q * (a - x) || p >= q * (b - x))
154  d = NumConstants::GOLDEN_RATIO_C() * (e = (x >= xm ? a - x : b - x));
155  else
156  {
157  d = p / q;
158  u = x + d;
159  if (u - a < tol2 || b - u < tol2)
160  d = NumTools::sign(tol1, xm - x);
161  }
162  }
163  else
164  {
165  d = NumConstants::GOLDEN_RATIO_C() * (e = (x >= xm ? a - x : b - x));
166  }
167  u = (NumTools::abs(d) >= tol1 ? x + d : x + NumTools::sign(tol1, d));
168 
169  // Function evaluaton:
171  pl[0].setValue(u);
172  fu = getFunction()->f(pl);
173  if (fu <= fx)
174  {
175  if (u >= x) a = x; else b = x;
176  NumTools::shift(v, w, x, u);
177  NumTools::shift(fv, fw, fx, fu);
178  }
179  else
180  {
181  if (u < x) a = u; else b = u;
182  if (fu <= fw || w == x)
183  {
184  v = w;
185  w = u;
186  fv = fw;
187  fw = fu;
188  }
189  else if (fu <= fv || v == x || v == w)
190  {
191  v = u;
192  fv = fu;
193  }
194  }
195 
196  // Store results for this step:
198  return fx;
199 }
200 
201 /******************************************************************************/
202 
204 {
206  throw Exception("BrentOneDimension::optimize. Initial interval not set: call the 'setInitialInterval' method first!");
208  // Apply parameters and evaluate function at minimum point:
210  return currentValue_;
211 }
212 
213 /******************************************************************************/
214 
virtual double f(const ParameterList &parameters)
Get the value of the function according to a given set of parameters.
Definition: Functions.h:117
OptimizationStopCondition * getStopCondition()
Get the stop condition of the optimization algorithm.
static T sign(T a)
Get the sign of a value.
Definition: NumTools.h:77
This class allows to perform a correspondence analysis.
double optimize()
Basic implementation.
This is the function abstract class.
Definition: Functions.h:86
static double GOLDEN_RATIO_C()
Definition: NumConstants.h:67
void setMaximumNumberOfEvaluations(unsigned int max)
Set the maximum number of function evaluation to perform during optimization.
static std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:189
The parameter list object.
Definition: ParameterList.h:61
virtual void setValue(double value)
Set the value of this parameter.
Definition: Parameter.cpp:123
void setDefaultStopCondition_(OptimizationStopCondition *osc)
Parameter & getParameter_(size_t i)
const Function * getFunction() const
Get the current function being optimized.
static Bracket bracketMinimum(double a, double b, Function *function, ParameterList parameters)
Bracket a minimum.
const ParameterList & getParameters() const
bool isToleranceReached() const
Tell if the we reached the desired tolerance with a given new set of estimates.
double getCurrentTolerance() const
Get the current tolerance.
double optimize()
Initialize optimizer.
Exception base class.
Definition: Exceptions.h:57
Brent&#39;s optimization for one parameter.
double callCount_
Count the number of times the isToleranceReached() function has been called.
Partial implementation of the Optimizer interface.
double currentValue_
The current value of the function.
void doInit(const ParameterList &params)
This function is called by the init() method and contains all calculations.
void setStopCondition(const OptimizationStopCondition &stopCondition)
Set the stop condition of the optimization algorithm.
double doStep()
This function is called by the step() method and contains all calculations.
virtual double getTolerance() const =0
Get the tolerance parameter.
void setInitialInterval(double inf, double sup)
Set intial search interval.
OptimizationStopCondition * getDefaultStopCondition()
Get the default stop condition of the optimization algorithm.
BrentOneDimension(Function *function=0)
static void shift(T &a, T &b, T c)
Definition: NumTools.h:145
static T abs(T a)
Get the magnitude of a value.
Definition: NumTools.h:66