bpp-core3  3.0.0
ThreePointsNumericalDerivative.cpp
Go to the documentation of this file.
1 //
2 // File: ThreePointsNumericalDerivative.cpp
3 // Authors:
4 // Julien Dutheil
5 // Created: 2006-08-17 15:00:00
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for numerical calculus.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 
43 
44 using namespace bpp;
45 using namespace std;
46 
48 {
49  if (computeD1_ && variables_.size() > 0)
50  {
51  if (function1_)
52  function1_->enableFirstOrderDerivatives(false);
53  if (function2_)
54  function2_->enableSecondOrderDerivatives(false);
55  function_->setParameters(parameters);
56  f2_ = function_->getValue();
57  if ((abs(f2_) >= NumConstants::VERY_BIG()) || std::isnan(f2_))
58  {
59  for (size_t i = 0; i < variables_.size(); ++i)
60  {
61  der1_[i] = log(-1);
62  der2_[i] = log(-1);
63  }
64  return;
65  }
66 
67  string lastVar;
68  bool functionChanged = false;
69  ParameterList p;
70  bool start = true;
71  for (size_t i = 0; i < variables_.size(); ++i)
72  {
73  string var = variables_[i];
74  if (!parameters.hasParameter(var))
75  continue;
76  if (!start)
77  {
78  vector<string> vars(2);
79  vars[0] = var;
80  vars[1] = lastVar;
81  p = parameters.createSubList(vars);
82  }
83  else
84  {
85  p = parameters.createSubList(var);
86  start = false;
87  }
88  lastVar = var;
89  functionChanged = true;
90  double value = function_->getParameterValue(var);
91  double h = -(1. + std::abs(value)) * h_;
92  if (abs(h) < p[0].getPrecision())
93  h = h < 0 ? -p[0].getPrecision() : p[0].getPrecision();
94  double hf1(0), hf3(0);
95  unsigned int nbtry = 0;
96 
97  // Compute f1_
98  while (hf1 == 0)
99  {
100  try
101  {
102  p[0].setValue(value + h);
103  function_->setParameters(p); // also reset previous parameter...
104 
105  p = p.createSubList(0);
106  f1_ = function_->getValue();
107  if ((abs(f1_) >= NumConstants::VERY_BIG()) || std::isnan(f1_))
108  throw ConstraintException("f1_ too large", &p[0], f1_);
109  else
110  hf1 = h;
111  }
112  catch (ConstraintException& ce)
113  {
114  if (++nbtry == 10) // no possibility to compute derivatives
115  break;
116  else if (h < 0)
117  h = -h; // try on the right
118  else
119  h /= -2; // try again on the left with smaller interval
120  }
121  }
122 
123  if (hf1 != 0)
124  {
125  // Compute f3_
126  if (h < 0)
127  h = -h; // on the right
128  else
129  h /= 2; // on the left with smaller interval
130 
131  nbtry = 0;
132  while (hf3 == 0)
133  {
134  try
135  {
136  p[0].setValue(value + h);
137  function_->setParameters(p); // also reset previous parameter...
138 
139  p = p.createSubList(0);
140  f3_ = function_->getValue();
141  if ((abs(f3_) >= NumConstants::VERY_BIG()) || std::isnan(f3_))
142  throw ConstraintException("f3_ too large", &p[0], f3_);
143  else
144  hf3 = h;
145  }
146  catch (ConstraintException& ce)
147  {
148  if (++nbtry == 10) // no possibility to compute derivatives
149  break;
150  else if (h < 0)
151  h = -h; // try on the right
152  else
153  h /= -2; // try again on the left with smaller interval
154  }
155  }
156  }
157 
158  if (hf3 == 0)
159  {
160  der1_[i] = log(-1);
161  der2_[i] = log(-1);
162  }
163  else
164  {
165  der1_[i] = (f1_ - f3_) / (hf1 - hf3);
166  der2_[i] = ((f1_ - f2_) / hf1 - (f3_ - f2_) / hf3) * 2 / (hf1 - hf3);
167  }
168  }
169 
170 
171  if (computeCrossD2_)
172  {
173  string lastVar1, lastVar2;
174  for (unsigned int i = 0; i < variables_.size(); i++)
175  {
176  string var1 = variables_[i];
177  if (!parameters.hasParameter(var1))
178  continue;
179  for (unsigned int j = 0; j < variables_.size(); j++)
180  {
181  if (j == i)
182  {
183  crossDer2_(i, j) = der2_[i];
184  continue;
185  }
186  string var2 = variables_[j];
187  if (!parameters.hasParameter(var2))
188  continue;
189 
190  vector<string> vars(2);
191  vars[0] = var1;
192  vars[1] = var2;
193  if (i > 0 && j > 0)
194  {
195  if (lastVar1 != var1 && lastVar1 != var2)
196  vars.push_back(lastVar1);
197  if (lastVar2 != var1 && lastVar2 != var2)
198  vars.push_back(lastVar2);
199  }
200  p = parameters.createSubList(vars);
201 
202  double value1 = function_->getParameterValue(var1);
203  double value2 = function_->getParameterValue(var2);
204  double h1 = (1. + std::abs(value1)) * h_;
205  double h2 = (1. + std::abs(value2)) * h_;
206 
207  // Compute 4 additional points:
208  try
209  {
210  p[0].setValue(value1 - h1);
211  p[1].setValue(value2 - h2);
212  function_->setParameters(p); // also reset previous parameter...
213  vector<size_t> tmp(2);
214  tmp[0] = 0;
215  tmp[1] = 1;
216  p = p.createSubList(tmp); // removed the previous parameters.
217  f11_ = function_->getValue();
218 
219  p[1].setValue(value2 + h2);
220  function_->setParameters(p.createSubList(1));
221  f12_ = function_->getValue();
222 
223  p[0].setValue(value1 + h1);
224  function_->setParameters(p.createSubList(0));
225  f22_ = function_->getValue();
226 
227  p[1].setValue(value2 - h2);
228  function_->setParameters(p.createSubList(1));
229  f21_ = function_->getValue();
230 
231  crossDer2_(i, j) = ((f22_ - f21_) - (f12_ - f11_)) / (4 * h1 * h2);
232  }
233  catch (ConstraintException& ce)
234  {
235  throw Exception("ThreePointsNumericalDerivative::setParameters. Could not compute cross derivatives at limit.");
236  }
237 
238  lastVar1 = var1;
239  lastVar2 = var2;
240  }
241  }
242  }
243 
244  // Reset last parameter and compute analytical derivatives if any.
245  if (function1_)
246  function1_->enableFirstOrderDerivatives(computeD1_);
247  if (function2_)
248  function2_->enableSecondOrderDerivatives(computeD2_);
249  if (functionChanged)
250  function_->setParameters(parameters.createSubList(lastVar));
251  }
252  else
253  {
254  // Reset initial value and compute analytical derivatives if any.
255  if (function1_)
256  function1_->enableFirstOrderDerivatives(computeD1_);
257  if (function2_)
258  function2_->enableSecondOrderDerivatives(computeD2_);
259  function_->setParameters(parameters);
260  // Just in case derivatives are not computed:
261  f2_ = function_->getValue();
262  }
263 }
Exception thrown when a value do not match a given constraint.
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Definition: Exceptions.h:59
static double VERY_BIG()
Definition: NumConstants.h:84
The parameter list object.
Definition: ParameterList.h:65
virtual bool hasParameter(const std::string &name) const
virtual void setParameters(const ParameterList &params)
Update the parameters from params.
virtual double getParameterValue(const std::string &name) const
Get the value of the parameter with name name.
virtual ParameterList createSubList(const std::vector< std::string > &names) const
Get given parameters as a sublist.
void updateDerivatives(const ParameterList parameters)
Compute derivatives.