ROOT  6.06/08
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/FitMethodFunction.h"
18 
20 
21 #include "Math/Error.h"
22 
23 #include "Fit/ParameterSettings.h"
24 
25 #include <cassert>
26 
27 #include <iostream>
28 #include <iomanip>
29 #include <cmath>
30 #include <algorithm>
31 #include <functional>
32 #include <ctype.h> // need to use c version of tolower defined here
33 #include <limits>
34 
35 namespace ROOT {
36 
37  namespace Math {
38 
39 
41  fDim(0),
42  fObjFunc(0),
43  fMinVal(0)
44 {
45  fValues.reserve(10);
46  fNames.reserve(10);
47  fSteps.reserve(10);
48 
50  if (niter <=0 ) niter = 1000;
51  SetMaxIterations(niter);
53 }
54 
55 
57  if (fObjFunc) delete fObjFunc;
58 }
59 
60 bool BasicMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) {
61  // set variable in minimizer - support only free variables
62  // no transformation implemented - so far
63  if (ivar > fValues.size() ) return false;
64  if (ivar == fValues.size() ) {
65  fValues.push_back(val);
66  fNames.push_back(name);
67  fSteps.push_back(step);
68  fVarTypes.push_back(kDefault);
69  }
70  else {
71  fValues[ivar] = val;
72  fNames[ivar] = name;
73  fSteps[ivar] = step;
74  fVarTypes[ivar] = kDefault;
75 
76  // remove bounds if needed
77  std::map<unsigned int, std::pair<double, double> >::iterator iter = fBounds.find(ivar);
78  if ( iter != fBounds.end() ) fBounds.erase (iter);
79 
80  }
81 
82  return true;
83 }
84 
85 bool BasicMinimizer::SetLowerLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double lower) {
86  // set lower limited variable
87  bool ret = SetVariable(ivar, name, val, step);
88  if (!ret) return false;
90  fBounds[ivar] = std::make_pair( lower, upper);
91  fVarTypes[ivar] = kLowBound;
92  return true;
93 }
94 bool BasicMinimizer::SetUpperLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double upper ) {
95  // set upper limited variable
96  bool ret = SetVariable(ivar, name, val, step);
97  if (!ret) return false;
99  fBounds[ivar] = std::make_pair( lower, upper);
100  fVarTypes[ivar] = kUpBound;
101  return true;
102 }
103 
104 bool BasicMinimizer::SetLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double lower, double upper) {
105  // set double bounded variable
106  bool ret = SetVariable(ivar, name, val, step);
107  if (!ret) return false;
108  fBounds[ivar] = std::make_pair( lower, upper);
109  fVarTypes[ivar] = kBounds;
110  return true;
111 }
112 
113 bool BasicMinimizer::SetFixedVariable(unsigned int ivar , const std::string & name , double val ) {
114  /// set fixed variable
115  bool ret = SetVariable(ivar, name, val, 0.);
116  if (!ret) return false;
117  fVarTypes[ivar] = kFix;
118  return true;
119 }
120 
121 
122 bool BasicMinimizer::SetVariableValue(unsigned int ivar, double val) {
123  // set variable value in minimizer
124  // no change to transformation or variable status
125  if (ivar > fValues.size() ) return false;
126  fValues[ivar] = val;
127  return true;
128 }
129 
130 bool BasicMinimizer::SetVariableValues( const double * x) {
131  // set all variable values in minimizer
132  if (x == 0) return false;
133  std::copy(x,x+fValues.size(), fValues.begin() );
134  return true;
135 }
136 
137 bool BasicMinimizer::SetVariableStepSize(unsigned int ivar, double step) {
138  // set step size
139  if (ivar > fValues.size() ) return false;
140  fSteps[ivar] = step;
141  return true;
142 }
143 
144 bool BasicMinimizer::SetVariableLowerLimit(unsigned int ivar, double lower) {
145  // set variable lower limit
146  double upper = (fBounds.count(ivar)) ? fBounds[ivar].second : std::numeric_limits<double>::infinity();
147  return SetVariableLimits(ivar, lower, upper);
148 }
149 
150 bool BasicMinimizer::SetVariableUpperLimit(unsigned int ivar, double upper) {
151  // set variable upper limit
152  double lower = (fBounds.count(ivar)) ? fBounds[ivar].first : - std::numeric_limits<double>::infinity();
153  return SetVariableLimits(ivar, lower, upper);
154 }
155 
156 bool BasicMinimizer::SetVariableLimits(unsigned int ivar, double lower, double upper) {
157  // set variable limits (remove limits if lower >= upper)
158  if (ivar > fVarTypes.size() ) return false;
159  // if limits do not exists add them or update
160  fBounds[ivar] = std::make_pair( lower, upper);
161  if (lower > upper || (lower == - std::numeric_limits<double>::infinity() &&
163  fBounds.erase(ivar);
164  fVarTypes[ivar] = kDefault;
165  }
166  else if (lower == upper)
167  FixVariable(ivar);
168  else {
169  if (lower == - std::numeric_limits<double>::infinity() )
170  fVarTypes[ivar] = kLowBound;
171  else if (upper == std::numeric_limits<double>::infinity() )
172  fVarTypes[ivar] = kUpBound;
173  else
174  fVarTypes[ivar] = kBounds;
175  }
176  return true;
177 }
178 
179 bool BasicMinimizer::FixVariable(unsigned int ivar) {
180  // fix variable
181  if (ivar > fVarTypes.size() ) return false;
182  fVarTypes[ivar] = kFix;
183  return true;
184 }
185 
186 bool BasicMinimizer::ReleaseVariable(unsigned int ivar) {
187  // fix variable
188  if (ivar > fVarTypes.size() ) return false;
189  if (fBounds.count(ivar) == 0) {
190  fVarTypes[ivar] = kDefault;
191  return true;
192  }
193  if (fBounds[ivar].first == - std::numeric_limits<double>::infinity() )
194  fVarTypes[ivar] = kLowBound;
195  else if (fBounds[ivar].second == std::numeric_limits<double>::infinity() )
196  fVarTypes[ivar] = kUpBound;
197  else
198  fVarTypes[ivar] = kBounds;
199 
200  return true;
201 }
202 
203 bool BasicMinimizer::IsFixedVariable(unsigned int ivar) const {
204  if (ivar > fVarTypes.size() ) return false;
205  return (fVarTypes[ivar] == kFix ) ;
206 }
207 
208 bool BasicMinimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & varObj) const {
209  if (ivar > fValues.size() ) return false;
210  assert(fValues.size() == fNames.size() && fValues.size() == fVarTypes.size() );
211  varObj.Set(fNames[ivar],fValues[ivar],fSteps[ivar]);
212  std::map< unsigned int , std::pair< double, double> >::const_iterator itr = fBounds.find(ivar);
213  if (itr != fBounds.end() ) {
214  double lower = (itr->second).first;
215  double upper = (itr->second).second;
216  if (fVarTypes[ivar] == kLowBound) varObj.SetLowerLimit( lower );
217  if (fVarTypes[ivar] == kUpBound) varObj.SetUpperLimit( upper );
218  else varObj.SetLimits( lower,upper);
219  }
220  if (fVarTypes[ivar] == kFix ) varObj.Fix();
221  return true;
222 }
223 
224 std::string BasicMinimizer::VariableName(unsigned int ivar) const {
225  if (ivar > fNames.size() ) return "";
226  return fNames[ivar];
227 }
228 
229 int BasicMinimizer::VariableIndex(const std::string & name) const {
230  std::vector<std::string>::const_iterator itr = std::find( fNames.begin(), fNames.end(), name);
231  if (itr == fNames.end() ) return -1;
232  return itr - fNames.begin();
233 }
234 
235 
236 
238  // set the function to minimizer
239  fObjFunc = func.Clone();
240  fDim = fObjFunc->NDim();
241 }
242 
244  // set the function to minimize
245  fObjFunc = dynamic_cast<const ROOT::Math::IMultiGradFunction *>( func.Clone());
246  assert(fObjFunc != 0);
247  fDim = fObjFunc->NDim();
248 }
249 
250 
252  unsigned int npar = fValues.size();
253  if (npar == 0 || npar < fDim ) {
254  MATH_ERROR_MSGVAL("BasicMinimizer::CheckDimension","Wrong number of parameters",npar);
255  return false;
256  }
257  return true;
258 }
259 
261  if (fObjFunc == 0) {
262  MATH_ERROR_MSG("BasicMinimizer::CheckFunction","Function has not been set");
263  return false;
264  }
265  return true;
266 }
267 
268 
270 
271  bool doTransform = (fBounds.size() > 0);
272  unsigned int ivar = 0;
273  while (!doTransform && ivar < fVarTypes.size() ) {
274  doTransform = (fVarTypes[ivar++] != kDefault );
275  }
276 
277  startValues = std::vector<double>(fValues.begin(), fValues.end() );
278 
279  MinimTransformFunction * trFunc = 0;
280 
281  // in case of transformation wrap objective function in a new transformation function
282  // and transform from external variables to internals one
283  // Transformations are supported only for gradient function
284  const IMultiGradFunction * gradObjFunc = (func) ? func : dynamic_cast<const IMultiGradFunction *>(fObjFunc);
285  doTransform &= (gradObjFunc != 0);
286 
287  if (doTransform) {
288  // minim transform function manages the passed function pointer (gradObjFunc)
289  trFunc = new MinimTransformFunction ( gradObjFunc, fVarTypes, fValues, fBounds );
290  // transform from external to internal
291  trFunc->InvTransformation(&fValues.front(), &startValues[0]);
292  // size can be different since internal parameter can have smaller size
293  // if there are fixed parameters
294  startValues.resize( trFunc->NDim() );
295  // no need to save fObjFunc since trFunc will manage it
296  fObjFunc = trFunc;
297  }
298  else {
299  if (func) fObjFunc = func; // to manege the passed function object
300  }
301 
302 // std::cout << " f has transform " << doTransform << " " << fBounds.size() << " " << startValues.size() << " ndim " << fObjFunc->NDim() << std::endl; std::cout << "InitialValues external : ";
303 // for (int i = 0; i < fValues.size(); ++i) std::cout << fValues[i] << " ";
304 // std::cout << "\n";
305 // std::cout << "InitialValues internal : ";
306 // for (int i = 0; i < startValues.size(); ++i) std::cout << startValues[i] << " ";
307 // std::cout << "\n";
308 
309 
310  return trFunc;
311 }
312 
314 
315  // do nothing
316  return false;
317 }
318 
319 void BasicMinimizer::SetFinalValues(const double * x) {
320  // check to see if a transformation need to be applied
321  const MinimTransformFunction * trFunc = TransformFunction();
322  if (trFunc) {
323  assert(fValues.size() >= trFunc->NTot() );
324  trFunc->Transformation(x, &fValues[0]);
325  }
326  else {
327  // case of no transformation applied
328  assert( fValues.size() >= NDim() );
329  std::copy(x, x + NDim(), fValues.begin() );
330  }
331 }
332 
334  int pr = std::cout.precision(18);
335  std::cout << "FVAL = " << fMinVal << std::endl;
336  std::cout.precision(pr);
337 // std::cout << "Edm = " << fState.Edm() << std::endl;
338  std::cout << "Niterations = " << NIterations() << std::endl;
339  unsigned int ncalls = NCalls();
340  if (ncalls) std::cout << "NCalls = " << ncalls << std::endl;
341  for (unsigned int i = 0; i < fDim; ++i)
342  std::cout << fNames[i] << "\t = " << fValues[i] << std::endl;
343 }
344 
346  return dynamic_cast<const ROOT::Math::IMultiGradFunction *>(fObjFunc);
347 }
348 
350  return dynamic_cast<const MinimTransformFunction *>(fObjFunc);
351 }
352 
353 unsigned int BasicMinimizer::NFree() const {
354  // number of free variables
355  unsigned int nfree = fValues.size();
356  for (unsigned int i = 0; i < fVarTypes.size(); ++i)
357  if (fVarTypes[i] == kFix) nfree--;
358  return nfree;
359 }
360 
361 
362  } // end namespace Math
363 
364 } // end namespace ROOT
365 
Interface (abstract class) for multi-dimensional functions providing a gradient calculation.
Definition: IFunction.h:322
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:459
std::vector< ROOT::Math::EMinimVariableType > fVarTypes
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
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 )
#define assert(cond)
Definition: unittest.h:542
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
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
static const float upper
Definition: main.cpp:49
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:271
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:268
virtual bool Minimize()
method to perform the minimization
void SetFinalValues(const double *x)
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
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)
const Double_t infinity
Definition: CsgOps.cxx:85
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)
double func(double *x, double *p)
Definition: stressTF1.cxx:213
Namespace for new Math classes and functions.
#define name(a, b)
Definition: linkTestLib0.cpp:5
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 ...
BasicMinimizer()
Default constructor.
void SetPrintLevel(int level)
set print level
Definition: Minimizer.h:453
Documentation for the abstract class IBaseFunctionMultiDim.
Definition: IFunction.h:63
virtual bool SetVariableValue(unsigned int ivar, double val)
set the value of an existing variable
static const float lower
Definition: main.cpp:48
virtual IBaseFunctionMultiDim * Clone() const =0
Clone a function.
virtual ~BasicMinimizer()
Destructor.