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