bpp-core3  3.0.0
BrentOneDimension.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "../../Text/TextTools.h"
6 #include "../NumConstants.h"
7 #include "../NumTools.h"
8 #include "BrentOneDimension.h"
10 
11 using namespace bpp;
12 
13 /******************************************************************************/
14 
16 {
17  callCount_++;
18  if (callCount_ <= burnin_)
19  return false;
20  const BrentOneDimension* bod = dynamic_cast<const BrentOneDimension*>(optimizer_);
21  return getCurrentTolerance() <= (bod->tol2 - 0.5 * (bod->b - bod->a));
22 }
23 
24 /******************************************************************************/
25 
27 {
28  // NRC Test for done:
29  const BrentOneDimension* bod = dynamic_cast<const BrentOneDimension*>(optimizer_);
30  return NumTools::abs(bod->x - bod->xm);
31 }
32 
33 /******************************************************************************/
34 
35 BrentOneDimension::BrentOneDimension(std::shared_ptr<FunctionInterface> function) :
37  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),
38  u(0), v(0), w(0), x(0), xm(0), _xinf(0), _xsup(0), isInitialIntervalSet_(false), bracketing_(BrentOneDimension::BRACKET_OUTWARD)
39 {
40  setDefaultStopCondition_(make_shared<BODStopCondition>(this));
43 }
44 
45 /******************************************************************************/
46 
47 double BrentOneDimension::ZEPS = 1.0e-10;
48 
49 /******************************************************************************/
50 
52 {
53  if (params.size() != 1)
54  throw Exception("BrentOneDimension::init(). This optimizer only deals with one parameter.");
55 
56  // Bracket the minimum.
57  Bracket bracket;
59  {
61  }
62  else
63  {
65  }
66 
67  if (getVerbose() > 0)
68  {
69  printMessage("Initial bracketing:");
70  printMessage("A: x = " + TextTools::toString(bracket.a.x) + ", f = " + TextTools::toString(bracket.a.f));
71  printMessage("B: x = " + TextTools::toString(bracket.b.x) + ", f = " + TextTools::toString(bracket.b.f));
72  printMessage("C: x = " + TextTools::toString(bracket.c.x) + ", f = " + TextTools::toString(bracket.c.f));
73  }
74 
75  // This will be the distance moved on the step before last.
76  e = 0.0;
77 
78  // a and b must be in ascending order, but input abscissa need not be.
79  a = (bracket.a.x < bracket.c.x ? bracket.a.x : bracket.c.x);
80  b = (bracket.a.x > bracket.c.x ? bracket.a.x : bracket.c.x);
81  // Initializations...
82  fw = fv = fx = getFunction()->f(getParameters());
83  if (fx < bracket.b.f)
84  {
85  // We don't want to lose our initial guess!
86  x = w = v = bracket.b.x = getParameters()[0].getValue();
87  }
88  else
89  {
90  x = w = v = bracket.b.x;
92  fw = fv = fx = getFunction()->f(getParameters());
93  }
94 }
95 
96 /******************************************************************************/
97 
98 void BrentOneDimension::setInitialInterval(double inf, double sup)
99 {
100  if (sup > inf)
101  {
102  _xinf = inf; _xsup = sup;
103  }
104  else
105  {
106  _xinf = sup; _xsup = inf;
107  }
108  isInitialIntervalSet_ = true;
109 }
110 
111 /******************************************************************************/
112 
114 {
115  xm = 0.5 * (a + b);
116  tol2 = 2.0 * (tol1 = getStopCondition()->getTolerance() * NumTools::abs(x) + ZEPS);
117 
118  if (NumTools::abs(e) > tol1)
119  {
120  r = (x - w) * (fx - fv);
121  q = (x - v) * (fx - fw);
122  p = (x - v) * q - (x - w) * r;
123  q = 2.0 * (q - r);
124  if (q > 0.0)
125  p = -p;
126  q = NumTools::abs(q);
127  etemp = e;
128  e = d;
129  if (NumTools::abs(p) >= NumTools::abs(0.5 * q * etemp) || p <= q * (a - x) || p >= q * (b - x))
130  d = NumConstants::GOLDEN_RATIO_C() * (e = (x >= xm ? a - x : b - x));
131  else
132  {
133  d = p / q;
134  u = x + d;
135  if (u - a < tol2 || b - u < tol2)
136  d = NumTools::sign(tol1, xm - x);
137  }
138  }
139  else
140  {
141  d = NumConstants::GOLDEN_RATIO_C() * (e = (x >= xm ? a - x : b - x));
142  }
143  u = (NumTools::abs(d) >= tol1 ? x + d : x + NumTools::sign(tol1, d));
144 
145  // Function evaluaton:
147  pl[0].setValue(u);
148 
149  fu = getFunction()->f(pl);
150 
151  if (fu <= fx)
152  {
153  if (u >= x)
154  a = x;
155  else
156  b = x;
157  NumTools::shift(v, w, x, u);
158  NumTools::shift(fv, fw, fx, fu);
159  }
160  else
161  {
162  if (u < x)
163  a = u;
164  else
165  b = u;
166  if (fu <= fw || w == x)
167  {
168  v = w;
169  w = u;
170  fv = fw;
171  fw = fu;
172  }
173  else if (fu <= fv || v == x || v == w)
174  {
175  v = u;
176  fv = fu;
177  }
178  }
179 
180  // Store results for this step:
182  return fx;
183 }
184 
185 /******************************************************************************/
186 
188 {
190  throw Exception("BrentOneDimension::optimize. Initial interval not set: call the 'setInitialInterval' method first!");
192  // Apply parameters and evaluate function at minimum point:
194  return currentValue_;
195 }
196 
197 /******************************************************************************/
double optimize() override
Basic implementation.
static T sign(T a)
Get the sign of a value.
Definition: NumTools.h:42
std::shared_ptr< OptimizationStopCondition > getStopCondition() override
Get the stop condition of the optimization algorithm.
size_t size() const
Definition: ParameterList.h:56
void setDefaultStopCondition_(std::shared_ptr< OptimizationStopCondition > osc)
const ParameterList & getParameters() const override
static double GOLDEN_RATIO_C()
Definition: NumConstants.h:32
The parameter list object.
Definition: ParameterList.h:27
static Bracket bracketMinimum(double a, double b, FunctionInterface &function, ParameterList parameters)
Bracket a minimum.
virtual void setValue(double value)
Set the value of this parameter.
Definition: Parameter.cpp:55
unsigned int getVerbose() const override
Get the verbose level.
BrentOneDimension(std::shared_ptr< FunctionInterface > function=nullptr)
Parameter & getParameter_(size_t i)
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. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
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.
static Bracket inwardBracketMinimum(double a, double b, FunctionInterface &function, ParameterList parameters, unsigned int intervalsNum=10)
Bracket a minimum by a search within the parameter&#39;s bounds.
const FunctionInterface & function() const override
Get the current function being optimized.
double doStep()
This function is called by the step() method and contains all calculations.
void setInitialInterval(double inf, double sup)
Set intial search interval.
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
std::shared_ptr< const FunctionInterface > getFunction() const override
Get the current function being optimized.
void setMaximumNumberOfEvaluations(unsigned int max) override
Set the maximum number of function evaluation to perform during optimization.
std::shared_ptr< OptimizationStopCondition > getDefaultStopCondition() override
Get the default stop condition of the optimization algorithm.
static void shift(T &a, T &b, T c)
Definition: NumTools.h:112
void printMessage(const std::string &message)
Give a message to print to the message handler.
void setStopCondition(std::shared_ptr< OptimizationStopCondition > stopCondition) override
Set the stop condition of the optimization algorithm.
static T abs(T a)
Get the magnitude of a value.
Definition: NumTools.h:31