bpp-core3  3.0.0
BfgsMultiDimensions.cpp
Go to the documentation of this file.
1 //
2 // File: BfgsMultiDimensions.cpp
3 // Authors:
4 // Laurent Guéguen
5 // Created: 2010-12-16 13:49:00
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 19, 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 
42 #include "BfgsMultiDimensions.h"
44 
45 using namespace bpp;
46 
47 /******************************************************************************/
48 
50  AbstractOptimizer(function),
51  // gtol_(gtol),
52  slope_(0),
53  Up_(),
54  Lo_(),
55  p_(),
56  gradient_(),
57  xi_(),
58  dg_(),
59  hdg_(),
60  hessian_(),
61  f1dim_(function)
62 {
66 }
67 
68 /******************************************************************************/
69 
71 {
72  size_t nbParams = params.size();
73  p_.resize(nbParams);
74  gradient_.resize(nbParams);
75  xi_.resize(nbParams);
76  dg_.resize(nbParams);
77  hdg_.resize(nbParams);
78  Up_.resize(nbParams);
79  Lo_.resize(nbParams);
80 
81  hessian_.resize(nbParams);
82  for (size_t i = 0; i < nbParams; i++)
83  {
84  hessian_[i].resize(nbParams);
85  }
86 
87  for (size_t i = 0; i < nbParams; i++)
88  {
89  std::shared_ptr<Constraint> cp = params[i].getConstraint();
90  if (!cp)
91  {
94  }
95  else
96  {
97  Up_[i] = cp->getAcceptedLimit(NumConstants::VERY_BIG()) - NumConstants::TINY();
98  Lo_[i] = cp->getAcceptedLimit(-NumConstants::VERY_BIG()) + NumConstants::TINY();
99  }
100  }
101 
103  getFunction_()->setParameters(params);
104 
106 
107  for (size_t i = 0; i < nbParams; i++)
108  {
109  p_[i] = getParameters()[i].getValue();
110 
111  for (unsigned int j = 0; j < nbParams; j++)
112  {
113  hessian_[i][j] = 0.0;
114  }
115  hessian_[i][i] = 1.0;
116  }
117 
118 
119  double sum = 0;
120  for (size_t i = 0; i < nbParams; i++)
121  {
122  sum += p_[i] * p_[i];
123  }
124 }
125 
126 /******************************************************************************/
127 
129 {
130  double f;
131  size_t n = getParameters().size();
132  // Loop over iterations.
133 
134  unsigned int i;
135 
136  for (i = 0; i < n; i++)
137  {
138  p_[i] = getParameters()[i].getValue();
139  }
140 
141  setDirection();
142 
145  getParameters_(), xi_,
146  gradient_,
147  // getStopCondition()->getTolerance(),
148  0, 0,
149  getVerbose() > 0 ? getVerbose() - 1 : 0);
151 
152  for (i = 0; i < n; i++)
153  {
154  xi_[i] = getParameters_()[i].getValue() - p_[i];
155  }
156 
157  f = getFunction()->f(getParameters());
158  if (f > currentValue_)
159  {
160  printMessage("!!! Function increase !!!");
161  printMessage("!!! Optimization might have failed. Try to reparametrize your function to remove constraints.");
162  tolIsReached_ = true;
163  return f;
164  }
165 
166  if (tolIsReached_)
167  {
168  return f;
169  }
170 
171  // double temp, test = 0.0;
172  // for (i = 0; i < n; i++)
173  // {
174  // temp = xi_[i];
175  // if (p_[i] > 1.0)
176  // temp /= p_[i];
177  // if (temp > test)
178  // test = temp;
179  // }
180 
181  // if (test < 1e-7)
182  // {
183  // tolIsReached_ = true;
184  // return f;
185  // }
186 
187  for (i = 0; i < n; i++)
188  {
189  dg_[i] = gradient_[i];
190  }
191 
193  // test = 0.0;
194 
195  // for (i = 0; i < n; i++)
196  // {
197  // temp = abs(gradient_[i]);
198  // if (abs(p_[i]) > 1.0)
199  // temp /= p_[i];
200  // if (temp > test)
201  // test = temp;
202  // }
203 
204  // if (f > 1.0)
205  // test /= f;
206 
207  // if (test < gtol_)
208  // {
209  // tolIsReached_ = true;
210  // return f;
211  // }
212 
213  for (i = 0; i < n; i++)
214  {
215  dg_[i] = gradient_[i] - dg_[i];
216  }
217 
218  for (i = 0; i < n; i++)
219  {
220  hdg_[i] = 0;
221  for (unsigned int j = 0; j < n; j++)
222  {
223  hdg_[i] += hessian_[i][j] * dg_[j];
224  }
225  }
226 
227  double fae(0), fac(0), sumdg(0), sumxi(0);
228 
229  for (i = 0; i < n; i++)
230  {
231  fac += dg_[i] * xi_[i];
232  fae += dg_[i] * hdg_[i];
233  sumdg += dg_[i] * dg_[i];
234  sumxi += xi_[i] * xi_[i];
235  }
236 
237  if (fac > sqrt(1e-7 * sumdg * sumxi))
238  {
239  fac = 1.0 / fac;
240  double fad = 1.0 / fae;
241  for (i = 0; i < n; i++)
242  {
243  dg_[i] = fac * xi_[i] - fad * hdg_[i];
244  }
245  for (i = 0; i < n; i++)
246  {
247  for (unsigned int j = i; j < n; j++)
248  {
249  hessian_[i][j] += fac * xi_[i] * xi_[j] - fad * hdg_[i] * hdg_[j] + fae * dg_[i] * dg_[j];
250  hessian_[j][i] = hessian_[i][j];
251  }
252  }
253  }
254 
255  return f;
256 }
257 
258 /******************************************************************************/
259 
260 void BfgsMultiDimensions::getGradient(std::vector<double>& gradient) const
261 {
262  for (unsigned int i = 0; i < gradient.size(); i++)
263  {
264  gradient[i] = getFunction()->getFirstOrderDerivative(getParameters()[i].getName());
265  }
266 }
267 
268 /******************************************************************************/
269 
271 {
272  size_t nbParams = getParameters().size();
273 
274  for (size_t i = 0; i < nbParams; i++)
275  {
276  xi_[i] = 0;
277  for (unsigned int j = 0; j < nbParams; j++)
278  {
279  xi_[i] -= hessian_[i][j] * gradient_[j];
280  }
281  }
282 
283  double v = 1, alpmax = 1;
284  for (size_t i = 0; i < nbParams; i++)
285  {
286  if ((xi_[i] > 0) && (p_[i] + NumConstants::TINY() * xi_[i] < Up_[i]))
287  v = (Up_[i] - p_[i]) / xi_[i];
288  else if ((xi_[i] < 0) && (p_[i] + NumConstants::TINY() * xi_[i] > Lo_[i]))
289  v = (Lo_[i] - p_[i]) / xi_[i];
290  if (v < alpmax)
291  alpmax = v;
292  }
293 
294  for (size_t i = 0; i < nbParams; i++)
295  {
296  if (p_[i] + NumConstants::TINY() * xi_[i] >= Up_[i])
297  xi_[i] = Up_[i] - p_[i];
298  else if (p_[i] + NumConstants::TINY() * xi_[i] <= Lo_[i])
299  xi_[i] = Lo_[i] - p_[i];
300  else
301  xi_[i] *= alpmax;
302  }
303 }
Partial implementation of the Optimizer interface.
void setOptimizationProgressCharacter(const std::string &c)
Set the character to be displayed during optimization.
void printMessage(const std::string &message)
Give a message to print to the message handler.
OptimizationStopCondition * getDefaultStopCondition()
Get the default stop condition of the optimization algorithm.
unsigned int nbEval_
The current number of function evaluations achieved.
const ParameterList & getParameters() const
void setStopCondition(const OptimizationStopCondition &stopCondition)
Set the stop condition of the optimization algorithm.
ParameterList & getParameters_()
double currentValue_
The current value of the function.
bool tolIsReached_
Tell if the tolerance level has been reached.
unsigned int getVerbose() const
Get the verbose level.
void setDefaultStopCondition_(OptimizationStopCondition *osc)
void getGradient(std::vector< double > &gradient) const
double doStep()
This function is called by the step() method and contains all calculations.
DerivableFirstOrder * getFunction_()
const DerivableFirstOrder * getFunction() const
Get the current function being optimized.
BfgsMultiDimensions(DerivableFirstOrder *function)
void doInit(const ParameterList &params)
This function is called by the init() method and contains all calculations.
This is the abstract class for first order derivable functions.
Definition: Functions.h:133
virtual double getFirstOrderDerivative(const std::string &variable) const =0
Get the derivative of the function at the current point.
virtual void enableFirstOrderDerivatives(bool yn)=0
Tell if derivatives must be computed.
Stop condition on function value.
virtual void setParameters(const ParameterList &parameters)=0
Set the point where the function must be computed.
virtual double f(const ParameterList &parameters)
Get the value of the function according to a given set of parameters.
Definition: Functions.h:117
static double TINY()
Definition: NumConstants.h:82
static double VERY_BIG()
Definition: NumConstants.h:84
static unsigned int lineSearch(DirectionFunction &f1dim, ParameterList &parameters, std::vector< double > &xi, std::vector< double > &gradient, OutputStream *profiler=0, OutputStream *messenger=0, unsigned int verbose=2)
Search a 'sufficiently low' value for a function in a given direction.
The parameter list object.
Definition: ParameterList.h:65
size_t size() const
Definition: ParameterList.h:92