18 #include "Math/IFunction.h"
19 #include "Math/IOptions.h"
21 #include "Minuit2/FCNAdapter.h"
22 #include "Minuit2/FumiliFCNAdapter.h"
23 #include "Minuit2/FCNGradAdapter.h"
24 #include "Minuit2/FunctionMinimum.h"
25 #include "Minuit2/MnMigrad.h"
26 #include "Minuit2/MnMinos.h"
27 #include "Minuit2/MinosError.h"
28 #include "Minuit2/MnHesse.h"
29 #include "Minuit2/MinuitParameter.h"
30 #include "Minuit2/MnUserFcn.h"
31 #include "Minuit2/MnPrint.h"
32 #include "Minuit2/FunctionMinimum.h"
33 #include "Minuit2/VariableMetricMinimizer.h"
34 #include "Minuit2/SimplexMinimizer.h"
35 #include "Minuit2/CombinedMinimizer.h"
36 #include "Minuit2/ScanMinimizer.h"
37 #include "Minuit2/FumiliMinimizer.h"
38 #include "Minuit2/MnParameterScan.h"
39 #include "Minuit2/MnContours.h"
55 if (prevErrorIgnoreLevel < 1001) {
57 return prevErrorIgnoreLevel;
71 : Minimizer(), fDim(0), fMinimizer(nullptr), fMinuitFCN(nullptr), fMinimum(nullptr) {
76 HybridMinimizer::HybridMinimizer(
const char *
type)
77 : Minimizer(), fDim(0), fMinimizer(nullptr), fMinuitFCN(nullptr), fMinimum(nullptr) {
85 if (algoname ==
"simplex")
87 if (algoname ==
"minimize")
89 if (algoname ==
"scan")
91 if (algoname ==
"fumili")
107 SetMinimizer(
new ROOT::Minuit2::VariableMetricMinimizer());
125 SetMinimizer(
new ROOT::Minuit2::VariableMetricMinimizer());
152 fState = MnUserParameterState();
171 std::string txtmsg =
"Parameter " +
name +
" has zero or invalid step size - consider it as constant ";
172 MN_INFO_MSG2(
"HybridMinimizer::SetVariable", txtmsg);
177 unsigned int minuit2Index =
fState.Index(
name);
178 if (minuit2Index != ivar) {
180 MN_INFO_MSG2(
"HybridMinimizer::SetVariable", txtmsg);
181 MN_INFO_VAL2(
"HybridMinimizer::SetVariable", minuit2Index);
184 fState.RemoveLimits(ivar);
194 fState.SetLowerLimit(ivar, lower);
230 if (ivar >=
fState.MinuitParameters().size())
232 return fState.GetName(ivar);
243 if (ivar >=
fState.MinuitParameters().size())
251 unsigned int n =
fState.MinuitParameters().size();
254 for (
unsigned int ivar = 0; ivar <
n; ++ivar)
255 fState.SetValue(ivar, x[ivar]);
265 fMinuitFCN =
new ROOT::Minuit2::FCNAdapter<ROOT::Math::IMultiGenFunction>(
func, ErrorDef());
268 const ROOT::Math::FitMethodFunction *fcnfunc = dynamic_cast<const ROOT::Math::FitMethodFunction *>(&
func);
270 MN_ERROR_MSG(
"HybridMinimizer: Wrong Fit method function for Fumili");
273 fMinuitFCN =
new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodFunction>(*fcnfunc,
fDim, ErrorDef());
283 fMinuitFCN =
new ROOT::Minuit2::FCNGradAdapter<ROOT::Math::IMultiGradFunction>(
func, ErrorDef());
286 const ROOT::Math::FitMethodGradFunction *fcnfunc = dynamic_cast<const ROOT::Math::FitMethodGradFunction *>(&
func);
288 MN_ERROR_MSG(
"HybridMinimizer: Wrong Fit method function for Fumili");
291 fMinuitFCN =
new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodGradFunction>(*fcnfunc,
fDim, ErrorDef());
299 MN_ERROR_MSG2(
"HybridMinimizer::Minimize",
"FCN function has not been set");
310 int maxfcn = MaxFunctionCalls();
312 int strategyLevel = Strategy();
330 MnPrint::SetLevel(PrintLevel());
337 fState.SetPrecision(Precision());
340 ROOT::Minuit2::MnStrategy strategy(strategyLevel);
341 ROOT::Math::IOptions *minuit2Opt = ROOT::Math::MinimizerOptions::FindDefault(
"Minuit2");
344 int nGradCycles = strategy.GradientNCycles();
345 int nHessCycles = strategy.HessianNCycles();
346 int nHessGradCycles = strategy.HessianGradientNCycles();
348 double gradTol = strategy.GradientTolerance();
349 double gradStepTol = strategy.GradientStepTolerance();
350 double hessStepTol = strategy.HessianStepTolerance();
351 double hessG2Tol = strategy.HessianG2Tolerance();
353 minuit2Opt->GetValue(
"GradientNCycles", nGradCycles);
354 minuit2Opt->GetValue(
"HessianNCycles", nHessCycles);
355 minuit2Opt->GetValue(
"HessianGradientNCycles", nHessGradCycles);
357 minuit2Opt->GetValue(
"GradientTolerance", gradTol);
358 minuit2Opt->GetValue(
"GradientStepTolerance", gradStepTol);
359 minuit2Opt->GetValue(
"HessianStepTolerance", hessStepTol);
360 minuit2Opt->GetValue(
"HessianG2Tolerance", hessG2Tol);
362 strategy.SetGradientNCycles(nGradCycles);
363 strategy.SetHessianNCycles(nHessCycles);
364 strategy.SetHessianGradientNCycles(nHessGradCycles);
366 strategy.SetGradientTolerance(gradTol);
367 strategy.SetGradientStepTolerance(gradStepTol);
368 strategy.SetHessianStepTolerance(hessStepTol);
369 strategy.SetHessianG2Tolerance(hessStepTol);
371 if (PrintLevel() > 0) {
377 const ROOT::Minuit2::FCNGradientBase *gradFCN = dynamic_cast<const ROOT::Minuit2::FCNGradientBase *>(
fMinuitFCN);
378 if (gradFCN !=
nullptr) {
381 ROOT::Minuit2::FunctionMinimum
min =
GetMinimizer()->Minimize(*gradFCN,
fState, strategy, maxfcn, tol);
382 fMinimum =
new ROOT::Minuit2::FunctionMinimum(
min);
385 fMinimum =
new ROOT::Minuit2::FunctionMinimum(
min);
389 if (
fMinimum->IsValid() && IsValidError() &&
fMinimum->State().Error().Dcovar() != 0) {
391 ROOT::Minuit2::MnHesse hesse(strategy);
432 if (
min.HasMadePosDefCovar()) {
433 txt =
"Covar was made pos def";
436 if (
min.HesseFailed()) {
437 txt =
"Hesse is not valid";
440 if (
min.IsAboveMaxEdm()) {
441 txt =
"Edm is above max";
444 if (
min.HasReachedCallLimit()) {
445 txt =
"Reached call limit";
449 bool validMinimum =
min.IsValid();
453 MN_INFO_MSG2(
"HybridMinimizer::Minimize", txt);
458 txt =
"unknown failure";
462 MN_INFO_MSG2(
"HybridMinimizer::Minimize",
msg);
506 const std::vector<MinuitParameter> ¶msObj =
fState.MinuitParameters();
507 if (paramsObj.empty())
514 for (
unsigned int i = 0;
i <
fDim; ++
i) {
523 const std::vector<MinuitParameter> ¶msObj =
fState.MinuitParameters();
524 if (paramsObj.empty())
531 for (
unsigned int i = 0;
i <
fDim; ++
i) {
532 const MinuitParameter &par = paramsObj[
i];
533 if (par.IsFixed() || par.IsConst())
546 if (!
fState.HasCovariance())
548 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst())
550 if (
fState.Parameter(
j).IsFixed() ||
fState.Parameter(
j).IsConst())
552 unsigned int k =
fState.IntOfExt(
i);
553 unsigned int l =
fState.IntOfExt(
j);
559 if (!
fState.HasCovariance())
561 for (
unsigned int i = 0;
i <
fDim; ++
i) {
562 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst()) {
563 for (
unsigned int j = 0;
j <
fDim; ++
j) {
567 unsigned int l =
fState.IntOfExt(
i);
568 for (
unsigned int j = 0;
j <
fDim; ++
j) {
571 if (
fState.Parameter(
j).IsFixed() ||
fState.Parameter(
j).IsConst())
576 unsigned int m =
fState.IntOfExt(
j);
590 for (
unsigned int i = 0;
i <
fDim; ++
i) {
591 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst()) {
592 for (
unsigned int j = 0;
j <
fDim; ++
j) {
596 unsigned int l =
fState.IntOfExt(
i);
597 for (
unsigned int j = 0;
j <
fDim; ++
j) {
600 if (
fState.Parameter(
j).IsFixed() ||
fState.Parameter(
j).IsConst())
605 unsigned int m =
fState.IntOfExt(
j);
619 if (!
fState.HasCovariance())
621 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst())
623 if (
fState.Parameter(
j).IsFixed() ||
fState.Parameter(
j).IsConst())
625 unsigned int k =
fState.IntOfExt(
i);
626 unsigned int l =
fState.IntOfExt(
j);
627 double cij =
fState.IntCovariance()(
k,
l);
642 if (!
fState.HasGlobalCC())
644 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst())
646 unsigned int k =
fState.IntOfExt(
i);
647 return fState.GlobalCC().GlobalCC()[
k];
657 bool runLower = runopt != 2;
658 bool runUpper = runopt != 1;
663 if (
fState.Parameter(
i).IsConst() ||
fState.Parameter(
i).IsFixed()) {
677 MN_ERROR_MSG(
"HybridMinimizer::GetMinosErrors: failed - no function minimum existing");
682 MN_ERROR_MSG(
"HybridMinimizer::MINOS failed due to invalid function minimum");
696 fState.SetPrecision(Precision());
703 int maxfcn = MaxFunctionCalls();
727 low = minos.Loval(
i, maxfcn, tol);
729 up = minos.Upval(
i, maxfcn, tol);
769 bool lowerInvalid = (runLower && !
me.LowerValid());
770 bool upperInvalid = (runUpper && !
me.UpperValid());
772 if (lowerInvalid || upperInvalid) {
780 if (
me.AtLowerMaxFcn())
782 if (
me.LowerNewMin())
787 if (
me.AtUpperMaxFcn())
789 if (
me.UpperNewMin())
793 fStatus += 10 * mstatus;
799 bool isValid = (runLower &&
me.LowerValid()) || (runUpper &&
me.UpperValid());
810 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Function must be set before using Scan");
814 if (ipar >
fState.MinuitParameters().size()) {
815 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Invalid number. Minimizer variables must be set before using Scan");
822 MnPrint::SetLevel(PrintLevel());
826 fState.SetPrecision(Precision());
829 double amin = scan.Fval();
832 std::vector<std::pair<double, double> >
result = scan(ipar, nstep - 1,
xmin,
xmax);
837 if (
result.size() != nstep) {
838 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Invalid result from MnParameterScan");
844 for (
unsigned int i = 0;
i < nstep; ++
i) {
851 if (scan.Fval() < amin) {
852 if (PrintLevel() > 0)
853 MN_INFO_MSG2(
"HybridMinimizer::Scan",
"A new minimum has been found");
854 fState.SetValue(ipar, scan.Parameters().Value(ipar));
864 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" no function minimum existing. Must minimize function before");
869 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
"Invalid function minimum");
882 MnPrint::SetLevel(PrintLevel());
886 fState.SetPrecision(Precision());
896 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" Invalid result from MnContours");
914 MN_ERROR_MSG2(
"HybridMinimizer::Hesse",
"FCN function has not been set");
918 int strategy = Strategy();
919 int maxfcn = MaxFunctionCalls();
924 MnPrint::SetLevel(PrintLevel());
928 fState.SetPrecision(Precision());
930 ROOT::Minuit2::MnHesse hesse(strategy);
948 if (PrintLevel() >= 3) {
953 if (!
fState.HasCovariance()) {
955 if (PrintLevel() > 0)
956 MN_INFO_MSG2(
"HybridMinimizer::Hesse",
"Hesse failed ");
961 if (
fMinimum->Error().HesseFailed())
963 if (
fMinimum->Error().InvertFailed())
965 else if (!(
fMinimum->Error().IsPosDef()))
968 fStatus += 100 * hstatus;
987 else if (
fMinimum->HasMadePosDefCovar())
989 else if (
fMinimum->HasValidCovariance())
996 return fState.CovarianceStatus();