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