ROOT  6.06/09
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 )
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 ...
#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...
void PrintResult() const
print result of minimization
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
#define MATH_ERROR_MSGVAL(loc, str, x)
Definition: Error.h:69
virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const
get variable settings in a variable object (like ROOT::Fit::ParamsSettings)
Double_t x[n]
Definition: legend1.C:17
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
void Fix()
fix the parameter
std::vector< double > fValues
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:50
std::map< unsigned int, std::pair< double, double > > fBounds
std::vector< double > fSteps
void SetLowerLimit(double low)
set a single lower limit
virtual unsigned int NDim() const
number of dimensions
virtual bool Minimize()
method to perform the minimization
void SetFinalValues(const double *x)
const ROOT::Math::MinimTransformFunction * TransformFunction() const
return transformation function (NULL if not having a transformation)
virtual std::string VariableName(unsigned int ivar) const
get name of variables (override if minimizer support storing of variable names)
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
virtual bool FixVariable(unsigned int ivar)
fix an existing variable
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 NIterations() const
number of iterations to reach the minimum
Definition: Minimizer.h:271
virtual unsigned int NFree() const
number of free variables (real dimension of the problem)
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
virtual bool IsFixedVariable(unsigned int ivar) const
query if an existing variable is fixed (i.e.
std::vector< std::string > fNames
const double * Transformation(const double *x) const
transform from internal to external result is cached also inside the class
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.
virtual unsigned int NCalls() const
number of function calls to reach the minimum
Definition: Minimizer.h:268
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.