Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
Minuit2Minimizer.cxx
Go to the documentation of this file.
1 // @(#)root/minuit2:$Id$
2 // Author: L. Moneta Wed Oct 18 11:48:00 2006
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Implementation file for class Minuit2Minimizer
12 
14 
15 #include "Math/IFunction.h"
16 #include "Math/IOptions.h"
17 
18 #include "Fit/ParameterSettings.h"
19 
20 #include "Minuit2/FCNAdapter.h"
22 #include "Minuit2/FCNGradAdapter.h"
24 #include "Minuit2/MnMigrad.h"
25 #include "Minuit2/MnMinos.h"
26 #include "Minuit2/MinosError.h"
27 #include "Minuit2/MnHesse.h"
29 #include "Minuit2/MnUserFcn.h"
30 #include "Minuit2/MnPrint.h"
35 #include "Minuit2/ScanMinimizer.h"
38 #include "Minuit2/MnContours.h"
39 #include "Minuit2/MnTraceObject.h"
40 #include "Minuit2/MinimumBuilder.h"
41 
42 #include <cassert>
43 #include <iostream>
44 #include <algorithm>
45 #include <functional>
46 
47 #ifdef USE_ROOT_ERROR
48 #include "TROOT.h"
49 #include "TMinuit2TraceObject.h"
50 #endif
51 
52 namespace ROOT {
53 
54 namespace Minuit2 {
55 
56 
57  // functions needed to control siwthc off of Minuit2 printing level
58 #ifdef USE_ROOT_ERROR
59  int TurnOffPrintInfoLevel() {
60  // switch off Minuit2 printing of INFO message (cut off is 1001)
61  int prevErrorIgnoreLevel = gErrorIgnoreLevel;
62  if (prevErrorIgnoreLevel < 1001) {
63  gErrorIgnoreLevel = 1001;
64  return prevErrorIgnoreLevel;
65  }
66  return -2; // no op in this case
67 }
68 
69 void RestoreGlobalPrintLevel(int value) {
70  gErrorIgnoreLevel = value;
71 }
72 #else
73  // dummy functions
74  int TurnOffPrintInfoLevel() { return -1; }
75  int ControlPrintLevel( ) { return -1;}
76  void RestoreGlobalPrintLevel(int ) {}
77 #endif
78 
79 
80 
81 
82 Minuit2Minimizer::Minuit2Minimizer(ROOT::Minuit2::EMinimizerType type ) :
83  Minimizer(),
84  fDim(0),
85  fMinimizer(0),
86  fMinuitFCN(0),
87  fMinimum(0)
88 {
89  // Default constructor implementation depending on minimizer type
90  SetMinimizerType(type);
91 }
92 
93 Minuit2Minimizer::Minuit2Minimizer(const char * type ) :
94  Minimizer(),
95  fDim(0),
96  fMinimizer(0),
97  fMinuitFCN(0),
98  fMinimum(0)
99 {
100  // constructor from a string
101 
102  std::string algoname(type);
103  // tolower() is not an std function (Windows)
104  std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower );
105 
106  EMinimizerType algoType = kMigrad;
107  if (algoname == "simplex") algoType = kSimplex;
108  if (algoname == "minimize" ) algoType = kCombined;
109  if (algoname == "scan" ) algoType = kScan;
110  if (algoname == "fumili" ) algoType = kFumili;
111  if (algoname == "bfgs" ) algoType = kMigradBFGS;
112 
113  SetMinimizerType(algoType);
114 }
115 
116 void Minuit2Minimizer::SetMinimizerType(ROOT::Minuit2::EMinimizerType type) {
117  // Set minimizer algorithm type
118  fUseFumili = false;
119  switch (type) {
120  case ROOT::Minuit2::kMigrad:
121  //std::cout << "Minuit2Minimizer: minimize using MIGRAD " << std::endl;
122  SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer() );
123  return;
124  case ROOT::Minuit2::kMigradBFGS:
125  //std::cout << "Minuit2Minimizer: minimize using MIGRAD " << std::endl;
126  SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer(VariableMetricMinimizer::BFGSType()) );
127  return;
128  case ROOT::Minuit2::kSimplex:
129  //std::cout << "Minuit2Minimizer: minimize using SIMPLEX " << std::endl;
130  SetMinimizer( new ROOT::Minuit2::SimplexMinimizer() );
131  return;
132  case ROOT::Minuit2::kCombined:
133  SetMinimizer( new ROOT::Minuit2::CombinedMinimizer() );
134  return;
135  case ROOT::Minuit2::kScan:
136  SetMinimizer( new ROOT::Minuit2::ScanMinimizer() );
137  return;
138  case ROOT::Minuit2::kFumili:
139  SetMinimizer( new ROOT::Minuit2::FumiliMinimizer() );
140  fUseFumili = true;
141  return;
142  default:
143  //migrad minimizer
144  SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer() );
145 
146  }
147 }
148 
149 
150 Minuit2Minimizer::~Minuit2Minimizer()
151 {
152  // Destructor implementation.
153  if (fMinimizer) delete fMinimizer;
154  if (fMinuitFCN) delete fMinuitFCN;
155  if (fMinimum) delete fMinimum;
156 }
157 
158 Minuit2Minimizer::Minuit2Minimizer(const Minuit2Minimizer &) :
159  ROOT::Math::Minimizer()
160 {
161  // Implementation of copy constructor.
162 }
163 
164 Minuit2Minimizer & Minuit2Minimizer::operator = (const Minuit2Minimizer &rhs)
165 {
166  // Implementation of assignment operator.
167  if (this == &rhs) return *this; // time saving self-test
168  return *this;
169 }
170 
171 
172 void Minuit2Minimizer::Clear() {
173  // delete the state in case of consecutive minimizations
174  fState = MnUserParameterState();
175  // clear also the function minimum
176  if (fMinimum) delete fMinimum;
177  fMinimum = 0;
178 }
179 
180 
181 // set variables
182 
183 bool Minuit2Minimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) {
184  // set a free variable.
185  // Add the variable if not existing otherwise set value if exists already
186  // this is implemented in MnUserParameterState::Add
187  // if index is wrong (i.e. variable already exists but with a different index return false) but
188  // value is set for corresponding variable name
189 
190 // std::cout << " add parameter " << name << " " << val << " step " << step << std::endl;
191 
192  if (step <= 0) {
193  std::string txtmsg = "Parameter " + name + " has zero or invalid step size - consider it as constant ";
194  MN_INFO_MSG2("Minuit2Minimizer::SetVariable",txtmsg);
195  fState.Add(name.c_str(), val);
196  }
197  else
198  fState.Add(name.c_str(), val, step);
199 
200  unsigned int minuit2Index = fState.Index(name.c_str() );
201  if ( minuit2Index != ivar) {
202  std::string txtmsg("Wrong index used for the variable " + name);
203  MN_INFO_MSG2("Minuit2Minimizer::SetVariable",txtmsg);
204  MN_INFO_VAL2("Minuit2Minimizer::SetVariable",minuit2Index);
205  ivar = minuit2Index;
206  return false;
207  }
208  fState.RemoveLimits(ivar);
209 
210  return true;
211 }
212 
213 bool Minuit2Minimizer::SetLowerLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower ) {
214  // add a lower bounded variable
215  if (!SetVariable(ivar, name, val, step) ) return false;
216  fState.SetLowerLimit(ivar, lower);
217  return true;
218 }
219 
220 bool Minuit2Minimizer::SetUpperLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double upper ) {
221  // add a upper bounded variable
222  if (!SetVariable(ivar, name, val, step) ) return false;
223  fState.SetUpperLimit(ivar, upper);
224  return true;
225 }
226 
227 
228 
229 bool Minuit2Minimizer::SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower , double upper) {
230  // add a double bound variable
231  if (!SetVariable(ivar, name, val, step) ) return false;
232  fState.SetLimits(ivar, lower, upper);
233  return true;
234 }
235 
236 bool Minuit2Minimizer::SetFixedVariable(unsigned int ivar , const std::string & name , double val ) {
237  // add a fixed variable
238  // need a step size otherwise treated as a constant
239  // use 10%
240  double step = ( val != 0) ? 0.1 * std::abs(val) : 0.1;
241  if (!SetVariable(ivar, name, val, step ) ) {
242  ivar = fState.Index(name.c_str() );
243  }
244  fState.Fix(ivar);
245  return true;
246 }
247 
248 std::string Minuit2Minimizer::VariableName(unsigned int ivar) const {
249  // return the variable name
250  if (ivar >= fState.MinuitParameters().size() ) return std::string();
251  return fState.GetName(ivar);
252 }
253 
254 
255 int Minuit2Minimizer::VariableIndex(const std::string & name) const {
256  // return the variable index
257  // check if variable exist
258  return fState.Trafo().FindIndex(name);
259 }
260 
261 
262 bool Minuit2Minimizer::SetVariableValue(unsigned int ivar, double val) {
263  // set value for variable ivar (only for existing parameters)
264  if (ivar >= fState.MinuitParameters().size() ) return false;
265  fState.SetValue(ivar, val);
266  return true;
267 }
268 
269 bool Minuit2Minimizer::SetVariableValues(const double * x) {
270  // set value for variable ivar (only for existing parameters)
271  unsigned int n = fState.MinuitParameters().size();
272  if (n== 0) return false;
273  for (unsigned int ivar = 0; ivar < n; ++ivar)
274  fState.SetValue(ivar, x[ivar]);
275  return true;
276 }
277 
278 bool Minuit2Minimizer::SetVariableStepSize(unsigned int ivar, double step) {
279  // set the step-size of an existing variable
280  // parameter must exist or return false
281  if (ivar >= fState.MinuitParameters().size() ) return false;
282  fState.SetError(ivar, step);
283  return true;
284 }
285 
286 bool Minuit2Minimizer::SetVariableLowerLimit(unsigned int ivar, double lower) {
287  // set the limits of an existing variable
288  // parameter must exist or return false
289  if (ivar >= fState.MinuitParameters().size() ) return false;
290  fState.SetLowerLimit(ivar, lower);
291  return true;
292 }
293 bool Minuit2Minimizer::SetVariableUpperLimit(unsigned int ivar, double upper ) {
294  // set the limits of an existing variable
295  // parameter must exist or return false
296  if (ivar >= fState.MinuitParameters().size() ) return false;
297  fState.SetUpperLimit(ivar, upper);
298  return true;
299 }
300 
301 bool Minuit2Minimizer::SetVariableLimits(unsigned int ivar, double lower, double upper) {
302  // set the limits of an existing variable
303  // parameter must exist or return false
304  if (ivar >= fState.MinuitParameters().size() ) return false;
305  fState.SetLimits(ivar, lower,upper);
306  return true;
307 }
308 
309 bool Minuit2Minimizer::FixVariable(unsigned int ivar) {
310  // Fix an existing variable
311  if (ivar >= fState.MinuitParameters().size() ) return false;
312  fState.Fix(ivar);
313  return true;
314 }
315 
316 bool Minuit2Minimizer::ReleaseVariable(unsigned int ivar) {
317  // Release an existing variable
318  if (ivar >= fState.MinuitParameters().size() ) return false;
319  fState.Release(ivar);
320  return true;
321 }
322 
323 bool Minuit2Minimizer::IsFixedVariable(unsigned int ivar) const {
324  // query if variable is fixed
325  if (ivar >= fState.MinuitParameters().size() ) {
326  MN_ERROR_MSG2("Minuit2Minimizer","wrong variable index");
327  return false;
328  }
329  return (fState.Parameter(ivar).IsFixed() || fState.Parameter(ivar).IsConst() );
330 }
331 
332 bool Minuit2Minimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & varObj) const {
333  // retrieve variable settings (all set info on the variable)
334  if (ivar >= fState.MinuitParameters().size() ) {
335  MN_ERROR_MSG2("Minuit2Minimizer","wrong variable index");
336  return false;
337  }
338  const MinuitParameter & par = fState.Parameter(ivar);
339  varObj.Set( par.Name(), par.Value(), par.Error() );
340  if (par.HasLowerLimit() ) {
341  if (par.HasUpperLimit() ) {
342  varObj.SetLimits(par.LowerLimit(), par.UpperLimit() );
343  } else {
344  varObj.SetLowerLimit(par.LowerLimit() );
345  }
346  } else if (par.HasUpperLimit() ) {
347  varObj.SetUpperLimit(par.UpperLimit() );
348  }
349  if (par.IsConst() || par.IsFixed() ) varObj.Fix();
350  return true;
351 }
352 
353 
354 
355 void Minuit2Minimizer::SetFunction(const ROOT::Math::IMultiGenFunction & func) {
356  // set function to be minimized
357  if (fMinuitFCN) delete fMinuitFCN;
358  fDim = func.NDim();
359  if (!fUseFumili) {
360  fMinuitFCN = new ROOT::Minuit2::FCNAdapter<ROOT::Math::IMultiGenFunction> (func, ErrorDef() );
361  }
362  else {
363  // for Fumili the fit method function interface is required
364  const ROOT::Math::FitMethodFunction * fcnfunc = dynamic_cast<const ROOT::Math::FitMethodFunction *>(&func);
365  if (!fcnfunc) {
366  MN_ERROR_MSG("Minuit2Minimizer: Wrong Fit method function for Fumili");
367  return;
368  }
369  fMinuitFCN = new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodFunction> (*fcnfunc, fDim, ErrorDef() );
370  }
371 }
372 
373 void Minuit2Minimizer::SetFunction(const ROOT::Math::IMultiGradFunction & func) {
374  // set function to be minimized
375  fDim = func.NDim();
376  if (fMinuitFCN) delete fMinuitFCN;
377  if (!fUseFumili) {
378  fMinuitFCN = new ROOT::Minuit2::FCNGradAdapter<ROOT::Math::IMultiGradFunction> (func, ErrorDef() );
379  }
380  else {
381  // for Fumili the fit method function interface is required
382  const ROOT::Math::FitMethodGradFunction * fcnfunc = dynamic_cast<const ROOT::Math::FitMethodGradFunction*>(&func);
383  if (!fcnfunc) {
384  MN_ERROR_MSG("Minuit2Minimizer: Wrong Fit method function for Fumili");
385  return;
386  }
387  fMinuitFCN = new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodGradFunction> (*fcnfunc, fDim, ErrorDef() );
388  }
389 }
390 
391 bool Minuit2Minimizer::Minimize() {
392  // perform the minimization
393  // store a copy of FunctionMinimum
394  if (!fMinuitFCN) {
395  MN_ERROR_MSG2("Minuit2Minimizer::Minimize","FCN function has not been set");
396  return false;
397  }
398 
399  assert(GetMinimizer() != 0 );
400 
401  // delete result of previous minimization
402  if (fMinimum) delete fMinimum;
403  fMinimum = 0;
404 
405 
406  int maxfcn = MaxFunctionCalls();
407  double tol = Tolerance();
408  int strategyLevel = Strategy();
409  fMinuitFCN->SetErrorDef(ErrorDef() );
410 
411  int printLevel = PrintLevel();
412  if (printLevel >=1) {
413  // print the real number of maxfcn used (defined in ModularFuncitonMinimizer)
414  int maxfcn_used = maxfcn;
415  if (maxfcn_used == 0) {
416  int nvar = fState.VariableParameters();
417  maxfcn_used = 200 + 100*nvar + 5*nvar*nvar;
418  }
419  std::cout << "Minuit2Minimizer: Minimize with max-calls " << maxfcn_used
420  << " convergence for edm < " << tol << " strategy "
421  << strategyLevel << std::endl;
422  }
423 
424  // internal minuit messages
425  MnPrint::SetLevel(printLevel );
426  fMinimizer->Builder().SetPrintLevel(printLevel);
427 
428  // switch off Minuit2 printing
429  int prev_level = (printLevel <= 0 ) ? TurnOffPrintInfoLevel() : -2;
430 
431  // set the precision if needed
432  if (Precision() > 0) fState.SetPrecision(Precision());
433 
434  // set strategy and add extra options if needed
435  ROOT::Minuit2::MnStrategy strategy(strategyLevel);
436  ROOT::Math::IOptions * minuit2Opt = ROOT::Math::MinimizerOptions::FindDefault("Minuit2");
437  if (minuit2Opt) {
438  // set extra options
439  int nGradCycles = strategy.GradientNCycles();
440  int nHessCycles = strategy.HessianNCycles();
441  int nHessGradCycles = strategy.HessianGradientNCycles();
442 
443  double gradTol = strategy.GradientTolerance();
444  double gradStepTol = strategy.GradientStepTolerance();
445  double hessStepTol = strategy.HessianStepTolerance();
446  double hessG2Tol = strategy.HessianG2Tolerance();
447 
448  minuit2Opt->GetValue("GradientNCycles",nGradCycles);
449  minuit2Opt->GetValue("HessianNCycles",nHessCycles);
450  minuit2Opt->GetValue("HessianGradientNCycles",nHessGradCycles);
451 
452  minuit2Opt->GetValue("GradientTolerance",gradTol);
453  minuit2Opt->GetValue("GradientStepTolerance",gradStepTol);
454  minuit2Opt->GetValue("HessianStepTolerance",hessStepTol);
455  minuit2Opt->GetValue("HessianG2Tolerance",hessG2Tol);
456 
457  strategy.SetGradientNCycles(nGradCycles);
458  strategy.SetHessianNCycles(nHessCycles);
459  strategy.SetHessianGradientNCycles(nHessGradCycles);
460 
461  strategy.SetGradientTolerance(gradTol);
462  strategy.SetGradientStepTolerance(gradStepTol);
463  strategy.SetHessianStepTolerance(hessStepTol);
464  strategy.SetHessianG2Tolerance(hessStepTol);
465 
466  int storageLevel = 1;
467  bool ret = minuit2Opt->GetValue("StorageLevel",storageLevel);
468  if (ret) SetStorageLevel(storageLevel);
469 
470  if (printLevel > 0) {
471  std::cout << "Minuit2Minimizer::Minuit - Changing default options" << std::endl;
472  minuit2Opt->Print();
473  }
474 
475 
476  }
477 
478  // set a minimizer tracer object (default for printlevel=10, from gROOT for printLevel=11)
479  // use some special print levels
480  MnTraceObject * traceObj = 0;
481 #ifdef USE_ROOT_ERROR
482  if (printLevel == 10 && gROOT) {
483  TObject * obj = gROOT->FindObject("Minuit2TraceObject");
484  traceObj = dynamic_cast<ROOT::Minuit2::MnTraceObject*>(obj);
485  if (traceObj) {
486  // need to remove from the list
487  gROOT->Remove(obj);
488  }
489  }
490  if (printLevel == 20 || printLevel == 30 || printLevel == 40 || (printLevel >= 20000 && printLevel < 30000) ) {
491  int parNumber = printLevel-20000;
492  if (printLevel == 20) parNumber = -1;
493  if (printLevel == 30) parNumber = -2;
494  if (printLevel == 40) parNumber = 0;
495  traceObj = new TMinuit2TraceObject(parNumber);
496  }
497 #endif
498  if (printLevel == 100 || (printLevel >= 10000 && printLevel < 20000)) {
499  int parNumber = printLevel-10000;
500  traceObj = new MnTraceObject(parNumber);
501  }
502  if (traceObj) {
503  traceObj->Init(fState);
504  SetTraceObject(*traceObj);
505  }
506 
507  const ROOT::Minuit2::FCNGradientBase * gradFCN = dynamic_cast<const ROOT::Minuit2::FCNGradientBase *>( fMinuitFCN );
508  if ( gradFCN != 0) {
509  // use gradient
510  //SetPrintLevel(3);
511  ROOT::Minuit2::FunctionMinimum min = GetMinimizer()->Minimize(*gradFCN, fState, strategy, maxfcn, tol);
512  fMinimum = new ROOT::Minuit2::FunctionMinimum (min);
513  }
514  else {
515  ROOT::Minuit2::FunctionMinimum min = GetMinimizer()->Minimize(*GetFCN(), fState, strategy, maxfcn, tol);
516  fMinimum = new ROOT::Minuit2::FunctionMinimum (min);
517  }
518 
519  // check if Hesse needs to be run
520  if (fMinimum->IsValid() && IsValidError() && fMinimum->State().Error().Dcovar() != 0 ) {
521  // run Hesse (Hesse will add results in the last state of fMinimum
522  ROOT::Minuit2::MnHesse hesse(strategy );
523  hesse( *fMinuitFCN, *fMinimum, maxfcn);
524  }
525 
526  // -2 is the highest low invalid value for gErrorIgnoreLevel
527  if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
528 
529  fState = fMinimum->UserState();
530  bool ok = ExamineMinimum(*fMinimum);
531  //fMinimum = 0;
532 
533  // delete trace object if it was constructed
534  if (traceObj) { delete traceObj; }
535  return ok;
536 }
537 
538 bool Minuit2Minimizer::ExamineMinimum(const ROOT::Minuit2::FunctionMinimum & min) {
539  /// study the function minimum
540 
541  // debug ( print all the states)
542  int debugLevel = PrintLevel();
543  if (debugLevel >= 3) {
544 
545  const std::vector<ROOT::Minuit2::MinimumState>& iterationStates = min.States();
546  std::cout << "Number of iterations " << iterationStates.size() << std::endl;
547  for (unsigned int i = 0; i < iterationStates.size(); ++i) {
548  //std::cout << iterationStates[i] << std::endl;
549  const ROOT::Minuit2::MinimumState & st = iterationStates[i];
550  std::cout << "----------> Iteration " << i << std::endl;
551  int pr = std::cout.precision(12);
552  std::cout << " FVAL = " << st.Fval() << " Edm = " << st.Edm() << " Nfcn = " << st.NFcn() << std::endl;
553  std::cout.precision(pr);
554  if (st.HasCovariance() )
555  std::cout << " Error matrix change = " << st.Error().Dcovar() << std::endl;
556  if (st.HasParameters() ) {
557  std::cout << " Parameters : ";
558  // need to transform from internal to external
559  for (int j = 0; j < st.size() ; ++j) std::cout << " p" << j << " = " << fState.Int2ext( j, st.Vec()(j) );
560  std::cout << std::endl;
561  }
562  }
563  }
564 
565  fStatus = 0;
566  std::string txt;
567  if (!min.HasPosDefCovar() ) {
568  // this happens normally when Hesse failed
569  // it can happen in case MnSeed failed (see ROOT-9522)
570  txt = "Covar is not pos def";
571  fStatus = 5;
572  }
573  if (min.HasMadePosDefCovar() ) {
574  txt = "Covar was made pos def";
575  fStatus = 1;
576  }
577  if (min.HesseFailed() ) {
578  txt = "Hesse is not valid";
579  fStatus = 2;
580  }
581  if (min.IsAboveMaxEdm() ) {
582  txt = "Edm is above max";
583  fStatus = 3;
584  }
585  if (min.HasReachedCallLimit() ) {
586  txt = "Reached call limit";
587  fStatus = 4;
588  }
589 
590 
591  bool validMinimum = min.IsValid();
592  if (validMinimum) {
593  // print a warning message in case something is not ok
594  if (fStatus != 0 && debugLevel > 0) MN_INFO_MSG2("Minuit2Minimizer::Minimize",txt);
595  }
596  else {
597  // minimum is not valid when state is not valid and edm is over max or has passed call limits
598  if (fStatus == 0) {
599  // this should not happen
600  txt = "unknown failure";
601  fStatus = 6;
602  }
603  std::string msg = "Minimization did NOT converge, " + txt;
604  MN_INFO_MSG2("Minuit2Minimizer::Minimize",msg);
605  }
606 
607  if (debugLevel >= 1) PrintResults();
608  return validMinimum;
609 }
610 
611 
612 void Minuit2Minimizer::PrintResults() {
613  // print results of minimization
614  if (!fMinimum) return;
615  if (fMinimum->IsValid() ) {
616  // valid minimum
617  std::cout << "Minuit2Minimizer : Valid minimum - status = " << fStatus << std::endl;
618  int pr = std::cout.precision(18);
619  std::cout << "FVAL = " << fState.Fval() << std::endl;
620  std::cout << "Edm = " << fState.Edm() << std::endl;
621  std::cout.precision(pr);
622  std::cout << "Nfcn = " << fState.NFcn() << std::endl;
623  for (unsigned int i = 0; i < fState.MinuitParameters().size(); ++i) {
624  const MinuitParameter & par = fState.Parameter(i);
625  std::cout << par.Name() << "\t = " << par.Value() << "\t ";
626  if (par.IsFixed() ) std::cout << "(fixed)" << std::endl;
627  else if (par.IsConst() ) std::cout << "(const)" << std::endl;
628  else if (par.HasLimits() )
629  std::cout << "+/- " << par.Error() << "\t(limited)"<< std::endl;
630  else
631  std::cout << "+/- " << par.Error() << std::endl;
632  }
633  }
634  else {
635  std::cout << "Minuit2Minimizer : Invalid Minimum - status = " << fStatus << std::endl;
636  std::cout << "FVAL = " << fState.Fval() << std::endl;
637  std::cout << "Edm = " << fState.Edm() << std::endl;
638  std::cout << "Nfcn = " << fState.NFcn() << std::endl;
639  }
640 }
641 
642 const double * Minuit2Minimizer::X() const {
643  // return values at minimum
644  const std::vector<MinuitParameter> & paramsObj = fState.MinuitParameters();
645  if (paramsObj.size() == 0) return 0;
646  assert(fDim == paramsObj.size());
647  // be careful for multiple calls of this function. I will redo an allocation here
648  // only when size of vectors has changed (e.g. after a new minimization)
649  if (fValues.size() != fDim) fValues.resize(fDim);
650  for (unsigned int i = 0; i < fDim; ++i) {
651  fValues[i] = paramsObj[i].Value();
652  }
653 
654  return &fValues.front();
655 }
656 
657 
658 const double * Minuit2Minimizer::Errors() const {
659  // return error at minimum (set to zero for fixed and constant params)
660  const std::vector<MinuitParameter> & paramsObj = fState.MinuitParameters();
661  if (paramsObj.size() == 0) return 0;
662  assert(fDim == paramsObj.size());
663  // be careful for multiple calls of this function. I will redo an allocation here
664  // only when size of vectors has changed (e.g. after a new minimization)
665  if (fErrors.size() != fDim) fErrors.resize( fDim );
666  for (unsigned int i = 0; i < fDim; ++i) {
667  const MinuitParameter & par = paramsObj[i];
668  if (par.IsFixed() || par.IsConst() )
669  fErrors[i] = 0;
670  else
671  fErrors[i] = par.Error();
672  }
673 
674  return &fErrors.front();
675 }
676 
677 
678 double Minuit2Minimizer::CovMatrix(unsigned int i, unsigned int j) const {
679  // get value of covariance matrices (transform from external to internal indices)
680  if ( i >= fDim || j >= fDim) return 0;
681  if ( !fState.HasCovariance() ) return 0; // no info available when minimization has failed
682  if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) return 0;
683  if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst() ) return 0;
684  unsigned int k = fState.IntOfExt(i);
685  unsigned int l = fState.IntOfExt(j);
686  return fState.Covariance()(k,l);
687 }
688 
689 bool Minuit2Minimizer::GetCovMatrix(double * cov) const {
690  // get value of covariance matrices
691  if ( !fState.HasCovariance() ) return false; // no info available when minimization has failed
692  for (unsigned int i = 0; i < fDim; ++i) {
693  if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) {
694  for (unsigned int j = 0; j < fDim; ++j) { cov[i*fDim + j] = 0; }
695  }
696  else
697  {
698  unsigned int l = fState.IntOfExt(i);
699  for (unsigned int j = 0; j < fDim; ++j) {
700  // could probably speed up this loop (if needed)
701  int k = i*fDim + j;
702  if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst() )
703  cov[k] = 0;
704  else {
705  // need to transform from external to internal indices)
706  // for taking care of the removed fixed row/columns in the Minuit2 representation
707  unsigned int m = fState.IntOfExt(j);
708  cov[k] = fState.Covariance()(l,m);
709  }
710  }
711  }
712  }
713  return true;
714 }
715 
716 bool Minuit2Minimizer::GetHessianMatrix(double * hess) const {
717  // get value of Hessian matrix
718  // this is the second derivative matrices
719  if ( !fState.HasCovariance() ) return false; // no info available when minimization has failed
720  for (unsigned int i = 0; i < fDim; ++i) {
721  if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) {
722  for (unsigned int j = 0; j < fDim; ++j) { hess[i*fDim + j] = 0; }
723  }
724  else {
725  unsigned int l = fState.IntOfExt(i);
726  for (unsigned int j = 0; j < fDim; ++j) {
727  // could probably speed up this loop (if needed)
728  int k = i*fDim + j;
729  if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst() )
730  hess[k] = 0;
731  else {
732  // need to transform from external to internal indices)
733  // for taking care of the removed fixed row/columns in the Minuit2 representation
734  unsigned int m = fState.IntOfExt(j);
735  hess[k] = fState.Hessian()(l,m);
736  }
737  }
738  }
739  }
740 
741  return true;
742 }
743 
744 
745 double Minuit2Minimizer::Correlation(unsigned int i, unsigned int j) const {
746  // get correlation between parameter i and j
747  if ( i >= fDim || j >= fDim) return 0;
748  if ( !fState.HasCovariance() ) return 0; // no info available when minimization has failed
749  if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) return 0;
750  if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst() ) return 0;
751  unsigned int k = fState.IntOfExt(i);
752  unsigned int l = fState.IntOfExt(j);
753  double cij = fState.IntCovariance()(k,l);
754  double tmp = std::sqrt( std::abs ( fState.IntCovariance()(k,k) * fState.IntCovariance()(l,l) ) );
755  if (tmp > 0 ) return cij/tmp;
756  return 0;
757 }
758 
759 double Minuit2Minimizer::GlobalCC(unsigned int i) const {
760  // get global correlation coefficient for the parameter i. This is a number between zero and one which gives
761  // the correlation between the i-th parameter and that linear combination of all other parameters which
762  // is most strongly correlated with i.
763 
764  if ( i >= fDim ) return 0;
765  // no info available when minimization has failed or has some problems
766  if ( !fState.HasGlobalCC() ) return 0;
767  if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) return 0;
768  unsigned int k = fState.IntOfExt(i);
769  return fState.GlobalCC().GlobalCC()[k];
770 }
771 
772 
773 bool Minuit2Minimizer::GetMinosError(unsigned int i, double & errLow, double & errUp, int runopt) {
774  // return the minos error for parameter i
775  // if a minimum does not exist an error is returned
776  // runopt is a flag which specifies if only lower or upper error needs to be run
777  // if runopt = 0 both, = 1 only lower, + 2 only upper errors
778  errLow = 0; errUp = 0;
779  bool runLower = runopt != 2;
780  bool runUpper = runopt != 1;
781 
782  assert( fMinuitFCN );
783 
784  // need to know if parameter is const or fixed
785  if ( fState.Parameter(i).IsConst() || fState.Parameter(i).IsFixed() ) {
786  return false;
787  }
788 
789  int debugLevel = PrintLevel();
790  // internal minuit messages
791  MnPrint::SetLevel( debugLevel );
792 
793  // to run minos I need function minimum class
794  // redo minimization from current state
795 // ROOT::Minuit2::FunctionMinimum min =
796 // GetMinimizer()->Minimize(*GetFCN(),fState, ROOT::Minuit2::MnStrategy(strategy), MaxFunctionCalls(), Tolerance());
797 // fState = min.UserState();
798  if (fMinimum == 0) {
799  MN_ERROR_MSG("Minuit2Minimizer::GetMinosErrors: failed - no function minimum existing");
800  return false;
801  }
802 
803  if (!fMinimum->IsValid() ) {
804  MN_ERROR_MSG("Minuit2Minimizer::MINOS failed due to invalid function minimum");
805  return false;
806  }
807 
808  fMinuitFCN->SetErrorDef(ErrorDef() );
809  // if error def has been changed update it in FunctionMinimum
810  if (ErrorDef() != fMinimum->Up() )
811  fMinimum->SetErrorDef(ErrorDef() );
812 
813  // switch off Minuit2 printing
814  int prev_level = (PrintLevel() <= 0 ) ? TurnOffPrintInfoLevel() : -2;
815 
816  // set the precision if needed
817  if (Precision() > 0) fState.SetPrecision(Precision());
818 
819 
820  ROOT::Minuit2::MnMinos minos( *fMinuitFCN, *fMinimum);
821 
822  // run MnCross
823  MnCross low;
824  MnCross up;
825  int maxfcn = MaxFunctionCalls();
826  double tol = Tolerance();
827 
828  const char * par_name = fState.Name(i);
829 
830  // now input tolerance for migrad calls inside Minos (MnFunctionCross)
831  // before it was fixed to 0.05
832  // cut off too small tolerance (they are not needed)
833  tol = std::max(tol, 0.01);
834 
835  if (PrintLevel() >=1) {
836  // print the real number of maxfcn used (defined in MnMinos)
837  int maxfcn_used = maxfcn;
838  if (maxfcn_used == 0) {
839  int nvar = fState.VariableParameters();
840  maxfcn_used = 2*(nvar+1)*(200 + 100*nvar + 5*nvar*nvar);
841  }
842  std::cout << "Minuit2Minimizer::GetMinosError for parameter " << i << " " << par_name
843  << " using max-calls " << maxfcn_used << ", tolerance " << tol << std::endl;
844  }
845 
846 
847  if (runLower) low = minos.Loval(i,maxfcn,tol);
848  if (runUpper) up = minos.Upval(i,maxfcn,tol);
849 
850  ROOT::Minuit2::MinosError me(i, fMinimum->UserState().Value(i),low, up);
851 
852  if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
853 
854  // debug result of Minos
855  // print error message in Minos
856  // Note that the only invalid condition can happen when the (npar-1) minimization fails
857  // The error is also invalid when the maximum number of calls is reached or a new function minimum is found
858  // in case of the parameter at the limit the error is not ivalid.
859  // When the error is invalid the returned error is the Hessian error.
860 
861  if (debugLevel >= 1) {
862  if (runLower) {
863  if (!me.LowerValid() )
864  std::cout << "Minos: Invalid lower error for parameter " << par_name << std::endl;
865  if(me.AtLowerLimit())
866  std::cout << "Minos: Parameter : " << par_name << " is at Lower limit."<<std::endl;
867  if(me.AtLowerMaxFcn())
868  std::cout << "Minos: Maximum number of function calls exceeded when running for lower error" <<std::endl;
869  if(me.LowerNewMin() )
870  std::cout << "Minos: New Minimum found while running Minos for lower error" <<std::endl;
871 
872  if (debugLevel > 1) std::cout << "Minos: Lower error for parameter " << par_name << " : " << me.Lower() << std::endl;
873 
874  }
875  if (runUpper) {
876  if (!me.UpperValid() )
877  std::cout << "Minos: Invalid upper error for parameter " << par_name << std::endl;
878  if(me.AtUpperLimit())
879  std::cout << "Minos: Parameter " << par_name << " is at Upper limit."<<std::endl;
880  if(me.AtUpperMaxFcn())
881  std::cout << "Minos: Maximum number of function calls exceeded when running for upper error" <<std::endl;
882  if(me.UpperNewMin() )
883  std::cout << "Minos: New Minimum found while running Minos for upper error" <<std::endl;
884 
885  if (debugLevel > 1) std::cout << "Minos: Upper error for parameter " << par_name << " : " << me.Upper() << std::endl;
886  }
887 
888  }
889 
890  bool lowerInvalid = (runLower && !me.LowerValid() );
891  bool upperInvalid = (runUpper && !me.UpperValid() );
892  int mstatus = 0;
893  if (lowerInvalid || upperInvalid ) {
894  // set status accroding to bit
895  // bit 1: lower invalid Minos errors
896  // bit 2: uper invalid Minos error
897  // bit 3: invalid because max FCN
898  // bit 4 : invalid because a new minimum has been found
899  if (lowerInvalid) {
900  mstatus |= 1;
901  if (me.AtLowerMaxFcn() ) mstatus |= 4;
902  if (me.LowerNewMin() ) mstatus |= 8;
903  }
904  if(upperInvalid) {
905  mstatus |= 3;
906  if (me.AtUpperMaxFcn() ) mstatus |= 4;
907  if (me.UpperNewMin() ) mstatus |= 8;
908  }
909  //std::cout << "Error running Minos for parameter " << i << std::endl;
910  fStatus += 10*mstatus;
911  }
912 
913  errLow = me.Lower();
914  errUp = me.Upper();
915 
916  bool isValid = (runLower && me.LowerValid() ) || (runUpper && me.UpperValid() );
917  return isValid;
918 }
919 
920 bool Minuit2Minimizer::Scan(unsigned int ipar, unsigned int & nstep, double * x, double * y, double xmin, double xmax) {
921  // scan a parameter (variable) around the minimum value
922  // the parameters must have been set before
923  // if xmin=0 && xmax == 0 by default scan around 2 sigma of the error
924  // if the errors are also zero then scan from min and max of parameter range
925 
926  if (!fMinuitFCN) {
927  MN_ERROR_MSG2("Minuit2Minimizer::Scan"," Function must be set before using Scan");
928  return false;
929  }
930 
931  if ( ipar > fState.MinuitParameters().size() ) {
932  MN_ERROR_MSG2("Minuit2Minimizer::Scan"," Invalid number. Minimizer variables must be set before using Scan");
933  return false;
934  }
935 
936  // switch off Minuit2 printing
937  int prev_level = (PrintLevel() <= 0 ) ? TurnOffPrintInfoLevel() : -2;
938 
939  MnPrint::SetLevel( PrintLevel() );
940 
941 
942  // set the precision if needed
943  if (Precision() > 0) fState.SetPrecision(Precision());
944 
945  MnParameterScan scan( *fMinuitFCN, fState.Parameters() );
946  double amin = scan.Fval(); // fcn value of the function before scan
947 
948  // first value is param value
949  std::vector<std::pair<double, double> > result = scan(ipar, nstep-1, xmin, xmax);
950 
951  if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
952 
953  if (result.size() != nstep) {
954  MN_ERROR_MSG2("Minuit2Minimizer::Scan"," Invalid result from MnParameterScan");
955  return false;
956  }
957  // sort also the returned points in x
958  std::sort(result.begin(), result.end() );
959 
960 
961  for (unsigned int i = 0; i < nstep; ++i ) {
962  x[i] = result[i].first;
963  y[i] = result[i].second;
964  }
965 
966  // what to do if a new minimum has been found ?
967  // use that as new minimum
968  if (scan.Fval() < amin ) {
969  MN_INFO_MSG2("Minuit2Minimizer::Scan","A new minimum has been found");
970  fState.SetValue(ipar, scan.Parameters().Value(ipar) );
971 
972  }
973 
974 
975  return true;
976 }
977 
978 bool Minuit2Minimizer::Contour(unsigned int ipar, unsigned int jpar, unsigned int & npoints, double * x, double * y) {
979  // contour plot for parameter i and j
980  // need a valid FunctionMinimum otherwise exits
981  if (fMinimum == 0) {
982  MN_ERROR_MSG2("Minuit2Minimizer::Contour"," no function minimum existing. Must minimize function before");
983  return false;
984  }
985 
986  if (!fMinimum->IsValid() ) {
987  MN_ERROR_MSG2("Minuit2Minimizer::Contour","Invalid function minimum");
988  return false;
989  }
990  assert(fMinuitFCN);
991 
992  fMinuitFCN->SetErrorDef(ErrorDef() );
993  // if error def has been changed update it in FunctionMinimum
994  if (ErrorDef() != fMinimum->Up() ) {
995  fMinimum->SetErrorDef(ErrorDef() );
996  }
997 
998  if ( PrintLevel() >= 1 )
999  MN_INFO_VAL2("Minuit2Minimizer::Contour - computing contours - ",ErrorDef());
1000 
1001  // switch off Minuit2 printing (for level of 0,1)
1002  int prev_level = (PrintLevel() <= 1 ) ? TurnOffPrintInfoLevel() : -2;
1003 
1004  // decrease print-level to have too many messages
1005  MnPrint::SetLevel( PrintLevel() -1 );
1006 
1007  // set the precision if needed
1008  if (Precision() > 0) fState.SetPrecision(Precision());
1009 
1010  // eventually one should specify tolerance in contours
1011  MnContours contour(*fMinuitFCN, *fMinimum, Strategy() );
1012 
1013  if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
1014 
1015  // compute the contour
1016  std::vector<std::pair<double,double> > result = contour(ipar,jpar, npoints);
1017  if (result.size() != npoints) {
1018  MN_ERROR_MSG2("Minuit2Minimizer::Contour"," Invalid result from MnContours");
1019  return false;
1020  }
1021  for (unsigned int i = 0; i < npoints; ++i ) {
1022  x[i] = result[i].first;
1023  y[i] = result[i].second;
1024  }
1025 
1026  // restore print level
1027  MnPrint::SetLevel( PrintLevel() );
1028 
1029 
1030  return true;
1031 
1032 
1033 }
1034 
1035 bool Minuit2Minimizer::Hesse( ) {
1036  // find Hessian (full second derivative calculations)
1037  // the contained state will be updated with the Hessian result
1038  // in case a function minimum exists and is valid the result will be
1039  // appended in the function minimum
1040 
1041  if (!fMinuitFCN) {
1042  MN_ERROR_MSG2("Minuit2Minimizer::Hesse","FCN function has not been set");
1043  return false;
1044  }
1045 
1046  int strategy = Strategy();
1047  int maxfcn = MaxFunctionCalls();
1048 
1049  // switch off Minuit2 printing
1050  int prev_level = (PrintLevel() <= 0 ) ? TurnOffPrintInfoLevel() : -2;
1051 
1052  MnPrint::SetLevel( PrintLevel() );
1053 
1054  // set the precision if needed
1055  if (Precision() > 0) fState.SetPrecision(Precision());
1056 
1057  ROOT::Minuit2::MnHesse hesse( strategy );
1058 
1059  if (PrintLevel() >= 1)
1060  std::cout << "Minuit2Minimizer::Hesse using max-calls " << maxfcn << std::endl;
1061 
1062  // case when function minimum exists
1063  if (fMinimum) {
1064 
1065  // if (PrintLevel() >= 3) {
1066  // std::cout << "Minuit2Minimizer::Hesse - State before running Hesse " << std::endl;
1067  // std::cout << fState << std::endl;
1068  // }
1069 
1070  // run hesse and function minimum will be updated with Hesse result
1071  hesse( *fMinuitFCN, *fMinimum, maxfcn );
1072  // update user state
1073  fState = fMinimum->UserState();
1074  }
1075 
1076  else {
1077  // run Hesse on point stored in current state (independent of function minimum validity)
1078  // (x == 0)
1079  fState = hesse( *fMinuitFCN, fState, maxfcn);
1080  }
1081 
1082  if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
1083 
1084  if (PrintLevel() >= 3) {
1085  std::cout << "Minuit2Minimizer::Hesse - State returned from Hesse " << std::endl;
1086  std::cout << fState << std::endl;
1087  }
1088 
1089  int covStatus = fState.CovarianceStatus();
1090  std::string covStatusType = "not valid";
1091  if (covStatus == 1) covStatusType = "approximate";
1092  if (covStatus == 2) covStatusType = "full but made positive defined";
1093  if (covStatus == 3) covStatusType = "accurate";
1094 
1095  if (!fState.HasCovariance() ) {
1096  // if false means error is not valid and this is due to a failure in Hesse
1097  // update minimizer error status
1098  int hstatus = 4;
1099  // information on error state can be retrieved only if fMinimum is available
1100  if (fMinimum) {
1101  if (fMinimum->Error().HesseFailed() ) hstatus = 1;
1102  if (fMinimum->Error().InvertFailed() ) hstatus = 2;
1103  else if (!(fMinimum->Error().IsPosDef()) ) hstatus = 3;
1104  }
1105  if (PrintLevel() > 0) {
1106  std::string msg = "Hesse failed - matrix is " + covStatusType;
1107  MN_INFO_MSG2("Minuit2Minimizer::Hesse",msg);
1108  MN_INFO_VAL2("MInuit2Minimizer::Hesse",hstatus);
1109  }
1110  fStatus += 100*hstatus;
1111  return false;
1112  }
1113  if (PrintLevel() > 0) {
1114  std::string msg = "Hesse is valid - matrix is " + covStatusType;
1115  MN_INFO_MSG2("Minuit2Minimizer::Hesse",msg);
1116  }
1117 
1118  return true;
1119 }
1120 
1121 int Minuit2Minimizer::CovMatrixStatus() const {
1122  // return status of covariance matrix
1123  //-1 - not available (inversion failed or Hesse failed)
1124  // 0 - available but not positive defined
1125  // 1 - covariance only approximate
1126  // 2 full matrix but forced pos def
1127  // 3 full accurate matrix
1128 
1129  if (fMinimum) {
1130  // case a function minimum is available
1131  if (fMinimum->HasAccurateCovar() ) return 3;
1132  else if (fMinimum->HasMadePosDefCovar() ) return 2;
1133  else if (fMinimum->HasValidCovariance() ) return 1;
1134  else if (fMinimum->HasCovariance() ) return 0;
1135  return -1;
1136  }
1137  else {
1138  // case fMinimum is not available - use state information
1139  return fState.CovarianceStatus();
1140  }
1141  return 0;
1142 }
1143 
1144 void Minuit2Minimizer::SetTraceObject(MnTraceObject & obj) {
1145  // set trace object
1146  if (!fMinimizer) return;
1147  fMinimizer->Builder().SetTraceObject(obj);
1148 }
1149 
1150 void Minuit2Minimizer::SetStorageLevel(int level) {
1151  // set storage level
1152  if (!fMinimizer) return;
1153  fMinimizer->Builder().SetStorageLevel(level);
1154  }
1155 
1156 } // end namespace Minuit2
1157 
1158 } // end namespace ROOT