bpp-core3  3.0.0
AbstractOptimizer.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "../../App/ApplicationTools.h"
6 #include "../../Text/TextTools.h"
7 #include "../AutoParameter.h"
8 #include "AbstractOptimizer.h"
9 
10 // From the STL:
11 #include <iomanip>
12 #include <time.h>
13 
14 using namespace std;
15 using namespace bpp;
16 
17 /******************************************************************************/
18 
19 AbstractOptimizer::AbstractOptimizer(std::shared_ptr<FunctionInterface> function) :
20  function_(function),
21  parameters_(),
22  messageHandler_(ApplicationTools::message),
23  profiler_(ApplicationTools::message),
24  constraintPolicy_(AutoParameter::CONSTRAINTS_KEEP),
25  stopCondition_(0), defaultStopCondition_(0),
26  verbose_(true), isInitialized_(false), startTime_(), listeners_(),
27  updateParameters_(false), stepChar_("*"),
28  nbEvalMax_(1000000), nbEval_(0),
29  currentValue_(0), tolIsReached_(false)
30 {}
31 
32 /******************************************************************************/
33 
35  function_(opt.function_),
38  profiler_(opt.profiler_),
41  verbose_(opt.verbose_),
44  listeners_(), // We do not copy listeners!
46  stepChar_(opt.stepChar_),
48  nbEval_(opt.nbEval_),
51 {
52  if (opt.stopCondition_)
53  {
54  stopCondition_ = shared_ptr<OptimizationStopCondition>(opt.stopCondition_->clone());
55  stopCondition_->setOptimizer(this);
56  }
57  else
58  stopCondition_ = nullptr;
59 
60  if (opt.defaultStopCondition_)
61  {
62  defaultStopCondition_ = shared_ptr<OptimizationStopCondition>(opt.defaultStopCondition_->clone());
63  defaultStopCondition_->setOptimizer(this);
64  }
65  else
66  defaultStopCondition_ = nullptr;
67  // In case of AutoParameter instances, we must actualize the pointers toward _messageHandler:
68  //
69  if (isInitialized_)
70  {
72  autoParameter();
75  }
76 }
77 
78 /******************************************************************************/
79 
81 {
82  function_ = opt.function_;
85  profiler_ = opt.profiler_;
88  if (opt.stopCondition_)
89  {
90  stopCondition_ = shared_ptr<OptimizationStopCondition>(opt.stopCondition_->clone());
91  stopCondition_->setOptimizer(this);
92  }
93  else
94  stopCondition_ = nullptr;
95 
96  if (opt.defaultStopCondition_)
97  {
98  defaultStopCondition_ = shared_ptr<OptimizationStopCondition>(opt.defaultStopCondition_->clone());
99  defaultStopCondition_->setOptimizer(this);
100  }
101  else
102  defaultStopCondition_ = nullptr;
103 
104  nbEvalMax_ = opt.nbEvalMax_;
105  nbEval_ = opt.nbEval_;
106  verbose_ = opt.verbose_;
108  // In case of AutoParameter instances, we must actualize the pointers toward messageHandler_:
109  if (isInitialized_)
110  {
112  autoParameter();
115  }
116  startTime_ = opt.startTime_;
117  listeners_.resize(0); // Reset listener list, do not copy it!
119  stepChar_ = opt.stepChar_;
120  return *this;
121 }
122 
123 /******************************************************************************/
124 
126 {
127  if (!function_)
128  throw Exception("AbstractOptimizer::init. Optimizer currently has no function.");
129  // We do this in order to keep original constraints:
130  parameters_ = params;
131  // More secure, but too slow:
132  // parameters_ = function_->getParameters().createSubList(params.getParameterNames());
133  // parameters_.matchParametersValues(params);
135  autoParameter();
138  doInit(params);
139  nbEval_ = 0;
140  tolIsReached_ = false;
141  isInitialized_ = true;
142  time(&startTime_);
143  currentValue_ = function_->getValue();
144 
145  profile("Step\t");
146  for (unsigned int i = 0; i < parameters_.size(); i++)
147  {
148  profile(parameters_[i].getName() + "\t");
149  }
150  profileln("Function\tTime");
151 
152  // Parameters must be assigned by doInit:
153 
155 
156  // Initialize the StopCondition:
157  stopCondition_->init();
159 }
160 
161 /******************************************************************************/
162 
164 {
165  currentValue_ = doStep();
169  {
170  if (!updateParameters_)
171  parameters_.matchParametersValues(function_->getParameters());
172  // else already done!
173  // _currentValue = function_->getValue();
174  // Often useless, but avoid some bizare behaviour in particular cases:
176  }
177  tolIsReached_ = tolIsReached_ || stopCondition_->isToleranceReached();
178  return currentValue_;
179 }
180 
181 /**************************************************************************/
182 
184 {
185  if (!isInitialized_)
186  throw Exception("AbstractOptimizer::optimize. Optimizer not initialized: call the 'init' method first!");
187  tolIsReached_ = false;
188  for (nbEval_ = 1; nbEval_ < nbEvalMax_ && !tolIsReached_; nbEval_++)
189  {
190  if (verbose_)
192  step();
193  }
194  return currentValue_;
195 }
196 
197 /******************************************************************************/
198 
200 {
201  if (profiler_)
202  *profiler_ << v;
203 }
204 
205 /******************************************************************************/
206 
208 {
209  if (profiler_)
210  (*profiler_ << v).endLine();
211 }
212 
213 /******************************************************************************/
214 
215 void AbstractOptimizer::profile(unsigned int v)
216 {
217  if (profiler_)
218  *profiler_ << v;
219 }
220 /******************************************************************************/
221 
222 void AbstractOptimizer::profileln(unsigned int v)
223 {
224  if (profiler_)
225  (*profiler_ << v).endLine();
226 }
227 
228 /******************************************************************************/
229 
230 void AbstractOptimizer::profile(const std::string& s)
231 {
232  if (profiler_)
233  *profiler_ << s;
234 }
235 
236 /******************************************************************************/
237 
238 void AbstractOptimizer::profileln(const std::string& s)
239 {
240  if (profiler_)
241  (*profiler_ << s).endLine();
242 }
243 
244 /******************************************************************************/
245 
246 void AbstractOptimizer::printPoint(const ParameterList& params, double value)
247 {
248  size_t ndim = params.size();
249  profile(nbEval_);
250  profile("\t");
251  for (size_t j = 0; j < ndim; j++)
252  {
253  profile(TextTools::toString(params[j].getValue()));
254  profile("\t");
255  }
256  profile(value);
257  profile("\t");
258  time_t seconds;
259  time(&seconds);
260  profileln(difftime(seconds, startTime_));
261 }
262 
263 /******************************************************************************/
264 
265 void AbstractOptimizer::printMessage(const std::string& message)
266 {
267  if (messageHandler_)
268  (*messageHandler_ << message).endLine();
269 }
270 
271 /******************************************************************************/
272 
274 {
275  for (size_t i = 0; i < parameters_.size(); ++i)
276  {
277  AutoParameter ap(parameters_[i]);
279  parameters_.setParameter(i, ap);
280  }
281 }
282 
283 /******************************************************************************/
284 
286 {
287  for (size_t i = 0; i < parameters_.size(); ++i)
288  {
289  parameters_[i].removeConstraint();
290  }
291 }
292 
293 /******************************************************************************/
294 
296 {
297  for (auto listener : listeners_)
298  {
299  listener->optimizationInitializationPerformed(event);
300  }
301 }
302 
303 /******************************************************************************/
304 
306 {
307  for (auto listener : listeners_)
308  {
309  listener->optimizationStepPerformed(event);
310  }
311 }
312 
313 /******************************************************************************/
314 
316 {
317  for (auto listener : listeners_)
318  {
319  if (listener->listenerModifiesParameters())
320  return true;
321  }
322  return false;
323 }
324 
325 /******************************************************************************/
bool isInitialized_
Check if the optimizer have been feeded with initial parameters values.
static std::string CONSTRAINTS_IGNORE
Definition: AutoParameter.h:99
AbstractOptimizer & operator=(const AbstractOptimizer &opt)
double step() override
Basic implementation.
virtual void doInit(const ParameterList &params)=0
This function is called by the init() method and contains all calculations.
double optimize() override
Basic implementation.
virtual bool matchParametersValues(const ParameterList &params, std::vector< size_t > *updatedParameters=0)
Update the parameters from params.
void profileln(double v)
Print to the profile if there is one and end line.
std::shared_ptr< FunctionInterface > function_
The function to optimize.
size_t size() const
Definition: ParameterList.h:56
STL namespace.
void ignoreConstraints()
Remove the constraints of all the arguments.
The parameter list object.
Definition: ParameterList.h:27
This class provides some common tools for developping applications.
bool tolIsReached_
Tell if the tolerance level has been reached.
virtual void setMessageHandler(std::shared_ptr< OutputStream > mh)
Set the message handler for this AutoParameter.
Definition: AutoParameter.h:95
std::shared_ptr< OutputStream > messageHandler_
The message handler.
std::shared_ptr< OptimizationStopCondition > stopCondition_
The stoping condition to use while optimizing.
bool listenerModifiesParameters() const
unsigned int verbose_
State of the verbose mode: > 0 = enabled.
The AutoParameter class.
Definition: AutoParameter.h:23
virtual void setParameter(size_t index, const Parameter &param)
Change given parameter.
void printPoint(const ParameterList &params, double value)
Print parameters and corresponding function evaluation to profiler.
std::shared_ptr< OutputStream > profiler_
The profiler.
An event object which indicates that an optimization event occured.
Definition: Optimizer.h:22
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
static std::string CONSTRAINTS_AUTO
Definition: AutoParameter.h:98
unsigned int nbEvalMax_
The maximum number of function evaluations allowed.
std::vector< std::shared_ptr< OptimizationListener > > listeners_
unsigned int nbEval_
The current number of function evaluations achieved.
Partial implementation of the Optimizer interface.
void fireOptimizationInitializationPerformed(const OptimizationEvent &event)
Notify all listeners that optimizer initialization was performed.
double currentValue_
The current value of the function.
static void displayUnlimitedGauge(size_t iter, const std::string &mes="")
Display a gauge for unefined amount of iterations.
std::string constraintPolicy_
The constraint policy.
std::shared_ptr< OptimizationStopCondition > defaultStopCondition_
The default stoping condition to use while optimizing.
virtual double doStep()=0
This function is called by the step() method and contains all calculations.
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
void profile(double v)
Print to the profile if there is one.
void init(const ParameterList &params) override
Basic implementation.
void fireOptimizationStepPerformed(const OptimizationEvent &event)
Notify all listeners that an optimization step was performed.
void printMessage(const std::string &message)
Give a message to print to the message handler.
AbstractOptimizer(std::shared_ptr< FunctionInterface > function=nullptr)
ParameterList parameters_
The parameters that will be optimized.
void autoParameter()
Build a list of AutoParameter instead of Parameter.