bpp-core3  3.0.0
NewtonOneDimension.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 "../NumTools.h"
7 #include "NewtonOneDimension.h"
8 
9 using namespace bpp;
10 
11 /******************************************************************************/
12 
13 NewtonOneDimension::NewtonOneDimension(std::shared_ptr<SecondOrderDerivable> function) :
14  AbstractOptimizer(function),
15  _param(),
16  _maxCorrection(10)
17 {
18  setDefaultStopCondition_(make_shared<FunctionStopCondition>(this));
20  nbEvalMax_ = 10000;
21 }
22 
23 /******************************************************************************/
24 
26 {
27  // Set the initial value (no use here! Use setInitialValues() instead).
28  if (params.size() != 1)
29  throw Exception("NewtonOneDimension::init(). This optimizer only deals with one parameter.");
30  _param = params[0].getName();
32  getStopCondition()->init();
33 }
34 
35 /******************************************************************************/
36 
38 {
39  double movement;
40  ParameterList newPoint = getParameters();
41  ParameterList bckPoint = getFunction()->getParameters();
42  double newValue;
43  double firstOrderDerivative = firstOrderDerivableFunction().getFirstOrderDerivative(_param);
44  double secondOrderDerivative = secondOrderDerivableFunction().getSecondOrderDerivative(_param);
45  if (secondOrderDerivative <= 0)
46  {
47  printMessage("!!! Second order derivative is negative (" + TextTools::toString(getParameters()[0].getValue()) + "). No move performed.");
48  // movements[i] = 0; // We want to reach a minimum, not a maximum!
49  // My personnal improvement:
50  movement = -firstOrderDerivative / secondOrderDerivative;
51  }
52  else
53  movement = firstOrderDerivative / secondOrderDerivative;
54  if (std::isnan(movement))
55  {
56  printMessage("!!! Non derivable point. No move performed. (f=" + TextTools::toString(currentValue_) + ", d1=" + TextTools::toString(firstOrderDerivative) + ", d2=" + TextTools::toString(secondOrderDerivative) + ").");
57  movement = 0; // Either first or second order derivative is infinity. This may happen when the function == inf at this point.
58  }
59  newPoint[0].setValue(getParameters()[0].getValue() - movement);
60  newValue = getFunction()->f(newPoint);
61 
62  // Check newValue:
63  unsigned int count = 0;
64  while (newValue > currentValue_)
65  {
66  // Restore previous point (all parameters in case of global constraint):
67  getFunction()->setParameters(bckPoint);
68 
69  count++;
70  if (count >= _maxCorrection)
71  {
72  printMessage("!!! Felsenstein-Churchill correction applied too much time. Stopping here. Convergence probably not reached.");
73  tolIsReached_ = true;
74  return currentValue_;
75  // throw Exception("NewtonOneDimension::step(). Felsenstein-Churchill correction applied more than 10000 times.");
76  }
77  printMessage("!!! Function at new point is greater than at current point: " + TextTools::toString(newValue) + ">" + TextTools::toString(currentValue_) + ". Applying Felsenstein-Churchill correction, value = " + TextTools::toString(newPoint[0].getValue()));
78  movement = movement / 2;
79  newPoint[0].setValue(getParameters()[0].getValue() - movement);
80  newValue = getFunction()->f(newPoint);
81  }
82 
83  getParameters_() = newPoint; // Function as been set to newPoint by the call of f(newPoint).
84  return newValue;
85 }
86 
87 /******************************************************************************/
void doInit(const ParameterList &params)
This function is called by the init() method and contains all calculations.
std::shared_ptr< OptimizationStopCondition > getStopCondition() override
Get the stop condition of the optimization algorithm.
std::size_t count(const std::string &s, const std::string &pattern)
Count the occurences of a given pattern in a string.
Definition: TextTools.cpp:388
size_t size() const
Definition: ParameterList.h:56
void setDefaultStopCondition_(std::shared_ptr< OptimizationStopCondition > osc)
ParameterList & getParameters_()
const ParameterList & getParameters() const override
The parameter list object.
Definition: ParameterList.h:27
bool tolIsReached_
Tell if the tolerance level has been reached.
virtual double getFirstOrderDerivative(const std::string &variable) const =0
Get the derivative of the function at the current point.
virtual double getSecondOrderDerivative(const std::string &variable) const =0
Get the second order derivative of the function at the current point.
NewtonOneDimension(std::shared_ptr< SecondOrderDerivable > function=nullptr)
const SecondOrderDerivable & secondOrderDerivableFunction() const
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
double doStep()
This function is called by the step() method and contains all calculations.
unsigned int nbEvalMax_
The maximum number of function evaluations allowed.
Partial implementation of the Optimizer interface.
double currentValue_
The current value of the function.
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.
std::shared_ptr< OptimizationStopCondition > getDefaultStopCondition() override
Get the default stop condition of the optimization algorithm.
const FirstOrderDerivable & firstOrderDerivableFunction() const
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.