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;
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);
175 fState.Add(name, val, step);
177 unsigned int minuit2Index =
fState.Index(name);
178 if (minuit2Index != ivar) {
179 std::string txtmsg(
"Wrong index used for the variable " + name);
180 MN_INFO_MSG2(
"HybridMinimizer::SetVariable", txtmsg);
181 MN_INFO_VAL2(
"HybridMinimizer::SetVariable", minuit2Index);
184 fState.RemoveLimits(ivar);
194 fState.SetLowerLimit(ivar, lower);
203 fState.SetUpperLimit(ivar, upper);
212 fState.SetLimits(ivar, lower, upper);
222 ivar =
fState.Index(name);
230 if (ivar >=
fState.MinuitParameters().size())
232 return fState.GetName(ivar);
238 return fState.Trafo().FindIndex(name);
243 if (ivar >=
fState.MinuitParameters().size())
245 fState.SetValue(ivar, val);
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);
410 if (debugLevel >= 3) {
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();
452 if (fStatus != 0 && debugLevel > 0)
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())
509 assert(
fDim == paramsObj.size());
514 for (
unsigned int i = 0;
i <
fDim; ++
i) {
523 const std::vector<MinuitParameter> ¶msObj =
fState.MinuitParameters();
524 if (paramsObj.empty())
526 assert(
fDim == paramsObj.size());
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) {
564 cov[
i * fDim +
j] = 0;
567 unsigned int l =
fState.IntOfExt(
i);
568 for (
unsigned int j = 0;
j <
fDim; ++
j) {
570 int k =
i * fDim +
j;
571 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst())
576 unsigned int m =
fState.IntOfExt(j);
588 if (!
fState.HasCovariance())
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) {
593 hess[
i * fDim +
j] = 0;
596 unsigned int l =
fState.IntOfExt(
i);
597 for (
unsigned int j = 0;
j <
fDim; ++
j) {
599 int k =
i * 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()) {
669 MnPrint::SetLevel(debugLevel);
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);
731 ROOT::Minuit2::MinosError
me(i,
fMinimum->UserState().Value(i),
low,
up);
739 if (debugLevel >= 1) {
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");
842 std::sort(result.begin(), result.end());
844 for (
unsigned int i = 0;
i < nstep; ++
i) {
845 x[
i] = result[
i].first;
846 y[
i] = result[
i].second;
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());
894 std::vector<std::pair<double, double> >
result = contour(ipar, jpar, npoints);
895 if (result.size() !=
npoints) {
896 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" Invalid result from MnContours");
900 x[
i] = result[
i].first;
901 y[
i] = result[
i].second;
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();
int CovMatrixStatus() const override
bool SetVariable(unsigned int ivar, const std::string &name, double val, double step) override
set free variable
double Correlation(unsigned int i, unsigned int j) const override
bool Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) override
ROOT::Minuit2::MnUserParameterState fState
ROOT::Minuit2::FCNBase * fMinuitFCN
ROOT::Minuit2::FunctionMinimum * fMinimum
HybridMinimizer(EMinimizerType type=kMigrad)
std::string VariableName(unsigned int ivar) const override
get name of variables (override if minimizer support storing of variable names)
void SetFunction(const ROOT::Math::IMultiGenFunction &func) override
set the function to minimize
bool SetVariableValue(unsigned int ivar, double val) override
set variable
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 )
const double * Errors() const override
return errors at the minimum
void SetMinimizerType(EMinimizerType type)
bool GetMinosError(unsigned int i, double &errLow, double &errUp, int=0) override
std::vector< double > fErrors
bool SetFixedVariable(unsigned int, const std::string &, double) override
set fixed variable (override if minimizer supports them )
bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum &min)
examine the minimum result
double GlobalCC(unsigned int i) const override
~HybridMinimizer() override
virtual void SetMinimizer(ROOT::Minuit2::ModularFunctionMinimizer *m)
bool GetCovMatrix(double *cov) const override
Abs< T >::type abs(const T &t)
bool SetVariableValues(const double *val) override
HybridMinimizer & operator=(const HybridMinimizer &rhs)
int TurnOffPrintInfoLevel()
int VariableIndex(const std::string &name) const override
const double * X() const override
return pointer to X values at the minimum
std::vector< double > fValues
void RestoreGlobalPrintLevel(int)
bool GetHessianMatrix(double *h) const override
ROOT::Minuit2::ModularFunctionMinimizer * fMinimizer
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 )
virtual const ROOT::Minuit2::ModularFunctionMinimizer * GetMinimizer() const
double CovMatrix(unsigned int i, unsigned int j) const override
void PrintResults() override
print result of minimization
virtual const ROOT::Minuit2::FCNBase * GetFCN() const
bool Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin=0, double xmax=0) override
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 )