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