bpp-core3  3.0.0
NumericalDerivative.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #ifndef BPP_NUMERIC_FUNCTION_NUMERICALDERIVATIVE_H
6 #define BPP_NUMERIC_FUNCTION_NUMERICALDERIVATIVE_H
7 
8 
9 #include "../Matrix/Matrix.h"
10 #include "Functions.h"
11 
12 // From the STL:
13 #include <map>
14 #include <vector>
15 #include <string>
16 
17 namespace bpp
18 {
26  public virtual SecondOrderDerivable
27 {
28 public:
36  virtual void setInterval(double h) = 0;
37 
41  virtual double getInterval() const = 0;
42 
48  virtual void setParametersToDerivate(const std::vector<std::string>& variables) = 0;
49 
50 };
51 
65  public virtual NumericalDerivativeInterface,
66  public FunctionWrapper
67 {
68 protected:
69  std::shared_ptr<FirstOrderDerivable> function1_;
70  std::shared_ptr<SecondOrderDerivable> function2_;
71  double h_;
72  std::vector<std::string> variables_;
73  mutable std::map<std::string, size_t> index_; // Store positions in array corresponding to variable names.
74  std::vector<double> der1_;
75  std::vector<double> der2_;
77  bool computeD1_, computeD2_, computeCrossD2_;
78 
79 public:
80  AbstractNumericalDerivative(std::shared_ptr<FunctionInterface> function) :
81  FunctionWrapper(function), function1_(0), function2_(0),
82  h_(0.0001), variables_(), index_(), der1_(), der2_(), crossDer2_(),
83  computeD1_(true), computeD2_(true), computeCrossD2_(false) {}
84 
85  AbstractNumericalDerivative(std::shared_ptr<FirstOrderDerivable> function) :
86  FunctionWrapper(function), function1_(function), function2_(0),
87  h_(0.0001), variables_(), index_(), der1_(), der2_(), crossDer2_(),
88  computeD1_(true), computeD2_(true), computeCrossD2_(false) {}
89 
90  AbstractNumericalDerivative(std::shared_ptr<SecondOrderDerivable> function) :
91  FunctionWrapper(function), function1_(function), function2_(function),
92  h_(0.0001), variables_(), index_(), der1_(), der2_(), crossDer2_(),
93  computeD1_(true), computeD2_(true), computeCrossD2_(false) {}
94 
96  FunctionWrapper(ad), function1_(ad.function1_), function2_(ad.function2_),
97  h_(ad.h_), variables_(ad.variables_), index_(ad.index_), der1_(ad.der1_), der2_(ad.der2_), crossDer2_(ad.crossDer2_),
98  computeD1_(ad.computeD1_), computeD2_(ad.computeD2_), computeCrossD2_(ad.computeCrossD2_) {}
99 
101  {
103  function1_ = ad.function1_;
104  function2_ = ad.function2_;
105  h_ = ad.h_;
106  variables_ = ad.variables_;
107  index_ = ad.index_;
108  der1_ = ad.der1_;
109  der2_ = ad.der2_;
110  crossDer2_ = ad.crossDer2_;
111  computeD1_ = ad.computeD1_;
112  computeD2_ = ad.computeD2_;
113  computeCrossD2_ = ad.computeCrossD2_;
114  return *this;
115  }
116 
118 
119  AbstractNumericalDerivative* clone() const override = 0;
120 
121 public:
122  void setInterval(double h) override { h_ = h; }
123 
124  double getInterval() const override { return h_; }
125 
126  void setParametersToDerivate(const std::vector<std::string>& variables) override
127  {
128  variables_ = variables;
129  index_.clear();
130  for (size_t i = 0; i < variables_.size(); i++)
131  {
132  index_[variables_[i]] = i;
133  }
134  der1_.resize(variables_.size());
135  der2_.resize(variables_.size());
136  crossDer2_.resize(variables_.size(), variables_.size());
137  }
138 
144  void enableFirstOrderDerivatives(bool yn) override { computeD1_ = yn; }
145  bool enableFirstOrderDerivatives() const override { return computeD1_; }
146 
147  double getFirstOrderDerivative(const std::string& variable) const override
148  {
149  std::map<std::string, size_t>::iterator it = index_.find(variable);
150  if (computeD1_ && it != index_.end())
151  return der1_[it->second];
152 
153  if (function1_)
154  return function1_->getFirstOrderDerivative(variable);
155 
156  throw Exception("First order derivative not computed for variable " + variable + ".");
157  }
165  void enableSecondOrderDerivatives(bool yn) override { computeD2_ = yn; }
166  bool enableSecondOrderDerivatives() const override { return computeD2_; }
167 
168  double getSecondOrderDerivative(const std::string& variable) const override
169  {
170  std::map<std::string, size_t>::iterator it = index_.find(variable);
171  if (computeD2_ && it != index_.end())
172  return der2_[it->second];
173 
174  if (function2_)
175  return function2_->getSecondOrderDerivative(variable);
176 
177  throw Exception("Second order derivative not computed for variable " + variable + ".");
178  }
179 
180  double getSecondOrderDerivative(const std::string& variable1, const std::string& variable2) const override
181  {
182  std::map<std::string, size_t>::iterator it1 = index_.find(variable1);
183  std::map<std::string, size_t>::iterator it2 = index_.find(variable2);
184  if (computeCrossD2_ && it1 != index_.end() && it2 != index_.end()) return crossDer2_(it1->second, it2->second);
185 
186  if (function2_)
187  return function2_->getSecondOrderDerivative(variable1, variable2);
188 
189  throw Exception("Cross second order derivative not computed for variables " + variable1 + " and " + variable2 + ".");
190  }
191 
199  double f(const ParameterList& parameters) override
200  {
201  setParameters(parameters);
202  return getValue();
203  }
204  void setParameters(const ParameterList& parameters) override
205  {
206  function_->setParameters(parameters);
207  updateDerivatives(parameters);
208  }
209  void setAllParametersValues(const ParameterList& parameters) override
210  {
211  function_->setAllParametersValues(parameters);
212  updateDerivatives(parameters);
213  }
214 
215  void setParameterValue(const std::string& name, double value) override
216  {
217  function_->setParameterValue(name, value);
218  updateDerivatives(function_->getParameters().createSubList(name));
219  }
220 
221  void setParametersValues(const ParameterList& parameters) override
222  {
223  function_->setParametersValues(parameters);
224  updateDerivatives(parameters);
225  }
226 
227  bool matchParametersValues(const ParameterList& parameters) override
228  {
229  bool test = function_->matchParametersValues(parameters);
230  updateDerivatives(parameters);
231  return test;
232  }
235  void enableSecondOrderCrossDerivatives(bool yn) { computeCrossD2_ = yn; }
236  bool enableSecondOrderCrossDerivatives() const { return computeCrossD2_; }
237 
238 protected:
245  virtual void updateDerivatives(const ParameterList& parameters) = 0;
246 };
247 } // end of namespace bpp.
248 #endif // BPP_NUMERIC_FUNCTION_NUMERICALDERIVATIVE_H
virtual void setParametersToDerivate(const std::vector< std::string > &variables)=0
Set the list of parameters to derivate numerically.
double getSecondOrderDerivative(const std::string &variable) const override
Get the second order derivative of the function at the current point.
void setParameterValue(const std::string &name, double value) override
Set the value of parameter with name name to be equal to value.
bool enableFirstOrderDerivatives() const override
Tell if derivatives must be computed.
virtual double getInterval() const =0
std::shared_ptr< SecondOrderDerivable > function2_
void setParametersToDerivate(const std::vector< std::string > &variables) override
Set the list of parameters to derivate numerically.
void enableSecondOrderDerivatives(bool yn) override
Tell if derivatives must be computed.
std::vector< std::string > variables_
bool matchParametersValues(const ParameterList &parameters) override
Update the parameters from parameters.
Numerical derivative function wrapper, partial implementation.
The parameter list object.
Definition: ParameterList.h:27
bool enableSecondOrderDerivatives() const override
Tell if derivatives must be computed.
AbstractNumericalDerivative(const AbstractNumericalDerivative &ad)
double getFirstOrderDerivative(const std::string &variable) const override
Get the derivative of the function at the current point.
AbstractNumericalDerivative(std::shared_ptr< SecondOrderDerivable > function)
double getInterval() const override
void enableFirstOrderDerivatives(bool yn) override
Tell if derivatives must be computed.
virtual void setParameters(const ParameterList &parameters)=0
Set the point where the function must be computed.
AbstractNumericalDerivative(std::shared_ptr< FunctionInterface > function)
void resize(size_t nRows, size_t nCols)
Resize the matrix.
Definition: Matrix.h:176
General class that wraps a function into another one. This class is meant to be derivated and just pr...
Definition: Functions.h:231
std::shared_ptr< FirstOrderDerivable > function1_
double getSecondOrderDerivative(const std::string &variable1, const std::string &variable2) const override
Get the value of the cross derivative of the function according to a given set of parameters...
AbstractNumericalDerivative(std::shared_ptr< FirstOrderDerivable > function)
void setParametersValues(const ParameterList &parameters) override
Update the parameters from parameters.
void setAllParametersValues(const ParameterList &parameters) override
Set the parameters values to be equals to those of parameters.
Numerical derivative function wrapper.
std::map< std::string, size_t > index_
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
void setInterval(double h) override
Set the interval value used in numerical approximation.
void setParameters(const ParameterList &parameters) override
Set the point where the function must be computed.
AbstractNumericalDerivative & operator=(const AbstractNumericalDerivative &ad)
SecondOrderDerivable * clone() const =0
Create a copy of this object and send a pointer to it.
FunctionWrapper & operator=(const FunctionWrapper &fw)
Definition: Functions.h:240
virtual void setInterval(double h)=0
Set the interval value used in numerical approximation.
This is the abstract class for second order derivable functions.
Definition: Functions.h:151
double f(const ParameterList &parameters) override
Get the value of the function according to a given set of parameters.
virtual double getValue() const =0
Get the value of the function at the current point.