bpp-core3  3.0.0
TwoPointsNumericalDerivative.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
6 
7 using namespace bpp;
8 using namespace std;
9 
11 {
12  if (computeD1_ && variables_.size() > 0)
13  {
14  if (function1_)
15  function1_->enableFirstOrderDerivatives(false);
16  if (function2_)
17  function2_->enableSecondOrderDerivatives(false);
18  function_->setParameters(parameters);
19  f1_ = function_->getValue();
20  if ((abs(f1_) >= NumConstants::VERY_BIG()) || std::isnan(f1_))
21  {
22  for (size_t i = 0; i < variables_.size(); ++i)
23  {
24  der1_[i] = log(-1);
25  der2_[i] = log(-1);
26  }
27  return;
28  }
29 
30  string lastVar;
31  bool functionChanged = false;
32  ParameterList p;
33  bool start = true;
34  for (size_t i = 0; i < variables_.size(); ++i)
35  {
36  string var = variables_[i];
37  if (!parameters.hasParameter(var))
38  continue;
39  if (!start)
40  {
41  vector<string> vars(2);
42  vars[0] = var;
43  vars[1] = lastVar;
44  p = parameters.createSubList(vars);
45  }
46  else
47  {
48  p = parameters.createSubList(var);
49  start = false;
50  }
51  lastVar = var;
52  functionChanged = true;
53  double value = function_->getParameterValue(var);
54  double h = -(1. + std::abs(value)) * h_;
55  if (abs(h) < p[0].getPrecision())
56  h = h < 0 ? -p[0].getPrecision() : p[0].getPrecision();
57  double hf2(0);
58  unsigned int nbtry = 0;
59 
60  // Compute one other point:
61  while (hf2 == 0)
62  {
63  try
64  {
65  p[0].setValue(value + h);
66  function_->setParameters(p); // also reset previous parameter...
67 
68  p = p.createSubList(0);
69  f2_ = function_->getValue();
70  if ((abs(f2_) >= NumConstants::VERY_BIG()) || std::isnan(f2_))
71  throw ConstraintException("f2_ too large", &p[0], f2_);
72  else
73  hf2 = h;
74  }
75  catch (ConstraintException& ce)
76  {
77  if (++nbtry == 10) // no possibility to compute derivatives
78  break;
79  else if (h < 0)
80  h = -h; // try on the right
81  else
82  h /= -2; // try again on the left with smaller interval
83  }
84  }
85 
86  der1_[i] = (f2_ - f1_) / h;
87  }
88  // Reset last parameter and compute analytical derivatives if any:
89  if (function1_)
90  function1_->enableFirstOrderDerivatives(computeD1_);
91  if (functionChanged)
92  function_->setParameters(parameters.createSubList(lastVar));
93  }
94  else
95  {
96  // Reset initial value and compute analytical derivatives if any.
97  if (function1_)
98  function1_->enableFirstOrderDerivatives(computeD1_);
99  if (function2_)
100  function2_->enableSecondOrderDerivatives(computeD2_);
101  // Just in case derivatives are not computed:
102  function_->setParameters(parameters);
103  f1_ = function_->getValue();
104  }
105 }
virtual ParameterList createSubList(const std::vector< std::string > &names) const
Get given parameters as a sublist.
virtual double getParameterValue(const std::string &name) const
Get the value of the parameter with name name.
STL namespace.
The parameter list object.
Definition: ParameterList.h:27
virtual bool hasParameter(const std::string &name) const
void updateDerivatives(const ParameterList &parameters) override
Compute derivatives.
static double VERY_BIG()
Definition: NumConstants.h:48
virtual void setParameters(const ParameterList &params)
Update the parameters from params.
Exception thrown when a value do not match a given constraint.