Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
19
20#include "Minuit2/FCNAdapter.h"
23#include "Minuit2/MnMigrad.h"
24#include "Minuit2/MnMinos.h"
25#include "Minuit2/MinosError.h"
26#include "Minuit2/MnHesse.h"
28#include "Minuit2/MnPrint.h"
35#include "Minuit2/MnContours.h"
38
39#include <cassert>
40#include <iostream>
41#include <algorithm>
42#include <functional>
43
44#ifdef USE_ROOT_ERROR
45#include "TError.h"
46#include "TROOT.h"
47#include "TMinuit2TraceObject.h"
48#endif
49
50namespace ROOT {
51
52namespace Minuit2 {
53
54// functions needed to control siwthc off of Minuit2 printing level
55#ifdef USE_ROOT_ERROR
57{
58 // switch off Minuit2 printing of INFO message (cut off is 1001)
60 if (prevErrorIgnoreLevel < 1001) {
61 gErrorIgnoreLevel = 1001;
63 }
64 return -2; // no op in this case
65}
66
68{
70}
71#else
72// dummy functions
74{
75 return -1;
76}
78{
79 return -1;
80}
82#endif
83
85{
86 // Default constructor implementation depending on minimizer type
88}
89
91{
92 // constructor from a string
93
94 std::string algoname(type);
95 // tolower() is not an std function (Windows)
96 std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int (*)(int))tolower);
97
99 if (algoname == "simplex")
101 if (algoname == "minimize")
103 if (algoname == "scan")
104 algoType = kScan;
105 if (algoname == "fumili" || algoname == "fumili2")
107 if (algoname == "bfgs")
109
111}
112
114{
115 // Set minimizer algorithm type
116 fUseFumili = false;
117 switch (type) {
118 case ROOT::Minuit2::kMigrad: fMinimizer = std::make_unique<ROOT::Minuit2::VariableMetricMinimizer>(); return;
120 fMinimizer = std::make_unique<ROOT::Minuit2::VariableMetricMinimizer>(VariableMetricMinimizer::BFGSType());
121 return;
122 case ROOT::Minuit2::kSimplex: fMinimizer = std::make_unique<ROOT::Minuit2::SimplexMinimizer>(); return;
123 case ROOT::Minuit2::kCombined: fMinimizer = std::make_unique<ROOT::Minuit2::CombinedMinimizer>(); return;
124 case ROOT::Minuit2::kScan: fMinimizer = std::make_unique<ROOT::Minuit2::ScanMinimizer>(); return;
126 fMinimizer = std::make_unique<ROOT::Minuit2::FumiliMinimizer>();
127 fUseFumili = true;
128 return;
129 default:
130 // migrad minimizer
131 fMinimizer = std::make_unique<ROOT::Minuit2::VariableMetricMinimizer>();
132 }
133}
134
136
138{
139 // delete the state in case of consecutive minimizations
141 // clear also the function minimum
142 fMinimum.reset();
143}
144
145// set variables
146
147bool Minuit2Minimizer::SetVariable(unsigned int ivar, const std::string &name, double val, double step)
148{
149 // set a free variable.
150 // Add the variable if not existing otherwise set value if exists already
151 // this is implemented in MnUserParameterState::Add
152 // if index is wrong (i.e. variable already exists but with a different index return false) but
153 // value is set for corresponding variable name
154
155 // std::cout << " add parameter " << name << " " << val << " step " << step << std::endl;
156 MnPrint print("Minuit2Minimizer::SetVariable", PrintLevel());
157
158 if (step <= 0) {
159 print.Info("Parameter", name, "has zero or invalid step size - consider it as constant");
160 fState.Add(name, val);
161 } else
162 fState.Add(name, val, step);
163
164 unsigned int minuit2Index = fState.Index(name);
165 if (minuit2Index != ivar) {
166 print.Warn("Wrong index", minuit2Index, "used for the variable", name);
168 return false;
169 }
171
172 return true;
173}
174
175/** set initial second derivatives
176 */
177bool Minuit2Minimizer::SetCovarianceDiag(std::span<const double> d2, unsigned int n)
178{
179 MnPrint print("Minuit2Minimizer::SetCovarianceDiag", PrintLevel());
180
181 std::vector<double> cov(n * (n + 1) / 2);
182
183 for (unsigned int i = 0; i < n; i++) {
184 for (unsigned int j = i; j < n; j++)
185 cov[i + j * (j + 1) / 2] = (i == j) ? d2[i] : 0.;
186 }
187
189}
190
191bool Minuit2Minimizer::SetCovariance(std::span<const double> cov, unsigned int nrow)
192{
193 MnPrint print("Minuit2Minimizer::SetCovariance", PrintLevel());
194
196
197 return true;
198}
199
200bool Minuit2Minimizer::SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step,
201 double lower)
202{
203 // add a lower bounded variable
204 if (!SetVariable(ivar, name, val, step))
205 return false;
207 return true;
208}
209
210bool Minuit2Minimizer::SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step,
211 double upper)
212{
213 // add a upper bounded variable
214 if (!SetVariable(ivar, name, val, step))
215 return false;
217 return true;
218}
219
220bool Minuit2Minimizer::SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step,
221 double lower, double upper)
222{
223 // add a double bound variable
224 if (!SetVariable(ivar, name, val, step))
225 return false;
227 return true;
228}
229
230bool Minuit2Minimizer::SetFixedVariable(unsigned int ivar, const std::string &name, double val)
231{
232 // add a fixed variable
233 // need a step size otherwise treated as a constant
234 // use 10%
235 double step = (val != 0) ? 0.1 * std::abs(val) : 0.1;
236 if (!SetVariable(ivar, name, val, step)) {
238 }
239 fState.Fix(ivar);
240 return true;
241}
242
243std::string Minuit2Minimizer::VariableName(unsigned int ivar) const
244{
245 // return the variable name
246 if (ivar >= fState.MinuitParameters().size())
247 return std::string();
248 return fState.GetName(ivar);
249}
250
251int Minuit2Minimizer::VariableIndex(const std::string &name) const
252{
253 // return the variable index
254 // check if variable exist
255 return fState.Trafo().FindIndex(name);
256}
257
258bool Minuit2Minimizer::SetVariableValue(unsigned int ivar, double val)
259{
260 // set value for variable ivar (only for existing parameters)
261 if (ivar >= fState.MinuitParameters().size())
262 return false;
263 fState.SetValue(ivar, val);
264 return true;
265}
266
268{
269 // set value for variable ivar (only for existing parameters)
270 unsigned int n = fState.MinuitParameters().size();
271 if (n == 0)
272 return false;
273 for (unsigned int ivar = 0; ivar < n; ++ivar)
275 return true;
276}
277
278bool Minuit2Minimizer::SetVariableStepSize(unsigned int ivar, double step)
279{
280 // set the step-size of an existing variable
281 // parameter must exist or return false
282 if (ivar >= fState.MinuitParameters().size())
283 return false;
284 fState.SetError(ivar, step);
285 return true;
286}
287
289{
290 // set the limits of an existing variable
291 // parameter must exist or return false
292 if (ivar >= fState.MinuitParameters().size())
293 return false;
295 return true;
296}
298{
299 // set the limits of an existing variable
300 // parameter must exist or return false
301 if (ivar >= fState.MinuitParameters().size())
302 return false;
304 return true;
305}
306
307bool Minuit2Minimizer::SetVariableLimits(unsigned int ivar, double lower, double upper)
308{
309 // set the limits of an existing variable
310 // parameter must exist or return false
311 if (ivar >= fState.MinuitParameters().size())
312 return false;
314 return true;
315}
316
318{
319 // Fix an existing variable
320 if (ivar >= fState.MinuitParameters().size())
321 return false;
322 fState.Fix(ivar);
323 return true;
324}
325
327{
328 // Release an existing variable
329 if (ivar >= fState.MinuitParameters().size())
330 return false;
332 return true;
333}
334
336{
337 // query if variable is fixed
338 if (ivar >= fState.MinuitParameters().size()) {
339 MnPrint print("Minuit2Minimizer", PrintLevel());
340 print.Error("Wrong variable index");
341 return false;
342 }
343 return (fState.Parameter(ivar).IsFixed() || fState.Parameter(ivar).IsConst());
344}
345
347{
348 // retrieve variable settings (all set info on the variable)
349 if (ivar >= fState.MinuitParameters().size()) {
350 MnPrint print("Minuit2Minimizer", PrintLevel());
351 print.Error("Wrong variable index");
352 return false;
353 }
354 const MinuitParameter &par = fState.Parameter(ivar);
355 varObj.Set(par.Name(), par.Value(), par.Error());
356 if (par.HasLowerLimit()) {
357 if (par.HasUpperLimit()) {
358 varObj.SetLimits(par.LowerLimit(), par.UpperLimit());
359 } else {
360 varObj.SetLowerLimit(par.LowerLimit());
361 }
362 } else if (par.HasUpperLimit()) {
363 varObj.SetUpperLimit(par.UpperLimit());
364 }
365 if (par.IsConst() || par.IsFixed())
366 varObj.Fix();
367 return true;
368}
369
371{
372 // set function to be minimized
373 fMinuitFCN.reset();
374 fDim = func.NDim();
375 const bool hasGrad = func.HasGradient();
376 if (!fUseFumili) {
377 auto lambdaFunc = [&func](double const *params) { return func(params); };
378 auto adapter = std::make_unique<ROOT::Minuit2::FCNAdapter>(lambdaFunc, ErrorDef());
379 if (hasGrad) {
380 auto const &gradFunc = dynamic_cast<ROOT::Math::IMultiGradFunction const &>(func);
381 auto lambdaGrad = [&gradFunc](double const *params, double *grad) { return gradFunc.Gradient(params, grad); };
382 adapter->SetGradientFunction(lambdaGrad);
383 }
384 fMinuitFCN = std::move(adapter);
385 return;
386 }
387 if (hasGrad) {
388 // for Fumili the fit method function interface is required
389 auto fcnfunc = dynamic_cast<const ROOT::Math::FitMethodGradFunction *>(&func);
390 if (!fcnfunc) {
391 MnPrint print("Minuit2Minimizer", PrintLevel());
392 print.Error("Wrong Fit method function for Fumili");
393 return;
394 }
395 fMinuitFCN = std::make_unique<ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodGradFunction>>(*fcnfunc, fDim,
396 ErrorDef());
397 } else {
398 // for Fumili the fit method function interface is required
399 auto fcnfunc = dynamic_cast<const ROOT::Math::FitMethodFunction *>(&func);
400 if (!fcnfunc) {
401 MnPrint print("Minuit2Minimizer", PrintLevel());
402 print.Error("Wrong Fit method function for Fumili");
403 return;
404 }
405 fMinuitFCN =
406 std::make_unique<ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodFunction>>(*fcnfunc, fDim, ErrorDef());
407 }
408}
409
410void Minuit2Minimizer::SetHessianFunction(std::function<bool(std::span<const double>, double *)> hfunc)
411{
412 // for Fumili not supported for the time being
413 if (fUseFumili) return;
414 auto fcn = static_cast<ROOT::Minuit2::FCNAdapter *>(fMinuitFCN.get());
415 if (!fcn) return;
416 fcn->SetHessianFunction(hfunc);
417}
418
419void Minuit2Minimizer::SetSecondDerivativeAlwaysVanishesFunc(std::function<bool(unsigned int, unsigned int)> func)
420{
421 // not supported for Fumili, whose FCN is not an FCNAdapter
422 if (fUseFumili) return;
423 auto fcn = static_cast<ROOT::Minuit2::FCNAdapter *>(fMinuitFCN.get());
424 if (!fcn) return;
425 fcn->SetSecondDerivativeAlwaysVanishesFunc(std::move(func));
426}
427
428namespace {
429
431{
433 // set strategy and add extra options if needed
435 if (!minuit2Opt) {
437 }
438 if (!minuit2Opt) {
439 return st;
440 }
441 auto customize = [&minuit2Opt](const char *name, auto val) {
442 minuit2Opt->GetValue(name, val);
443 return val;
444 };
445 // set extra options
446 st.SetGradientNCycles(customize("GradientNCycles", int(st.GradientNCycles())));
447 st.SetHessianNCycles(customize("HessianNCycles", int(st.HessianNCycles())));
448 st.SetHessianGradientNCycles(customize("HessianGradientNCycles", int(st.HessianGradientNCycles())));
449
450 st.SetGradientTolerance(customize("GradientTolerance", st.GradientTolerance()));
451 st.SetGradientStepTolerance(customize("GradientStepTolerance", st.GradientStepTolerance()));
452 st.SetHessianStepTolerance(customize("HessianStepTolerance", st.HessianStepTolerance()));
453 st.SetHessianG2Tolerance(customize("HessianG2Tolerance", st.HessianG2Tolerance()));
454
455 // These two are the parts of strategy 3 that matter most for ill-conditioned problems
456 st.SetHessianCentralFDMixedDerivatives(
457 customize("HessianCentralFDMixedDerivatives", int(st.HessianCentralFDMixedDerivatives())));
458 st.SetHessianForcePosDef(customize("HessianForcePosDef", int(st.HessianForcePosDef())));
459
460 return st;
461}
462
463} // namespace
464
465/// Perform the minimization and store a copy of FunctionMinimum.
466/// The maximum number of function calls used can be checked via `this->MaxFunctionCalls()`,
467/// if this value is 0 (the default), then it is replaced with
468/// `2 * (nvar + 1) * (200 + 100 * nvar + 5 * nvar * nvar` where `nvar` is number of variable parameters.
469/// \see MnMinos::FindCrossValue
470/// Other minimization settings can be retrieved via `Tolerance()`, `Strategy()`, `ErrorDef()`, `Precision()`
471/// \see ROOT::Math::MinimizerOptions::PrintDefault()
473{
474
475
476 MnPrint print("Minuit2Minimizer::Minimize", PrintLevel());
477
478 if (!fMinuitFCN) {
479 print.Error("FCN function has not been set");
480 return false;
481 }
482
483 assert(GetMinimizer() != nullptr);
484
485 // delete result of previous minimization
486 fMinimum.reset();
487
488 const int maxfcn = MaxFunctionCalls();
489 const double tol = Tolerance();
490 const int strategyLevel = Strategy();
491 fMinuitFCN->SetErrorDef(ErrorDef());
492
493 const int printLevel = PrintLevel();
494 print.Debug("Minuit print level is", printLevel);
495 if (PrintLevel() >= 1) {
496 // print the real number of maxfcn used (defined in ModularFunctionMinimizer)
497 int maxfcn_used = maxfcn;
498 if (maxfcn_used == 0) {
499 int nvar = fState.VariableParameters();
500 maxfcn_used = 200 + 100 * nvar + 5 * nvar * nvar;
501 }
502 std::cout << "Minuit2Minimizer: Minimize with max-calls " << maxfcn_used << " convergence for edm < " << tol
503 << " strategy " << strategyLevel << std::endl;
504 }
505
506 // internal minuit messages
507 fMinimizer->Builder().SetPrintLevel(printLevel);
508
509 // switch off Minuit2 printing
510 const int prev_level = (printLevel <= 0) ? TurnOffPrintInfoLevel() : -2;
512
513 // set the precision if needed
514 if (Precision() > 0)
516
517 // add extra options if needed
519 if (!minuit2Opt) {
521 }
522 if (minuit2Opt) {
523 // set extra options
524 int storageLevel = 1;
525 bool ret = minuit2Opt->GetValue("StorageLevel", storageLevel);
526 if (ret)
528
529 // fumili options
530 if (fUseFumili) {
531 std::string fumiliMethod;
532 ret = minuit2Opt->GetValue("FumiliMethod", fumiliMethod);
533 if (ret) {
534 auto fumiliMinimizer = dynamic_cast<ROOT::Minuit2::FumiliMinimizer *>(fMinimizer.get());
535 if (fumiliMinimizer)
536 fumiliMinimizer->SetMethod(fumiliMethod);
537 }
538 }
539
540 if (printLevel > 0) {
541 std::cout << "Minuit2Minimizer::Minuit - Changing default options" << std::endl;
542 minuit2Opt->Print();
543 }
544 }
545
546 // set a minimizer tracer object (default for printlevel=10, from gROOT for printLevel=11)
547 // use some special print levels
548 MnTraceObject *traceObj = nullptr;
549#ifdef USE_ROOT_ERROR
550 if (printLevel == 10 && gROOT) {
551 TObject *obj = gROOT->FindObject("Minuit2TraceObject");
552 traceObj = dynamic_cast<ROOT::Minuit2::MnTraceObject *>(obj);
553 if (traceObj) {
554 // need to remove from the list
555 gROOT->Remove(obj);
556 }
557 }
558 if (printLevel == 20 || printLevel == 30 || printLevel == 40 || (printLevel >= 20000 && printLevel < 30000)) {
559 int parNumber = printLevel - 20000;
560 if (printLevel == 20)
561 parNumber = -1;
562 if (printLevel == 30)
563 parNumber = -2;
564 if (printLevel == 40)
565 parNumber = 0;
567 }
568#endif
569 if (printLevel == 100 || (printLevel >= 10000 && printLevel < 20000)) {
570 int parNumber = printLevel - 10000;
572 }
573 if (traceObj) {
574 traceObj->Init(fState);
576 }
577
579
581 fMinimum = std::make_unique<ROOT::Minuit2::FunctionMinimum>(min);
582
583 // check if Hesse needs to be run. We do it when is requested (IsValidError() == true , set by SetParabError(true) in fitConfig)
584 // (IsValidError() means the flag to get correct error from the Minimizer is set (Minimizer::SetValidError())
585 // AND when we have a valid minimum,
586 // AND when the the current covariance matrix is estimated using the iterative approximation (Dcovar != 0 , i.e. Hesse has not computed before)
587 if (fMinimum->IsValid() && IsValidError() && fMinimum->State().Error().Dcovar() != 0) {
588 // run Hesse (Hesse will add results in the last state of fMinimum
590 hesse(*fMinuitFCN, *fMinimum, maxfcn);
591 }
592
593 // -2 is the highest low invalid value for gErrorIgnoreLevel
594 if (prev_level > -2)
597
598 // copy minimum state (parameter values and errors)
599 fState = fMinimum->UserState();
600 bool ok = ExamineMinimum(*fMinimum);
601 // fMinimum = 0;
602
603 // delete trace object if it was constructed
604 if (traceObj) {
605 delete traceObj;
606 }
607 return ok;
608}
609
611{
612 /// study the function minimum
613
614 // debug ( print all the states)
615 int debugLevel = PrintLevel();
616 if (debugLevel >= 3) {
617
618 std::span<const ROOT::Minuit2::MinimumState> iterationStates = min.States();
619 std::cout << "Number of iterations " << iterationStates.size() << std::endl;
620 for (unsigned int i = 0; i < iterationStates.size(); ++i) {
621 // std::cout << iterationStates[i] << std::endl;
623 std::cout << "----------> Iteration " << i << std::endl;
624 int pr = std::cout.precision(12);
625 std::cout << " FVAL = " << st.Fval() << " Edm = " << st.Edm() << " Nfcn = " << st.NFcn()
626 << std::endl;
627 std::cout.precision(pr);
628 if (st.HasCovariance())
629 std::cout << " Error matrix change = " << st.Error().Dcovar() << std::endl;
630 if (st.HasParameters()) {
631 std::cout << " Parameters : ";
632 // need to transform from internal to external
633 for (int j = 0; j < st.size(); ++j)
634 std::cout << " p" << j << " = " << fState.Int2ext(j, st.Vec()(j));
635 std::cout << std::endl;
636 }
637 }
638 }
639
640 fStatus = 0;
641 std::string txt;
642 if (!min.HasPosDefCovar()) {
643 // this happens normally when Hesse failed
644 // it can happen in case MnSeed failed (see ROOT-9522)
645 txt = "Covar is not pos def";
646 fStatus = 5;
647 }
648 if (min.HasMadePosDefCovar()) {
649 txt = "Covar was made pos def";
650 fStatus = 1;
651 }
652 if (min.HesseFailed()) {
653 txt = "Hesse is not valid";
654 fStatus = 2;
655 }
656 if (min.IsAboveMaxEdm()) {
657 txt = "Edm is above max";
658 fStatus = 3;
659 }
660 if (min.HasReachedCallLimit()) {
661 txt = "Reached call limit";
662 fStatus = 4;
663 }
664
665 MnPrint print("Minuit2Minimizer::Minimize", debugLevel);
666 bool validMinimum = min.IsValid();
667 if (validMinimum) {
668 // print a warning message in case something is not ok
669 // this for example is case when Covar was made posdef and fStatus=3
670 if (fStatus != 0 && debugLevel > 0)
671 print.Warn(txt);
672 } else {
673 // minimum is not valid when state is not valid and edm is over max or has passed call limits
674 if (fStatus == 0) {
675 // this should not happen
676 txt = "unknown failure";
677 fStatus = 6;
678 }
679 print.Warn("Minimization did NOT converge,", txt);
680 }
681
682 if (debugLevel >= 1)
683 PrintResults();
684
685 // set the minimum values in the fValues vector
686 std::span<const MinuitParameter> paramsObj = fState.MinuitParameters();
687 if (paramsObj.empty())
688 return false;
689 assert(fDim == paramsObj.size());
690 // re-size vector if it has changed after a new minimization
691 if (fValues.size() != fDim)
692 fValues.resize(fDim);
693 for (unsigned int i = 0; i < fDim; ++i) {
694 fValues[i] = paramsObj[i].Value();
695 }
696
697 return validMinimum;
698}
699
701{
702 // print results of minimization
703 if (!fMinimum)
704 return;
705 if (fMinimum->IsValid()) {
706 // valid minimum
707 std::cout << "Minuit2Minimizer : Valid minimum - status = " << fStatus << std::endl;
708 int pr = std::cout.precision(18);
709 std::cout << "FVAL = " << fState.Fval() << std::endl;
710 std::cout << "Edm = " << fState.Edm() << std::endl;
711 std::cout.precision(pr);
712 std::cout << "Nfcn = " << fState.NFcn() << std::endl;
713 for (unsigned int i = 0; i < fState.MinuitParameters().size(); ++i) {
714 const MinuitParameter &par = fState.Parameter(i);
715 std::cout << par.Name() << "\t = " << par.Value() << "\t ";
716 if (par.IsFixed())
717 std::cout << "(fixed)" << std::endl;
718 else if (par.IsConst())
719 std::cout << "(const)" << std::endl;
720 else if (par.HasLimits())
721 std::cout << "+/- " << par.Error() << "\t(limited)" << std::endl;
722 else
723 std::cout << "+/- " << par.Error() << std::endl;
724 }
725 } else {
726 std::cout << "Minuit2Minimizer : Invalid minimum - status = " << fStatus << std::endl;
727 std::cout << "FVAL = " << fState.Fval() << std::endl;
728 std::cout << "Edm = " << fState.Edm() << std::endl;
729 std::cout << "Nfcn = " << fState.NFcn() << std::endl;
730 }
731}
732
733const double *Minuit2Minimizer::Errors() const
734{
735 // return error at minimum (set to zero for fixed and constant params)
736 std::span<const MinuitParameter> paramsObj = fState.MinuitParameters();
737 if (paramsObj.empty())
738 return nullptr;
739 assert(fDim == paramsObj.size());
740 // be careful for multiple calls of this function. I will redo an allocation here
741 // only when size of vectors has changed (e.g. after a new minimization)
742 if (fErrors.size() != fDim)
743 fErrors.resize(fDim);
744 for (unsigned int i = 0; i < fDim; ++i) {
745 const MinuitParameter &par = paramsObj[i];
746 if (par.IsFixed() || par.IsConst())
747 fErrors[i] = 0;
748 else
749 fErrors[i] = par.Error();
750 }
751
752 return &fErrors.front();
753}
754
755double Minuit2Minimizer::CovMatrix(unsigned int i, unsigned int j) const
756{
757 // get value of covariance matrices (transform from external to internal indices)
758 if (i >= fDim || j >= fDim)
759 return 0;
760 if (!fState.HasCovariance())
761 return 0; // no info available when minimization has failed
762 if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst())
763 return 0;
764 if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst())
765 return 0;
766 unsigned int k = fState.IntOfExt(i);
767 unsigned int l = fState.IntOfExt(j);
768 return fState.Covariance()(k, l);
769}
770
772{
773 // get value of covariance matrices
774 if (!fState.HasCovariance())
775 return false; // no info available when minimization has failed
776 for (unsigned int i = 0; i < fDim; ++i) {
777 if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) {
778 for (unsigned int j = 0; j < fDim; ++j) {
779 cov[i * fDim + j] = 0;
780 }
781 } else {
782 unsigned int l = fState.IntOfExt(i);
783 for (unsigned int j = 0; j < fDim; ++j) {
784 // could probably speed up this loop (if needed)
785 int k = i * fDim + j;
786 if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst())
787 cov[k] = 0;
788 else {
789 // need to transform from external to internal indices)
790 // for taking care of the removed fixed row/columns in the Minuit2 representation
791 unsigned int m = fState.IntOfExt(j);
792 cov[k] = fState.Covariance()(l, m);
793 }
794 }
795 }
796 }
797 return true;
798}
799
801{
802 // get value of Hessian matrix
803 // this is the second derivative matrices
804 //
805 // Note: for parameters with limits, the returned external Hessian is obtained by inverting the
806 // external covariance matrix, which is transformed from the internal one with the Jacobian of the
807 // int<->ext transformation only (see MnUserTransformation::Int2extCovariance). This is correct only
808 // at the minimum, where the external gradient vanishes. Away from the minimum the transformation
809 // would need an additional second-derivative term and the result would be inaccurate.
810 if (!fState.HasCovariance())
811 return false; // no info available when minimization has failed
812 for (unsigned int i = 0; i < fDim; ++i) {
813 if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst()) {
814 for (unsigned int j = 0; j < fDim; ++j) {
815 hess[i * fDim + j] = 0;
816 }
817 } else {
818 unsigned int l = fState.IntOfExt(i);
819 for (unsigned int j = 0; j < fDim; ++j) {
820 // could probably speed up this loop (if needed)
821 int k = i * fDim + j;
822 if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst())
823 hess[k] = 0;
824 else {
825 // need to transform from external to internal indices)
826 // for taking care of the removed fixed row/columns in the Minuit2 representation
827 unsigned int m = fState.IntOfExt(j);
828 hess[k] = fState.Hessian()(l, m);
829 }
830 }
831 }
832 }
833
834 return true;
835}
836
837double Minuit2Minimizer::Correlation(unsigned int i, unsigned int j) const
838{
839 // get correlation between parameter i and j
840 if (i >= fDim || j >= fDim)
841 return 0;
842 if (!fState.HasCovariance())
843 return 0; // no info available when minimization has failed
844 if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst())
845 return 0;
846 if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst())
847 return 0;
848 unsigned int k = fState.IntOfExt(i);
849 unsigned int l = fState.IntOfExt(j);
850 double cij = fState.IntCovariance()(k, l);
851 double tmp = std::sqrt(std::abs(fState.IntCovariance()(k, k) * fState.IntCovariance()(l, l)));
852 if (tmp > 0)
853 return cij / tmp;
854 return 0;
855}
856
857std::vector<double> Minuit2Minimizer::GlobalCC() const
858{
859 // get global correlation coefficient for the parameter i. This is a number between zero and one which gives
860 // the correlation between the i-th parameter and that linear combination of all other parameters which
861 // is most strongly correlated with i.
862
863 std::vector<double> out;
865 // no info available when minimization has failed or has some problems
866 if (!globalCC.IsValid())
867 return out;
868 out.resize(fDim);
869 for (unsigned int i = 0; i < fDim; ++i) {
870 if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst())
871 out[i] = 0;
872 else {
873 unsigned int k = fState.IntOfExt(i);
874 out[i] = globalCC.GlobalCC()[k];
875 }
876 }
877 return out;
878}
879
880bool Minuit2Minimizer::GetMinosError(unsigned int i, double &errLow, double &errUp, int runopt)
881{
882 // return the minos error for parameter i
883 // if a minimum does not exist an error is returned
884 // runopt is a flag which specifies if only lower or upper error needs to be run
885 // if runopt = 0 both, = 1 only lower, + 2 only upper errors
886 errLow = 0;
887 errUp = 0;
888
890
891 // need to know if parameter is const or fixed
892 if (fState.Parameter(i).IsConst() || fState.Parameter(i).IsFixed()) {
893 return false;
894 }
895
896 MnPrint print("Minuit2Minimizer::GetMinosError", PrintLevel());
897
898 // to run minos I need function minimum class
899 // redo minimization from current state
900 // ROOT::Minuit2::FunctionMinimum min =
901 // GetMinimizer()->Minimize(*GetFCN(),fState, ROOT::Minuit2::MnStrategy(strategy), MaxFunctionCalls(),
902 // Tolerance());
903 // fState = min.UserState();
904 if (fMinimum == nullptr) {
905 print.Error("Failed - no function minimum existing");
906 return false;
907 }
908
909 if (!fMinimum->IsValid()) {
910 print.Error("Failed - invalid function minimum");
911 return false;
912 }
913
914 fMinuitFCN->SetErrorDef(ErrorDef());
915 // if error def has been changed update it in FunctionMinimum
916 if (ErrorDef() != fMinimum->Up())
917 fMinimum->SetErrorDef(ErrorDef());
918
920
921 // run again the Minimization in case of a new minimum
922 // bit 8 is set
923 if ((mstatus & 8) != 0) {
924 print.Info([&](std::ostream &os) {
925 os << "Found a new minimum: run again the Minimization starting from the new point";
926 os << "\nFVAL = " << fState.Fval();
927 for (auto &par : fState.MinuitParameters()) {
928 os << '\n' << par.Name() << "\t = " << par.Value();
929 }
930 });
931 // release parameter that was fixed in the returned state from Minos
933 bool ok = Minimize();
934 if (!ok)
935 return false;
936 // run again Minos from new Minimum (also lower error needs to be re-computed)
937 print.Info("Run now again Minos from the new found Minimum");
939
940 // do not reset new minimum bit to flag for other parameters
941 mstatus |= 8;
942 }
943
944 fStatus += 10 * mstatus;
946
947 bool isValid = ((mstatus & 1) == 0) && ((mstatus & 2) == 0);
948 return isValid;
949}
950
951int Minuit2Minimizer::RunMinosError(unsigned int i, double &errLow, double &errUp, int runopt)
952{
953
954 bool runLower = runopt != 2;
955 bool runUpper = runopt != 1;
956
957 const int debugLevel = PrintLevel();
958 // switch off Minuit2 printing
959 const int prev_level = (debugLevel <= 0) ? TurnOffPrintInfoLevel() : -2;
961
962 // set the precision if needed
963 if (Precision() > 0)
965
967
968 // run MnCross
969 MnCross low;
970 MnCross up;
971 int maxfcn = MaxFunctionCalls();
972 double tol = Tolerance();
973
974 const char *par_name = fState.Name(i);
975
976 // now input tolerance for migrad calls inside Minos (MnFunctionCross)
977 // before it was fixed to 0.05
978 // cut off too small tolerance (they are not needed)
979 tol = std::max(tol, 0.01);
980
981 // get the real number of maxfcn used (defined in MnMinos) to be printed
982 int maxfcn_used = maxfcn;
983 if (maxfcn_used == 0) {
984 int nvar = fState.VariableParameters();
985 maxfcn_used = 2 * (nvar + 1) * (200 + 100 * nvar + 5 * nvar * nvar);
986 }
987
988 if (runLower) {
989 if (debugLevel >= 1) {
990 std::cout << "************************************************************************************************"
991 "******\n";
992 std::cout << "Minuit2Minimizer::GetMinosError - Run MINOS LOWER error for parameter #" << i << " : "
993 << par_name << " using max-calls " << maxfcn_used << ", tolerance " << tol << std::endl;
994 }
995 low = minos.Loval(i, maxfcn, tol);
996 }
997 if (runUpper) {
998 if (debugLevel >= 1) {
999 std::cout << "************************************************************************************************"
1000 "******\n";
1001 std::cout << "Minuit2Minimizer::GetMinosError - Run MINOS UPPER error for parameter #" << i << " : "
1002 << par_name << " using max-calls " << maxfcn_used << ", tolerance " << tol << std::endl;
1003 }
1004 up = minos.Upval(i, maxfcn, tol);
1005 }
1006
1007 ROOT::Minuit2::MinosError me(i, fMinimum->UserState().Value(i), low, up);
1008
1009 // restore global print level
1010 if (prev_level > -2)
1013
1014 // debug result of Minos
1015 // print error message in Minos
1016 // Note that the only invalid condition can happen when the (npar-1) minimization fails
1017 // The error is also invalid when the maximum number of calls is reached or a new function minimum is found
1018 // in case of the parameter at the limit the error is not invalid.
1019 // When the error is invalid the returned error is the Hessian error.
1020
1021 if (debugLevel > 0) {
1022 if (runLower) {
1023 if (!me.LowerValid())
1024 std::cout << "Minos: Invalid lower error for parameter " << par_name << std::endl;
1025 if (me.AtLowerLimit())
1026 std::cout << "Minos: Parameter : " << par_name << " is at Lower limit; error is " << me.Lower()
1027 << std::endl;
1028 if (me.AtLowerMaxFcn())
1029 std::cout << "Minos: Maximum number of function calls exceeded when running for lower error for parameter "
1030 << par_name << std::endl;
1031 if (me.LowerNewMin())
1032 std::cout << "Minos: New Minimum found while running Minos for lower error for parameter " << par_name
1033 << std::endl;
1034
1035 if (debugLevel >= 1 && me.LowerValid())
1036 std::cout << "Minos: Lower error for parameter " << par_name << " : " << me.Lower() << std::endl;
1037 }
1038 if (runUpper) {
1039 if (!me.UpperValid())
1040 std::cout << "Minos: Invalid upper error for parameter " << par_name << std::endl;
1041 if (me.AtUpperLimit())
1042 std::cout << "Minos: Parameter " << par_name << " is at Upper limit; error is " << me.Upper() << std::endl;
1043 if (me.AtUpperMaxFcn())
1044 std::cout << "Minos: Maximum number of function calls exceeded when running for upper error for parameter "
1045 << par_name << std::endl;
1046 if (me.UpperNewMin())
1047 std::cout << "Minos: New Minimum found while running Minos for upper error for parameter " << par_name
1048 << std::endl;
1049
1050 if (debugLevel >= 1 && me.UpperValid())
1051 std::cout << "Minos: Upper error for parameter " << par_name << " : " << me.Upper() << std::endl;
1052 }
1053 }
1054
1055 MnPrint print("RunMinosError", PrintLevel());
1056 bool lowerInvalid = (runLower && !me.LowerValid());
1057 bool upperInvalid = (runUpper && !me.UpperValid());
1058 // print message in case of invalid error also in printLevel0
1059 if (lowerInvalid) {
1060 print.Warn("Invalid lower error for parameter", fMinimum->UserState().Name(i));
1061 }
1062 if (upperInvalid) {
1063 print.Warn("Invalid upper error for parameter", fMinimum->UserState().Name(i));
1064 }
1065 // print also case it is lower/upper limit
1066 if (me.AtLowerLimit()) {
1067 print.Warn("Lower error for parameter", fMinimum->UserState().Name(i), "is at the Lower limit!");
1068 }
1069 if (me.AtUpperLimit()) {
1070 print.Warn("Upper error for parameter", fMinimum->UserState().Name(i), "is at the Upper limit!");
1071 }
1072
1073 int mstatus = 0;
1074 if (lowerInvalid || upperInvalid) {
1075 // set status according to bit
1076 // bit 1: lower invalid Minos errors
1077 // bit 2: upper invalid Minos error
1078 // bit 3: invalid because max FCN
1079 // bit 4 : invalid because a new minimum has been found
1080 if (lowerInvalid) {
1081 mstatus |= 1;
1082 if (me.AtLowerMaxFcn())
1083 mstatus |= 4;
1084 if (me.LowerNewMin())
1085 mstatus |= 8;
1086 }
1087 if (upperInvalid) {
1088 mstatus |= 2;
1089 if (me.AtUpperMaxFcn())
1090 mstatus |= 4;
1091 if (me.UpperNewMin())
1092 mstatus |= 8;
1093 }
1094 }
1095 // case upper/lower limit
1096 if (me.AtUpperLimit() || me.AtLowerLimit())
1097 mstatus |= 16;
1098
1099 if (runLower)
1100 errLow = me.Lower();
1101 if (runUpper)
1102 errUp = me.Upper();
1103
1104 // in case of new minimum found update also the minimum state
1105 if ((runLower && me.LowerNewMin()) && (runUpper && me.UpperNewMin())) {
1106 // take state with lower function value
1107 fState = (low.State().Fval() < up.State().Fval()) ? low.State() : up.State();
1108 } else if (runLower && me.LowerNewMin()) {
1109 fState = low.State();
1110 } else if (runUpper && me.UpperNewMin()) {
1111 fState = up.State();
1112 }
1113
1114 return mstatus;
1115}
1116
1117bool Minuit2Minimizer::Scan(unsigned int ipar, unsigned int &nstep, double *x, double *y, double xmin, double xmax)
1118{
1119 // scan a parameter (variable) around the minimum value
1120 // the parameters must have been set before
1121 // if xmin=0 && xmax == 0 by default scan around 2 sigma of the error
1122 // if the errors are also zero then scan from min and max of parameter range
1123
1124 MnPrint print("Minuit2Minimizer::Scan", PrintLevel());
1125 if (!fMinuitFCN) {
1126 print.Error("Function must be set before using Scan");
1127 return false;
1128 }
1129
1130 if (ipar > fState.MinuitParameters().size()) {
1131 print.Error("Invalid number; minimizer variables must be set before using Scan");
1132 return false;
1133 }
1134
1135 // switch off Minuit2 printing
1136 const int prev_level = (PrintLevel() <= 0) ? TurnOffPrintInfoLevel() : -2;
1138
1139 // set the precision if needed
1140 if (Precision() > 0)
1142
1144 double amin = scan.Fval(); // fcn value of the function before scan
1145
1146 // first value is param value
1147 std::vector<std::pair<double, double>> result = scan(ipar, nstep - 1, xmin, xmax);
1148
1149 // restore global print level
1150 if (prev_level > -2)
1153
1154 if (result.size() != nstep) {
1155 print.Error("Invalid result from MnParameterScan");
1156 return false;
1157 }
1158 // sort also the returned points in x
1159 std::sort(result.begin(), result.end());
1160
1161 for (unsigned int i = 0; i < nstep; ++i) {
1162 x[i] = result[i].first;
1163 y[i] = result[i].second;
1164 }
1165
1166 // what to do if a new minimum has been found ?
1167 // use that as new minimum
1168 if (scan.Fval() < amin) {
1169 print.Info("A new minimum has been found");
1170 fState.SetValue(ipar, scan.Parameters().Value(ipar));
1171 }
1172
1173 return true;
1174}
1175
1176bool Minuit2Minimizer::Contour(unsigned int ipar, unsigned int jpar, unsigned int &npoints, double *x, double *y)
1177{
1178 // contour plot for parameter i and j
1179 // need a valid FunctionMinimum otherwise exits
1180
1181 MnPrint print("Minuit2Minimizer::Contour", PrintLevel());
1182
1183 if (fMinimum == nullptr) {
1184 print.Error("No function minimum existing; must minimize function before");
1185 return false;
1186 }
1187
1188 if (!fMinimum->IsValid()) {
1189 print.Error("Invalid function minimum");
1190 return false;
1191 }
1193
1194 fMinuitFCN->SetErrorDef(ErrorDef());
1195 // if error def has been changed update it in FunctionMinimum
1196 if (ErrorDef() != fMinimum->Up()) {
1197 fMinimum->SetErrorDef(ErrorDef());
1198 }
1199
1200 print.Info("Computing contours at level -", ErrorDef());
1201
1202 // switch off Minuit2 printing (for level of 0,1)
1203 const int prev_level = (PrintLevel() <= 1) ? TurnOffPrintInfoLevel() : -2;
1205
1206 // set the precision if needed
1207 if (Precision() > 0)
1209
1210 // eventually one should specify tolerance in contours
1211 MnContours contour(*fMinuitFCN, *fMinimum, Strategy());
1212
1213 // restore global print level
1214 if (prev_level > -2)
1217
1218 // compute the contour
1219 std::vector<std::pair<double, double>> result = contour(ipar, jpar, npoints);
1220 if (result.size() != npoints) {
1221 print.Error("Invalid result from MnContours");
1222 return false;
1223 }
1224 for (unsigned int i = 0; i < npoints; ++i) {
1225 x[i] = result[i].first;
1226 y[i] = result[i].second;
1227 }
1228 print.Info([&](std::ostream &os) {
1229 os << " Computed " << npoints << " points at level " << ErrorDef();
1230 for (unsigned int i = 0; i < npoints; i++) {
1231 if (i %5 == 0) os << std::endl;
1232 os << "( " << x[i] << ", " << y[i] << ") ";
1233 }
1234 os << std::endl << std::endl;
1235 });
1236
1237 return true;
1238}
1239
1241{
1242 // find Hessian (full second derivative calculations)
1243 // the contained state will be updated with the Hessian result
1244 // in case a function minimum exists and is valid the result will be
1245 // appended in the function minimum
1246
1247 MnPrint print("Minuit2Minimizer::Hesse", PrintLevel());
1248
1249 if (!fMinuitFCN) {
1250 print.Error("FCN function has not been set");
1251 return false;
1252 }
1253
1254 const int maxfcn = MaxFunctionCalls();
1255 print.Info("Using max-calls", maxfcn);
1256
1257 // switch off Minuit2 printing
1258 const int prev_level = (PrintLevel() <= 0) ? TurnOffPrintInfoLevel() : -2;
1260
1261 // set the precision if needed
1262 if (Precision() > 0)
1264
1266
1267 // case when function minimum exists
1268 if (fMinimum) {
1269
1270 // if (PrintLevel() >= 3) {
1271 // std::cout << "Minuit2Minimizer::Hesse - State before running Hesse " << std::endl;
1272 // std::cout << fState << std::endl;
1273 // }
1274
1275 // run hesse and function minimum will be updated with Hesse result
1276 hesse(*fMinuitFCN, *fMinimum, maxfcn);
1277 // update user state
1278 fState = fMinimum->UserState();
1279 }
1280
1281 else {
1282 // run Hesse on point stored in current state (independent of function minimum validity)
1283 // (x == 0)
1284 fState = hesse(*fMinuitFCN, fState, maxfcn);
1285 }
1286
1287 // restore global print level
1288 if (prev_level > -2)
1291
1292 if (PrintLevel() >= 3) {
1293 std::cout << "Minuit2Minimizer::Hesse - State returned from Hesse " << std::endl;
1294 std::cout << fState << std::endl;
1295 }
1296
1298 std::string covStatusType = "not valid";
1299 if (covStatus == 1)
1300 covStatusType = "approximate";
1301 if (covStatus == 2)
1302 covStatusType = "full but made positive defined";
1303 if (covStatus == 3)
1304 covStatusType = "accurate";
1305 if (covStatus == 0)
1306 covStatusType = "full but not positive defined";
1307
1308 if (!fState.HasCovariance()) {
1309 // if false means error is not valid and this is due to a failure in Hesse
1310 // update minimizer error status
1311 int hstatus = 4;
1312 // information on error state can be retrieved only if fMinimum is available
1313 if (fMinimum) {
1314 if (fMinimum->Error().HesseFailed())
1315 hstatus = 1;
1316 if (fMinimum->Error().InvertFailed())
1317 hstatus = 2;
1318 else if (!(fMinimum->Error().IsPosDef()))
1319 hstatus = 3;
1320 }
1321
1322 print.Warn("Hesse failed - matrix is", covStatusType);
1323 print.Warn(hstatus);
1324
1325 fStatus += 100 * hstatus;
1326 return false;
1327 }
1328
1329 print.Info("Hesse is valid - matrix is", covStatusType);
1330
1331 return true;
1332}
1333
1335{
1336 // return status of covariance matrix
1337 //-1 - not available (inversion failed or Hesse failed)
1338 // 0 - available but not positive defined
1339 // 1 - covariance only approximate
1340 // 2 full matrix but forced pos def
1341 // 3 full accurate matrix
1342
1343 if (fMinimum) {
1344 // case a function minimum is available
1345 if (fMinimum->HasAccurateCovar())
1346 return 3;
1347 else if (fMinimum->HasMadePosDefCovar())
1348 return 2;
1349 else if (fMinimum->HasValidCovariance())
1350 return 1;
1351 else if (fMinimum->HasCovariance())
1352 return 0;
1353 return -1;
1354 } else {
1355 // case fMinimum is not available - use state information
1356 return fState.CovarianceStatus();
1357 }
1358 return 0;
1359}
1360
1362{
1363 // set trace object
1364 if (fMinimizer)
1365 fMinimizer->Builder().SetTraceObject(obj);
1366}
1367
1369{
1370 // set storage level
1371 if (fMinimizer)
1372 fMinimizer->Builder().SetStorageLevel(level);
1373}
1374
1375void Minuit2Minimizer::SetFCN(unsigned int nDim, std::unique_ptr<ROOT::Minuit2::FCNBase> fcn)
1376{
1377 fDim = nDim;
1378 fMinuitFCN = std::move(fcn);
1379}
1380
1381} // end namespace Minuit2
1382
1383} // end namespace ROOT
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Int_t gErrorIgnoreLevel
errors with level below this value will be ignored. Default is kUnset.
Definition TError.cxx:33
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:142
float xmin
float xmax
#define gROOT
Definition TROOT.h:417
Class, describing value, limits and step size of the parameters Provides functionality also to set/re...
FitMethodFunction class Interface for objective functions (like chi2 and likelihood used in the fit) ...
Documentation for the abstract class IBaseFunctionMultiDim.
Definition IFunction.h:63
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:239
Generic interface for defining configuration options of a numerical algorithm.
Definition IOptions.h:28
const IOptions * ExtraOptions() const
return extra options (NULL pointer if they are not present)
static ROOT::Math::IOptions * FindDefault(const char *name)
Find an extra options and return a nullptr if it is not existing.
double Tolerance() const
Absolute tolerance.
Definition Minimizer.h:317
unsigned int MaxFunctionCalls() const
Max number of function calls.
Definition Minimizer.h:311
double Precision() const
Precision of minimizer in the evaluation of the objective function.
Definition Minimizer.h:321
int fStatus
status of minimizer
Definition Minimizer.h:388
int Strategy() const
Strategy.
Definition Minimizer.h:324
double ErrorDef() const
Definition Minimizer.h:334
MinimizerOptions fOptions
minimizer options
Definition Minimizer.h:387
bool IsValidError() const
Definition Minimizer.h:337
int PrintLevel() const
Set print level.
Definition Minimizer.h:308
Adapter class to wrap user-provided functions into the FCNBase interface.
Definition FCNAdapter.h:37
Instantiates the seed generator and Minimum builder for the Fumili minimization method.
class holding the full result of the minimization; both internal and external (MnUserParameterState) ...
MinimumState keeps the information (position, Gradient, 2nd deriv, etc) after one minimization step (...
Class holding the result of Minos (lower and upper values) for a specific parameter.
Definition MinosError.h:25
bool AtUpperLimit() const
Definition MinosError.h:87
bool AtLowerMaxFcn() const
Definition MinosError.h:88
bool AtUpperMaxFcn() const
Definition MinosError.h:89
bool AtLowerLimit() const
Definition MinosError.h:86
bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum &min)
examine the minimum result
Minuit2Minimizer(ROOT::Minuit2::EMinimizerType type=ROOT::Minuit2::kMigrad)
Default constructor.
void SetStorageLevel(int level)
set storage level = 1 : store all iteration states (default) = 0 : store only first and last state to...
bool SetCovariance(std::span< const double > cov, unsigned int nrow) override
set initial covariance matrix
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 Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) override
find the contour points (xi,xj) of the function for parameter i and j around the minimum The contour ...
virtual bool SetCovarianceDiag(std::span< const double > d2, unsigned int n) override
set initial second derivatives
bool IsFixedVariable(unsigned int ivar) const override
query if an existing variable is fixed (i.e.
bool SetVariableUpperLimit(unsigned int ivar, double upper) override
set the upper-limit of an already existing variable
bool SetVariableValues(const double *val) override
Set the values of all existing variables (array must be dimensioned to the size of the existing param...
bool SetVariable(unsigned int ivar, const std::string &name, double val, double step) override
set free variable
const double * Errors() const override
return errors at the minimum
void SetFunction(const ROOT::Math::IMultiGenFunction &func) override
set the function to minimize
bool SetVariableStepSize(unsigned int ivar, double step) override
set the step size of an already existing variable
bool GetCovMatrix(double *cov) const override
Fill the passed array with the covariance matrix elements if the variable is fixed or const the value...
bool ReleaseVariable(unsigned int ivar) override
release an existing variable
bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const override
get variable settings in a variable object (like ROOT::Fit::ParamsSettings)
bool Hesse() override
perform a full calculation of the Hessian matrix for error calculation If a valid minimum exists the ...
bool GetMinosError(unsigned int i, double &errLow, double &errUp, int=0) override
get the minos error for parameter i, return false if Minos failed A minimizaiton must be performed be...
std::string VariableName(unsigned int ivar) const override
get name of variables (override if minimizer support storing of variable names)
int RunMinosError(unsigned int i, double &errLow, double &errUp, int runopt)
bool SetVariableLimits(unsigned int ivar, double lower, double upper) override
set the limits of an already existing variable
double Correlation(unsigned int i, unsigned int j) const override
return correlation coefficient between variable i and j.
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 SetTraceObject(MnTraceObject &obj)
set an object to trace operation for each iteration The object must be a (or inherit from) ROOT::Minu...
virtual const ROOT::Minuit2::ModularFunctionMinimizer * GetMinimizer() const
double CovMatrix(unsigned int i, unsigned int j) const override
return covariance matrix elements if the variable is fixed or const the value is zero The ordering of...
void SetMinimizerType(ROOT::Minuit2::EMinimizerType type)
std::unique_ptr< ROOT::Minuit2::ModularFunctionMinimizer > fMinimizer
bool SetVariableValue(unsigned int ivar, double val) override
set variable
bool Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin=0, double xmax=0) override
scan a parameter i around the minimum.
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 SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper) override
set upper limit variable (override if minimizer supports them )
ROOT::Minuit2::MnUserParameterState fState
bool SetVariableLowerLimit(unsigned int ivar, double lower) override
set the lower-limit of an already existing variable
bool FixVariable(unsigned int ivar) override
fix an existing variable
void SetSecondDerivativeAlwaysVanishesFunc(std::function< bool(unsigned int, unsigned int)> func)
Set a predicate advertising which mixed second derivatives of the minimized function are identically ...
void SetHessianFunction(std::function< bool(std::span< const double >, double *)> hfunc) override
set the function implementing Hessian computation
bool Minimize() override
method to perform the minimization.
bool SetFixedVariable(unsigned int, const std::string &, double) override
set fixed variable (override if minimizer supports them )
bool GetHessianMatrix(double *h) const override
Fill the passed array with the Hessian matrix elements The Hessian matrix is the matrix of the second...
void PrintResults() override
return reference to the objective function virtual const ROOT::Math::IGenFunction & Function() const;
void Clear() override
Reset for consecutive minimization - implement if needed.
~Minuit2Minimizer() override
Destructor (no operations)
std::vector< double > GlobalCC() const override
get global correlation coefficient for the variable i.
void SetFCN(unsigned int nDim, std::unique_ptr< ROOT::Minuit2::FCNBase > fcn)
To set the function directly to a Minuit 2 function.
int CovMatrixStatus() const override
return the status of the covariance matrix status = -1 : not available (inversion failed or Hesse fai...
std::unique_ptr< ROOT::Minuit2::FCNBase > fMinuitFCN
std::unique_ptr< ROOT::Minuit2::FunctionMinimum > fMinimum
class for the individual Minuit Parameter with Name and number; contains the input numbers for the mi...
API class for Contours Error analysis (2-dim errors); minimization has to be done before and Minimum ...
Definition MnContours.h:35
const MnUserParameterState & State() const
Definition MnCross.h:84
class for global correlation coefficient
API class for calculating the numerical covariance matrix (== 2x Inverse Hessian == 2x Inverse 2nd de...
Definition MnHesse.h:41
API class for Minos Error analysis (asymmetric errors); minimization has to be done before and Minimu...
Definition MnMinos.h:33
MnCross Loval(unsigned int, unsigned int maxcalls=0, double toler=0.1) const
Definition MnMinos.cxx:206
MnCross Upval(unsigned int, unsigned int maxcalls=0, double toler=0.1) const
Definition MnMinos.cxx:200
Scans the values of FCN as a function of one Parameter and retains the best function and Parameter va...
const MnUserParameters & Parameters() const
void Debug(const Ts &... args)
Definition MnPrint.h:135
void Error(const Ts &... args)
Definition MnPrint.h:117
void Info(const Ts &... args)
Definition MnPrint.h:129
static int SetGlobalLevel(int level)
Definition MnPrint.cxx:111
void Warn(const Ts &... args)
Definition MnPrint.h:123
API class for defining four levels of strategies: low (0), medium (1), high (2), very high (>=3); act...
Definition MnStrategy.h:255
class which holds the external user and/or internal Minuit representation of the parameters and error...
void SetLimits(unsigned int, double, double)
const MnUserParameters & Parameters() const
unsigned int Index(const std::string &) const
const std::string & GetName(unsigned int) const
double Int2ext(unsigned int, double) const
MnGlobalCorrelationCoeff GlobalCC() const
const MinuitParameter & Parameter(unsigned int i) const
void Add(const std::string &name, double val, double err)
const char * Name(unsigned int) const
void AddCovariance(const MnUserCovariance &)
const std::vector< ROOT::Minuit2::MinuitParameter > & MinuitParameters() const
facade: forward interface of MnUserParameters and MnUserTransformation
unsigned int IntOfExt(unsigned int) const
const MnUserTransformation & Trafo() const
const MnUserCovariance & IntCovariance() const
const MnUserCovariance & Covariance() const
const_iterator begin() const
const_iterator end() const
Mother of all ROOT objects.
Definition TObject.h:42
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:424
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
void RestoreGlobalPrintLevel(int)
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4