ROOT   6.14/05 Reference Guide
BasicMinimizer.cxx
Go to the documentation of this file.
1 // @(#)root/mathmore:$Id$
2 // Author: L. Moneta Oct 2012
3
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10
11 // Implementation file for class BasicMinimizer
12
13 #include "Math/BasicMinimizer.h"
14
15 #include "Math/IFunction.h"
16
17 #include "Math/IFunctionfwd.h"
18
19 #include "Math/IParamFunctionfwd.h"
20
21 #include "Math/FitMethodFunction.h"
22
24
25 #include "Math/Error.h"
26
27 #include "Fit/ParameterSettings.h"
28
29 #include <cassert>
30
31 #include <iostream>
32 #include <iomanip>
33 #include <cmath>
34 #include <algorithm>
35 #include <functional>
36 #include <ctype.h> // need to use c version of tolower defined here
37 #include <limits>
38
39 namespace ROOT {
40
41  namespace Math {
42
43
45  fDim(0),
46  fObjFunc(0),
47  fMinVal(0)
48 {
49  fValues.reserve(10);
50  fNames.reserve(10);
51  fSteps.reserve(10);
52
54  if (niter <=0 ) niter = 1000;
55  SetMaxIterations(niter);
57 }
58
59
61  if (fObjFunc) delete fObjFunc;
62 }
63
64 bool BasicMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) {
65  // set variable in minimizer - support only free variables
66  // no transformation implemented - so far
67  if (ivar > fValues.size() ) return false;
68  if (ivar == fValues.size() ) {
69  fValues.push_back(val);
70  fNames.push_back(name);
71  fSteps.push_back(step);
72  fVarTypes.push_back(kDefault);
73  }
74  else {
75  fValues[ivar] = val;
76  fNames[ivar] = name;
77  fSteps[ivar] = step;
78  fVarTypes[ivar] = kDefault;
79
80  // remove bounds if needed
81  std::map<unsigned int, std::pair<double, double> >::iterator iter = fBounds.find(ivar);
82  if ( iter != fBounds.end() ) fBounds.erase (iter);
83
84  }
85
86  return true;
87 }
88
89 bool BasicMinimizer::SetLowerLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double lower) {
90  // set lower limited variable
91  bool ret = SetVariable(ivar, name, val, step);
92  if (!ret) return false;
93  const double upper = std::numeric_limits<double>::infinity();
94  fBounds[ivar] = std::make_pair( lower, upper);
95  fVarTypes[ivar] = kLowBound;
96  return true;
97 }
98 bool BasicMinimizer::SetUpperLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double upper ) {
99  // set upper limited variable
100  bool ret = SetVariable(ivar, name, val, step);
101  if (!ret) return false;
102  const double lower = -std::numeric_limits<double>::infinity();
103  fBounds[ivar] = std::make_pair( lower, upper);
104  fVarTypes[ivar] = kUpBound;
105  return true;
106 }
107
108 bool BasicMinimizer::SetLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double lower, double upper) {
109  // set double bounded variable
110  bool ret = SetVariable(ivar, name, val, step);
111  if (!ret) return false;
112  fBounds[ivar] = std::make_pair( lower, upper);
113  fVarTypes[ivar] = kBounds;
114  return true;
115 }
116
117 bool BasicMinimizer::SetFixedVariable(unsigned int ivar , const std::string & name , double val ) {
118  /// set fixed variable
119  bool ret = SetVariable(ivar, name, val, 0.);
120  if (!ret) return false;
121  fVarTypes[ivar] = kFix;
122  return true;
123 }
124
125
126 bool BasicMinimizer::SetVariableValue(unsigned int ivar, double val) {
127  // set variable value in minimizer
128  // no change to transformation or variable status
129  if (ivar > fValues.size() ) return false;
130  fValues[ivar] = val;
131  return true;
132 }
133
134 bool BasicMinimizer::SetVariableValues( const double * x) {
135  // set all variable values in minimizer
136  if (x == 0) return false;
137  std::copy(x,x+fValues.size(), fValues.begin() );
138  return true;
139 }
140
141 bool BasicMinimizer::SetVariableStepSize(unsigned int ivar, double step) {
142  // set step size
143  if (ivar > fValues.size() ) return false;
144  fSteps[ivar] = step;
145  return true;
146 }
147
148 bool BasicMinimizer::SetVariableLowerLimit(unsigned int ivar, double lower) {
149  // set variable lower limit
150  double upper = (fBounds.count(ivar)) ? fBounds[ivar].second : std::numeric_limits<double>::infinity();
151  return SetVariableLimits(ivar, lower, upper);
152 }
153
154 bool BasicMinimizer::SetVariableUpperLimit(unsigned int ivar, double upper) {
155  // set variable upper limit
156  double lower = (fBounds.count(ivar)) ? fBounds[ivar].first : - std::numeric_limits<double>::infinity();
157  return SetVariableLimits(ivar, lower, upper);
158 }
159
160 bool BasicMinimizer::SetVariableLimits(unsigned int ivar, double lower, double upper) {
161  // set variable limits (remove limits if lower >= upper)
162  if (ivar > fVarTypes.size() ) return false;
163  // if limits do not exists add them or update
164  fBounds[ivar] = std::make_pair( lower, upper);
165  if (lower > upper || (lower == - std::numeric_limits<double>::infinity() &&
166  upper == std::numeric_limits<double>::infinity() ) ) {
167  fBounds.erase(ivar);
168  fVarTypes[ivar] = kDefault;
169  }
170  else if (lower == upper)
171  FixVariable(ivar);
172  else {
173  if (lower == - std::numeric_limits<double>::infinity() )
174  fVarTypes[ivar] = kLowBound;
175  else if (upper == std::numeric_limits<double>::infinity() )
176  fVarTypes[ivar] = kUpBound;
177  else
178  fVarTypes[ivar] = kBounds;
179  }
180  return true;
181 }
182
183 bool BasicMinimizer::FixVariable(unsigned int ivar) {
184  // fix variable
185  if (ivar > fVarTypes.size() ) return false;
186  fVarTypes[ivar] = kFix;
187  return true;
188 }
189
190 bool BasicMinimizer::ReleaseVariable(unsigned int ivar) {
191  // fix variable
192  if (ivar > fVarTypes.size() ) return false;
193  if (fBounds.count(ivar) == 0) {
194  fVarTypes[ivar] = kDefault;
195  return true;
196  }
197  if (fBounds[ivar].first == - std::numeric_limits<double>::infinity() )
198  fVarTypes[ivar] = kLowBound;
199  else if (fBounds[ivar].second == std::numeric_limits<double>::infinity() )
200  fVarTypes[ivar] = kUpBound;
201  else
202  fVarTypes[ivar] = kBounds;
203
204  return true;
205 }
206
207 bool BasicMinimizer::IsFixedVariable(unsigned int ivar) const {
208  if (ivar > fVarTypes.size() ) return false;
209  return (fVarTypes[ivar] == kFix ) ;
210 }
211
212 bool BasicMinimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & varObj) const {
213  if (ivar > fValues.size() ) return false;
214  assert(fValues.size() == fNames.size() && fValues.size() == fVarTypes.size() );
215  varObj.Set(fNames[ivar],fValues[ivar],fSteps[ivar]);
216  std::map< unsigned int , std::pair< double, double> >::const_iterator itr = fBounds.find(ivar);
217  if (itr != fBounds.end() ) {
218  double lower = (itr->second).first;
219  double upper = (itr->second).second;
220  if (fVarTypes[ivar] == kLowBound) varObj.SetLowerLimit( lower );
221  if (fVarTypes[ivar] == kUpBound) varObj.SetUpperLimit( upper );
222  else varObj.SetLimits( lower,upper);
223  }
224  if (fVarTypes[ivar] == kFix ) varObj.Fix();
225  return true;
226 }
227
228 std::string BasicMinimizer::VariableName(unsigned int ivar) const {
229  if (ivar > fNames.size() ) return "";
230  return fNames[ivar];
231 }
232
233 int BasicMinimizer::VariableIndex(const std::string & name) const {
234  std::vector<std::string>::const_iterator itr = std::find( fNames.begin(), fNames.end(), name);
235  if (itr == fNames.end() ) return -1;
236  return itr - fNames.begin();
237 }
238
239
240
242  // set the function to minimizer
243  fObjFunc = func.Clone();
244  fDim = fObjFunc->NDim();
245 }
246
248  // set the function to minimize
249  fObjFunc = dynamic_cast<const ROOT::Math::IMultiGradFunction *>( func.Clone());
250  assert(fObjFunc != 0);
251  fDim = fObjFunc->NDim();
252 }
253
254
256  unsigned int npar = fValues.size();
257  if (npar == 0 || npar < fDim ) {
258  MATH_ERROR_MSGVAL("BasicMinimizer::CheckDimension","Wrong number of parameters",npar);
259  return false;
260  }
261  return true;
262 }
263
265  if (fObjFunc == 0) {
266  MATH_ERROR_MSG("BasicMinimizer::CheckFunction","Function has not been set");
267  return false;
268  }
269  return true;
270 }
271
272
274
275  bool doTransform = (fBounds.size() > 0);
276  unsigned int ivar = 0;
277  while (!doTransform && ivar < fVarTypes.size() ) {
278  doTransform = (fVarTypes[ivar++] != kDefault );
279  }
280
281  startValues = std::vector<double>(fValues.begin(), fValues.end() );
282
283  MinimTransformFunction * trFunc = 0;
284
285  // in case of transformation wrap objective function in a new transformation function
286  // and transform from external variables to internals one
287  // Transformations are supported only for gradient function
288  const IMultiGradFunction * gradObjFunc = (func) ? func : dynamic_cast<const IMultiGradFunction *>(fObjFunc);
289  doTransform &= (gradObjFunc != 0);
290
291  if (doTransform) {
292  // minim transform function manages the passed function pointer (gradObjFunc)
293  trFunc = new MinimTransformFunction ( gradObjFunc, fVarTypes, fValues, fBounds );
294  // transform from external to internal
295  trFunc->InvTransformation(&fValues.front(), &startValues[0]);
296  // size can be different since internal parameter can have smaller size
297  // if there are fixed parameters
298  startValues.resize( trFunc->NDim() );
299  // no need to save fObjFunc since trFunc will manage it
300  fObjFunc = trFunc;
301  }
302  else {
303  if (func) fObjFunc = func; // to manege the passed function object
304  }
305
306 // std::cout << " f has transform " << doTransform << " " << fBounds.size() << " " << startValues.size() << " ndim " << fObjFunc->NDim() << std::endl; std::cout << "InitialValues external : ";
307 // for (int i = 0; i < fValues.size(); ++i) std::cout << fValues[i] << " ";
308 // std::cout << "\n";
309 // std::cout << "InitialValues internal : ";
310 // for (int i = 0; i < startValues.size(); ++i) std::cout << startValues[i] << " ";
311 // std::cout << "\n";
312
313
314  return trFunc;
315 }
316
318
319  // do nothing
320  return false;
321 }
322
323 void BasicMinimizer::SetFinalValues(const double * x) {
324  // check to see if a transformation need to be applied
325  const MinimTransformFunction * trFunc = TransformFunction();
326  if (trFunc) {
327  assert(fValues.size() >= trFunc->NTot() );
328  trFunc->Transformation(x, &fValues[0]);
329  }
330  else {
331  // case of no transformation applied
332  assert( fValues.size() >= NDim() );
333  std::copy(x, x + NDim(), fValues.begin() );
334  }
335 }
336
338  int pr = std::cout.precision(18);
339  std::cout << "FVAL = " << fMinVal << std::endl;
340  std::cout.precision(pr);
341 // std::cout << "Edm = " << fState.Edm() << std::endl;
342  std::cout << "Niterations = " << NIterations() << std::endl;
343  unsigned int ncalls = NCalls();
344  if (ncalls) std::cout << "NCalls = " << ncalls << std::endl;
345  for (unsigned int i = 0; i < fDim; ++i)
346  std::cout << fNames[i] << "\t = " << fValues[i] << std::endl;
347 }
348
350  return dynamic_cast<const ROOT::Math::IMultiGradFunction *>(fObjFunc);
351 }
352
354  return dynamic_cast<const MinimTransformFunction *>(fObjFunc);
355 }
356
357 unsigned int BasicMinimizer::NFree() const {
358  // number of free variables
359  unsigned int nfree = fValues.size();
360  for (unsigned int i = 0; i < fVarTypes.size(); ++i)
361  if (fVarTypes[i] == kFix) nfree--;
362  return nfree;
363 }
364
365
366  } // end namespace Math
367
368 } // end namespace ROOT
369
virtual bool SetVariableUpperLimit(unsigned int ivar, double upper)
set the upper-limit of an already existing variable
void SetMaxIterations(unsigned int maxiter)
set maximum iterations (one iteration can have many function calls)
Definition: Minimizer.h:451
Interface (abstract class) for multi-dimensional functions providing a gradient calculation.
Definition: IFunction.h:326
std::vector< ROOT::Math::EMinimVariableType > fVarTypes
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
virtual bool SetVariableStepSize(unsigned int ivar, double step)
set the step size of an already existing variable
virtual bool SetFixedVariable(unsigned int, const std::string &, double)
set fixed variable (override if minimizer supports them )
virtual bool SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper)
set upper limit variable (override if minimizer supports them )
Class, describing value, limits and step size of the parameters Provides functionality also to set/re...
virtual bool SetVariableValues(const double *x)
set the values of all existing variables (array must be dimensioned to the size of existing parameter...
const double * Transformation(const double *x) const
transform from internal to external result is cached also inside the class
MinimTransformFunction class to perform a transformations on the variables to deal with fixed or limi...
virtual bool SetVariableLowerLimit(unsigned int ivar, double lower)
set the lower-limit of an already existing variable
virtual IBaseFunctionMultiDimTempl< T > * Clone() const =0
Clone a function.
MinimTransformFunction * CreateTransformation(std::vector< double > &startValues, const ROOT::Math::IMultiGradFunction *func=0)
virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper)
set the limits of an already existing variable
virtual bool SetVariable(unsigned int ivar, const std::string &name, double val, double step)
set free variable
virtual bool SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower)
set lower limit variable (override if minimizer supports them )
const ROOT::Math::IMultiGenFunction * fObjFunc
virtual std::string VariableName(unsigned int ivar) const
get name of variables (override if minimizer support storing of variable names)
#define MATH_ERROR_MSGVAL(loc, str, x)
Definition: Error.h:69
Double_t x[n]
Definition: legend1.C:17
void Fix()
fix the parameter
std::vector< double > fValues
virtual int VariableIndex(const std::string &name) const
get index of variable given a variable given a name return -1 if variable is not found ...
virtual unsigned int NDim() const
number of dimensions
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:50
std::map< unsigned int, std::pair< double, double > > fBounds
virtual unsigned int NIterations() const
number of iterations to reach the minimum
Definition: Minimizer.h:263
static constexpr double second
std::vector< double > fSteps
void SetLowerLimit(double low)
set a single lower limit
virtual unsigned int NCalls() const
number of function calls to reach the minimum
Definition: Minimizer.h:260
Documentation for the abstract class IBaseFunctionMultiDim.
Definition: IFunction.h:62
virtual bool Minimize()
method to perform the minimization
void SetFinalValues(const double *x)
virtual bool FixVariable(unsigned int ivar)
fix an existing variable
const ROOT::Math::MinimTransformFunction * TransformFunction() const
return transformation function (NULL if not having a transformation)
virtual void SetFunction(const ROOT::Math::IMultiGenFunction &func)
set the function to minimize
const ROOT::Math::IMultiGradFunction * GradObjFunction() const
return pointer to used gradient object function (NULL if gradient is not supported) ...
void Set(const std::string &name, double value, double step)
set value and name (unlimited parameter)
virtual unsigned int NFree() const
number of free variables (real dimension of the problem)
virtual bool IsFixedVariable(unsigned int ivar) const
query if an existing variable is fixed (i.e.
virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const
get variable settings in a variable object (like ROOT::Fit::ParamsSettings)
Namespace for new Math classes and functions.
virtual bool ReleaseVariable(unsigned int ivar)
release an existing variable
virtual bool SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double, double)
set upper/lower limited variable (override if minimizer supports them )
void SetUpperLimit(double up)
set a single upper limit
void PrintResult() const
print result of minimization
std::vector< std::string > fNames
void SetLimits(double low, double up)
set a double side limit, if low == up the parameter is fixed if low > up the limits are removed The c...
BasicMinimizer()
Default constructor.
void SetPrintLevel(int level)
set print level
Definition: Minimizer.h:445
Definition: first.py:1
virtual bool SetVariableValue(unsigned int ivar, double val)
set the value of an existing variable
char name[80]
Definition: TGX11.cxx:109
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
virtual ~BasicMinimizer()
Destructor.