Logo 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 <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 after cloning it
242 fObjFunc = func.Clone();
243 fDim = fObjFunc->NDim();
244}
245
247 // set the gradient function to minimize after cloning it
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 // in case of transformation wrap objective function in a new transformation function
283 // and transform from external variables to internals ones type
284 // Transformations are supported only for gradient function
285 const IMultiGradFunction * gradObjFunc = (func) ? func : dynamic_cast<const IMultiGradFunction *>(fObjFunc);
286 doTransform &= (gradObjFunc != 0);
287
288 if (!doTransform) return nullptr;
289
290 // minim transform function manages the passed function pointer (gradObjFunc)
291 auto trFunc = new MinimTransformFunction ( gradObjFunc, fVarTypes, fValues, fBounds );
292 // transform from external to internal
293 trFunc->InvTransformation(&fValues.front(), &startValues[0]);
294 // size can be different since internal parameter can have smaller size
295 // if there are fixed parameters
296 startValues.resize( trFunc->NDim() );
297 // we transfer ownership of trFunc to the caller
298 return trFunc;
299}
300
302
303 // do nothing
304 return false;
305}
306
307void BasicMinimizer::SetFinalValues(const double * x, const MinimTransformFunction * trFunc) {
308 // check to see if a transformation needs to be applied
309 if (trFunc) {
310 assert(fValues.size() >= trFunc->NTot() );
311 trFunc->Transformation(x, &fValues[0]);
312 }
313 else {
314 // case of no transformation applied
315 assert( fValues.size() >= NDim() );
316 std::copy(x, x + NDim(), fValues.begin() );
317 }
318}
319
321 int pr = std::cout.precision(18);
322 std::cout << "FVAL = " << fMinVal << std::endl;
323 std::cout.precision(pr);
324// std::cout << "Edm = " << fState.Edm() << std::endl;
325 std::cout << "Niterations = " << NIterations() << std::endl;
326 unsigned int ncalls = NCalls();
327 if (ncalls) std::cout << "NCalls = " << ncalls << std::endl;
328 for (unsigned int i = 0; i < fDim; ++i)
329 std::cout << fNames[i] << "\t = " << fValues[i] << std::endl;
330}
331
333 return dynamic_cast<const ROOT::Math::IMultiGradFunction *>(fObjFunc);
334}
335
336
337unsigned int BasicMinimizer::NFree() const {
338 // number of free variables
339 unsigned int nfree = fValues.size();
340 for (unsigned int i = 0; i < fVarTypes.size(); ++i)
341 if (fVarTypes[i] == kFix) nfree--;
342 return nfree;
343}
344
345
346 } // end namespace Math
347
348} // end namespace ROOT
349
#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
~BasicMinimizer() override
Destructor.
bool IsFixedVariable(unsigned int ivar) const override
query if an existing variable is fixed (i.e.
void PrintResult() const
print result of minimization
BasicMinimizer()
Default constructor.
const ROOT::Math::IMultiGenFunction * fObjFunc
unsigned int NFree() const override
number of free variables (real dimension of the problem)
unsigned int NDim() const override
number of dimensions
bool SetVariableStepSize(unsigned int ivar, double step) override
set the step size of an already existing variable
std::vector< ROOT::Math::EMinimVariableType > fVarTypes
vector specifying the type of variables
void SetFinalValues(const double *x, const MinimTransformFunction *func=nullptr)
bool SetVariable(unsigned int ivar, const std::string &name, double val, double step) override
set free variable
MinimTransformFunction * CreateTransformation(std::vector< double > &startValues, const ROOT::Math::IMultiGradFunction *func=nullptr)
int VariableIndex(const std::string &name) const override
get index of variable given a variable given a name return -1 if variable is not found
bool SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower) override
set lower limit variable (override if minimizer supports them )
void SetFunction(const ROOT::Math::IMultiGenFunction &func) override
set the function to minimize
bool SetVariableLowerLimit(unsigned int ivar, double lower) override
set the lower-limit of an already existing variable
bool SetVariableValues(const double *x) override
set the values of all existing variables (array must be dimensioned to the size of existing parameter...
bool Minimize() override
method to perform the minimization
std::vector< double > fSteps
bool SetFixedVariable(unsigned int, const std::string &, double) override
set fixed variable (override if minimizer supports them )
bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const override
get variable settings in a variable object (like ROOT::Fit::ParamsSettings)
std::map< unsigned int, std::pair< double, double > > fBounds
map specifying the bound using as key the parameter index
bool SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper) override
set upper limit variable (override if minimizer supports them )
bool SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double, double) override
set upper/lower limited variable (override if minimizer supports them )
bool ReleaseVariable(unsigned int ivar) override
release an existing variable
bool SetVariableLimits(unsigned int ivar, double lower, double upper) override
set the limits of an already existing variable
std::vector< double > fValues
bool FixVariable(unsigned int ivar) override
fix an existing variable
const ROOT::Math::IMultiGradFunction * GradObjFunction() const
return pointer to used gradient object function (NULL if gradient is not supported)
std::vector< std::string > fNames
std::string VariableName(unsigned int ivar) const override
get name of variables (override if minimizer support storing of variable names)
bool SetVariableValue(unsigned int ivar, double val) override
set the value of an existing variable
bool SetVariableUpperLimit(unsigned int ivar, double upper) override
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...
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.
@ kFix
fixed variable
@ kUpBound
variable has an upper bounds
@ kBounds
variable has two bounds
@ kLowBound
variable has a lower bound
@ kDefault
free variable (unlimited)
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
static constexpr double second
Definition: first.py:1