ROOT   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
20
22
24
25#include "Math/Error.h"
26
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
39namespace 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
64bool 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
89bool 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}
98bool 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
108bool 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
117bool 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
126bool 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
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
141bool 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
148bool 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
154bool 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
160bool 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
183bool BasicMinimizer::FixVariable(unsigned int ivar) {
184 // fix variable
185 if (ivar >= fVarTypes.size() ) return false;
186 fVarTypes[ivar] = kFix;
187 return true;
188}
189
190bool 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
207bool BasicMinimizer::IsFixedVariable(unsigned int ivar) const {
208 if (ivar >= fVarTypes.size() ) return false;
209 return (fVarTypes[ivar] == kFix ) ;
210}
211
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
228std::string BasicMinimizer::VariableName(unsigned int ivar) const {
229 if (ivar >= fNames.size() ) return "";
230 return fNames[ivar];
231}
232
233int 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
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
323void 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
351}
352
354 return dynamic_cast<const MinimTransformFunction *>(fObjFunc);
355}
356
357unsigned 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
#define MATH_ERROR_MSGVAL(loc, txt, x)
Definition: Error.h:108
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:82
char name[80]
Definition: TGX11.cxx:109
Class, describing value, limits and step size of the parameters Provides functionality also to set/re...
void Set(const std::string &name, double value, double step)
set value and name (unlimited parameter)
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...
void SetUpperLimit(double up)
set a single upper limit
void Fix()
fix the parameter
void SetLowerLimit(double low)
set a single lower limit
virtual ~BasicMinimizer()
Destructor.
virtual unsigned int NFree() const
number of free variables (real dimension of the problem)
virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const
get variable settings in a variable object (like ROOT::Fit::ParamsSettings)
void PrintResult() const
print result of minimization
BasicMinimizer()
Default constructor.
const ROOT::Math::IMultiGenFunction * fObjFunc
virtual bool IsFixedVariable(unsigned int ivar) const
query if an existing variable is fixed (i.e.
std::vector< ROOT::Math::EMinimVariableType > fVarTypes
const ROOT::Math::MinimTransformFunction * TransformFunction() const
return transformation function (NULL if not having a transformation)
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 )
virtual void SetFunction(const ROOT::Math::IMultiGenFunction &func)
set the function to minimize
virtual bool SetVariable(unsigned int ivar, const std::string &name, double val, double step)
set free variable
virtual bool FixVariable(unsigned int ivar)
fix an existing variable
virtual unsigned int NDim() const
number of dimensions
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 )
virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper)
set the limits of an already existing variable
std::vector< double > fSteps
virtual bool SetVariableValues(const double *x)
set the values of all existing variables (array must be dimensioned to the size of existing parameter...
virtual bool SetVariableStepSize(unsigned int ivar, double step)
set the step size of an already existing variable
virtual bool ReleaseVariable(unsigned int ivar)
release an existing variable
virtual std::string VariableName(unsigned int ivar) const
get name of variables (override if minimizer support storing of variable names)
std::map< unsigned int, std::pair< double, double > > fBounds
virtual bool SetVariableValue(unsigned int ivar, double val)
set the value of an existing variable
void SetFinalValues(const double *x)
virtual bool SetFixedVariable(unsigned int, const std::string &, double)
set fixed variable (override if minimizer supports them )
virtual bool SetVariableLowerLimit(unsigned int ivar, double lower)
set the lower-limit of an already existing variable
virtual bool Minimize()
method to perform the minimization
MinimTransformFunction * CreateTransformation(std::vector< double > &startValues, const ROOT::Math::IMultiGradFunction *func=0)
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
std::vector< double > fValues
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 )
return pointer to used gradient object function (NULL if gradient is not supported)
std::vector< std::string > fNames
virtual bool SetVariableUpperLimit(unsigned int ivar, double upper)
set the upper-limit of an already existing variable
Documentation for the abstract class IBaseFunctionMultiDim.
Definition: IFunction.h:62
virtual IBaseFunctionMultiDimTempl< T > * Clone() const =0
Clone a function.
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
Interface (abstract class) for multi-dimensional functions providing a gradient calculation.
Definition: IFunction.h:327
MinimTransformFunction class to perform a transformations on the variables to deal with fixed or limi...
unsigned int NDim() const
Retrieve the dimension of the function.
void InvTransformation(const double *xext, double *xint) const
inverse transformation (external -> internal)
const double * Transformation(const double *x) const
transform from internal to external result is cached also inside the class
virtual unsigned int NIterations() const
number of iterations to reach the minimum
Definition: Minimizer.h:263
void SetMaxIterations(unsigned int maxiter)
set maximum iterations (one iteration can have many function calls)
Definition: Minimizer.h:451
void SetPrintLevel(int level)
set print level
Definition: Minimizer.h:445
virtual unsigned int NCalls() const
number of function calls to reach the minimum
Definition: Minimizer.h:260
Double_t x[n]
Definition: legend1.C:17
Namespace for new Math classes and functions.
VSD Structures.
Definition: StringConv.hxx:21
static constexpr double second
Definition: first.py:1