Logo ROOT   6.07/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/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 
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
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
std::vector< ROOT::Math::EMinimVariableType > fVarTypes
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
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 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 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
#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
void Fix()
fix the parameter
std::vector< double > fValues
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 bool FixVariable(unsigned int ivar)
fix an existing variable
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) ...
virtual IBaseFunctionMultiDim * Clone() const =0
Clone a function.
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.
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
Definition: first.py:1
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
char name[80]
Definition: TGX11.cxx:109
virtual ~BasicMinimizer()
Destructor.
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:50