Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 
44 BasicMinimizer::BasicMinimizer( ) :
45  fDim(0),
46  fObjFunc(0),
47  fMinVal(0)
48 {
49  fValues.reserve(10);
50  fNames.reserve(10);
51  fSteps.reserve(10);
52 
53  int niter = ROOT::Math::MinimizerOptions::DefaultMaxIterations();
54  if (niter <=0 ) niter = 1000;
55  SetMaxIterations(niter);
56  SetPrintLevel(ROOT::Math::MinimizerOptions::DefaultPrintLevel());
57 }
58 
59 
60 BasicMinimizer::~BasicMinimizer () {
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 
241 void BasicMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction & func) {
242  // set the function to minimizer
243  fObjFunc = func.Clone();
244  fDim = fObjFunc->NDim();
245 }
246 
247 void BasicMinimizer::SetFunction(const ROOT::Math::IMultiGradFunction & func) {
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 
255 bool BasicMinimizer::CheckDimension() const {
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 
264 bool BasicMinimizer::CheckObjFunction() const {
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 
273 MinimTransformFunction * BasicMinimizer::CreateTransformation(std::vector<double> & startValues, const ROOT::Math::IMultiGradFunction * func) {
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 
317 bool BasicMinimizer::Minimize() {
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 
337 void BasicMinimizer::PrintResult() const {
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 
349 const ROOT::Math::IMultiGradFunction * BasicMinimizer::GradObjFunction() const {
350  return dynamic_cast<const ROOT::Math::IMultiGradFunction *>(fObjFunc);
351 }
352 
353 const MinimTransformFunction * BasicMinimizer::TransformFunction() const {
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