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(nullptr),
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 == nullptr) 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
246
248 unsigned int npar = fValues.size();
249 if (npar == 0 || npar < fDim ) {
250 MATH_ERROR_MSGVAL("BasicMinimizer::CheckDimension","Wrong number of parameters",npar);
251 return false;
252 }
253 return true;
254}
255
257 if (fObjFunc == nullptr) {
258 MATH_ERROR_MSG("BasicMinimizer::CheckFunction","Function has not been set");
259 return false;
260 }
261 return true;
262}
263
264
266
267 bool doTransform = (!fBounds.empty());
268 unsigned int ivar = 0;
269 while (!doTransform && ivar < fVarTypes.size() ) {
270 doTransform = (fVarTypes[ivar++] != kDefault );
271 }
272
273 startValues = std::vector<double>(fValues.begin(), fValues.end() );
274
275 // in case of transformation wrap objective function in a new transformation function
276 // and transform from external variables to internals ones type
277 // Transformations are supported only for gradient function
278 const IMultiGradFunction * gradObjFunc = (func) ? func : dynamic_cast<const IMultiGradFunction *>(fObjFunc);
279 doTransform &= (gradObjFunc != nullptr);
280
281 if (!doTransform) return nullptr;
282
283 // minim transform function manages the passed function pointer (gradObjFunc)
284 auto trFunc = new MinimTransformFunction ( gradObjFunc, fVarTypes, fValues, fBounds );
285 // transform from external to internal
286 trFunc->InvTransformation(&fValues.front(), &startValues[0]);
287 // size can be different since internal parameter can have smaller size
288 // if there are fixed parameters
289 startValues.resize( trFunc->NDim() );
290 // we transfer ownership of trFunc to the caller
291 return trFunc;
292}
293
295
296 // do nothing
297 return false;
298}
299
300void BasicMinimizer::SetFinalValues(const double * x, const MinimTransformFunction * trFunc) {
301 // check to see if a transformation needs to be applied
302 if (trFunc) {
303 assert(fValues.size() >= trFunc->NTot() );
304 trFunc->Transformation(x, &fValues[0]);
305 }
306 else {
307 // case of no transformation applied
308 assert( fValues.size() >= NDim() );
309 std::copy(x, x + NDim(), fValues.begin() );
310 }
311}
312
314 int pr = std::cout.precision(18);
315 std::cout << "FVAL = " << fMinVal << std::endl;
316 std::cout.precision(pr);
317// std::cout << "Edm = " << fState.Edm() << std::endl;
318 std::cout << "Niterations = " << NIterations() << std::endl;
319 unsigned int ncalls = NCalls();
320 if (ncalls) std::cout << "NCalls = " << ncalls << std::endl;
321 for (unsigned int i = 0; i < fDim; ++i)
322 std::cout << fNames[i] << "\t = " << fValues[i] << std::endl;
323}
324
326 return dynamic_cast<const ROOT::Math::IMultiGradFunction *>(fObjFunc);
327}
328
329
330unsigned int BasicMinimizer::NFree() const {
331 // number of free variables
332 unsigned int nfree = fValues.size();
333 for (unsigned int i = 0; i < fVarTypes.size(); ++i)
334 if (fVarTypes[i] == kFix) nfree--;
335 return nfree;
336}
337
338
339 } // end namespace Math
340
341} // end namespace ROOT
342
#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:61
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:168
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:246
void SetMaxIterations(unsigned int maxiter)
set maximum iterations (one iteration can have many function calls)
Definition Minimizer.h:349
void SetPrintLevel(int level)
set print level
Definition Minimizer.h:343
virtual unsigned int NCalls() const
number of function calls to reach the minimum
Definition Minimizer.h:243
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)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...