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;
98 if (algoname ==
"simplex") algoType =
kSimplex;
99 if (algoname ==
"minimize" ) algoType =
kCombined;
100 if (algoname ==
"scan" ) algoType =
kScan;
101 if (algoname ==
"fumili" ) algoType =
kFumili;
115 SetMinimizer(
new ROOT::Minuit2::VariableMetricMinimizer() );
133 SetMinimizer(
new ROOT::Minuit2::VariableMetricMinimizer() );
147 ROOT::Math::Minimizer()
155 if (
this == &rhs)
return *
this;
162 fState = MnUserParameterState();
181 std::string txtmsg =
"Parameter " + name +
" has zero or invalid step size - consider it as constant ";
182 MN_INFO_MSG2(
"HybridMinimizer::SetVariable",txtmsg);
186 fState.Add(name, val, step);
188 unsigned int minuit2Index =
fState.Index(name );
189 if ( minuit2Index != ivar) {
190 std::string txtmsg(
"Wrong index used for the variable " + name);
191 MN_INFO_MSG2(
"HybridMinimizer::SetVariable",txtmsg);
192 MN_INFO_VAL2(
"HybridMinimizer::SetVariable",minuit2Index);
195 fState.RemoveLimits(ivar);
202 if (!
SetVariable(ivar, name, val, step) )
return false;
203 fState.SetLowerLimit(ivar, lower);
209 if (!
SetVariable(ivar, name, val, step) )
return false;
210 fState.SetUpperLimit(ivar, upper);
218 if (!
SetVariable(ivar, name, val, step) )
return false;
219 fState.SetLimits(ivar, lower, upper);
229 ivar =
fState.Index(name );
238 return fState.GetName(ivar);
245 return fState.Trafo().FindIndex(name);
251 if (ivar >=
fState.MinuitParameters().size() )
return false;
252 fState.SetValue(ivar, val);
258 unsigned int n =
fState.MinuitParameters().size();
259 if (n== 0)
return false;
260 for (
unsigned int ivar = 0; ivar <
n; ++ivar)
261 fState.SetValue(ivar, x[ivar]);
271 fMinuitFCN =
new ROOT::Minuit2::FCNAdapter<ROOT::Math::IMultiGenFunction> (
func, ErrorDef() );
275 const ROOT::Math::FitMethodFunction * fcnfunc =
dynamic_cast<const ROOT::Math::FitMethodFunction *
>(&
func);
277 MN_ERROR_MSG(
"HybridMinimizer: Wrong Fit method function for Fumili");
280 fMinuitFCN =
new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodFunction> (*fcnfunc,
fDim, ErrorDef() );
289 fMinuitFCN =
new ROOT::Minuit2::FCNGradAdapter<ROOT::Math::IMultiGradFunction> (
func, ErrorDef() );
293 const ROOT::Math::FitMethodGradFunction * fcnfunc =
dynamic_cast<const ROOT::Math::FitMethodGradFunction*
>(&
func);
295 MN_ERROR_MSG(
"HybridMinimizer: Wrong Fit method function for Fumili");
298 fMinuitFCN =
new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodGradFunction> (*fcnfunc,
fDim, ErrorDef() );
306 MN_ERROR_MSG2(
"HybridMinimizer::Minimize",
"FCN function has not been set");
317 int maxfcn = MaxFunctionCalls();
319 int strategyLevel = Strategy();
337 MnPrint::SetLevel(PrintLevel() );
343 if (Precision() > 0)
fState.SetPrecision(Precision());
346 ROOT::Minuit2::MnStrategy strategy(strategyLevel);
347 ROOT::Math::IOptions * minuit2Opt = ROOT::Math::MinimizerOptions::FindDefault(
"Minuit2");
350 int nGradCycles = strategy.GradientNCycles();
351 int nHessCycles = strategy.HessianNCycles();
352 int nHessGradCycles = strategy.HessianGradientNCycles();
354 double gradTol = strategy.GradientTolerance();
355 double gradStepTol = strategy.GradientStepTolerance();
356 double hessStepTol = strategy.HessianStepTolerance();
357 double hessG2Tol = strategy.HessianG2Tolerance();
359 minuit2Opt->GetValue(
"GradientNCycles",nGradCycles);
360 minuit2Opt->GetValue(
"HessianNCycles",nHessCycles);
361 minuit2Opt->GetValue(
"HessianGradientNCycles",nHessGradCycles);
363 minuit2Opt->GetValue(
"GradientTolerance",gradTol);
364 minuit2Opt->GetValue(
"GradientStepTolerance",gradStepTol);
365 minuit2Opt->GetValue(
"HessianStepTolerance",hessStepTol);
366 minuit2Opt->GetValue(
"HessianG2Tolerance",hessG2Tol);
368 strategy.SetGradientNCycles(nGradCycles);
369 strategy.SetHessianNCycles(nHessCycles);
370 strategy.SetHessianGradientNCycles(nHessGradCycles);
372 strategy.SetGradientTolerance(gradTol);
373 strategy.SetGradientStepTolerance(gradStepTol);
374 strategy.SetHessianStepTolerance(hessStepTol);
375 strategy.SetHessianG2Tolerance(hessStepTol);
377 if (PrintLevel() > 0) {
384 const ROOT::Minuit2::FCNGradientBase * gradFCN =
dynamic_cast<const ROOT::Minuit2::FCNGradientBase *
>(
fMinuitFCN );
385 if ( gradFCN !=
nullptr) {
388 ROOT::Minuit2::FunctionMinimum
min =
GetMinimizer()->Minimize(*gradFCN,
fState, strategy, maxfcn, tol);
389 fMinimum =
new ROOT::Minuit2::FunctionMinimum (min);
393 fMinimum =
new ROOT::Minuit2::FunctionMinimum (min);
397 if (
fMinimum->IsValid() && IsValidError() &&
fMinimum->State().Error().Dcovar() != 0 ) {
399 ROOT::Minuit2::MnHesse hesse(strategy );
417 if (debugLevel >= 3) {
439 if (min.HasMadePosDefCovar() ) {
440 txt =
"Covar was made pos def";
443 if (min.HesseFailed() ) {
444 txt =
"Hesse is not valid";
447 if (min.IsAboveMaxEdm() ) {
448 txt =
"Edm is above max";
451 if (min.HasReachedCallLimit() ) {
452 txt =
"Reached call limit";
457 bool validMinimum = min.IsValid();
460 if (fStatus != 0 && debugLevel > 0) MN_INFO_MSG2(
"HybridMinimizer::Minimize",txt);
466 txt =
"unknown failure";
470 MN_INFO_MSG2(
"HybridMinimizer::Minimize",msg);
514 const std::vector<MinuitParameter> & paramsObj =
fState.MinuitParameters();
515 if (paramsObj.empty())
return nullptr;
516 assert(
fDim == paramsObj.size());
520 for (
unsigned int i = 0;
i <
fDim; ++
i) {
530 const std::vector<MinuitParameter> & paramsObj =
fState.MinuitParameters();
531 if (paramsObj.empty())
return nullptr;
532 assert(
fDim == paramsObj.size());
536 for (
unsigned int i = 0;
i <
fDim; ++
i) {
537 const MinuitParameter & par = paramsObj[
i];
538 if (par.IsFixed() || par.IsConst() )
550 if ( i >=
fDim || i >=
fDim)
return 0;
551 if ( !
fState.HasCovariance() )
return 0;
552 if (
fState.Parameter(i).IsFixed() ||
fState.Parameter(i).IsConst() )
return 0;
553 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
return 0;
554 unsigned int k =
fState.IntOfExt(i);
555 unsigned int l =
fState.IntOfExt(j);
561 if ( !
fState.HasCovariance() )
return false;
562 for (
unsigned int i = 0;
i <
fDim; ++
i) {
563 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst() ) {
564 for (
unsigned int j = 0; j <
fDim; ++j) { cov[
i*fDim + j] = 0; }
568 unsigned int l =
fState.IntOfExt(
i);
569 for (
unsigned int j = 0; j <
fDim; ++j) {
572 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
577 unsigned int m =
fState.IntOfExt(j);
589 if ( !
fState.HasCovariance() )
return false;
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) { hess[
i*fDim + j] = 0; }
595 unsigned int l =
fState.IntOfExt(
i);
596 for (
unsigned int j = 0; j <
fDim; ++j) {
599 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
604 unsigned int m =
fState.IntOfExt(j);
617 if ( i >=
fDim || i >=
fDim)
return 0;
618 if ( !
fState.HasCovariance() )
return 0;
619 if (
fState.Parameter(i).IsFixed() ||
fState.Parameter(i).IsConst() )
return 0;
620 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
return 0;
621 unsigned int k =
fState.IntOfExt(i);
622 unsigned int l =
fState.IntOfExt(j);
623 double cij =
fState.IntCovariance()(
k,
l);
625 if (tmp > 0 )
return cij/
tmp;
634 if ( i >=
fDim || i >=
fDim)
return 0;
636 if ( !
fState.HasGlobalCC() )
return 0;
637 if (
fState.Parameter(i).IsFixed() ||
fState.Parameter(i).IsConst() )
return 0;
638 unsigned int k =
fState.IntOfExt(i);
639 return fState.GlobalCC().GlobalCC()[
k];
648 errLow = 0; errUp = 0;
649 bool runLower = runopt != 2;
650 bool runUpper = runopt != 1;
655 if (
fState.Parameter(i).IsConst() ||
fState.Parameter(i).IsFixed() ) {
661 MnPrint::SetLevel( debugLevel );
669 MN_ERROR_MSG(
"HybridMinimizer::GetMinosErrors: failed - no function minimum existing");
674 MN_ERROR_MSG(
"HybridMinimizer::MINOS failed due to invalid function minimum");
687 if (Precision() > 0)
fState.SetPrecision(Precision());
695 int maxfcn = MaxFunctionCalls();
718 if (runLower) low = minos.Loval(i,maxfcn,tol);
719 if (runUpper) up = minos.Upval(i,maxfcn,tol);
721 ROOT::Minuit2::MinosError me(i,
fMinimum->UserState().Value(i),low,
up);
729 if (debugLevel >= 1) {
759 bool lowerInvalid = (runLower && !me.LowerValid() );
760 bool upperInvalid = (runUpper && !me.UpperValid() );
762 if (lowerInvalid || upperInvalid ) {
770 if (me.AtLowerMaxFcn() ) mstatus |= 4;
771 if (me.LowerNewMin() ) mstatus |= 8;
775 if (me.AtUpperMaxFcn() ) mstatus |= 4;
776 if (me.UpperNewMin() ) mstatus |= 8;
779 fStatus += 10*mstatus;
785 bool isValid = (runLower && me.LowerValid() ) || (runUpper && me.UpperValid() );
796 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Function must be set before using Scan");
800 if ( ipar >
fState.MinuitParameters().size() ) {
801 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Invalid number. Minimizer variables must be set before using Scan");
808 MnPrint::SetLevel( PrintLevel() );
812 if (Precision() > 0)
fState.SetPrecision(Precision());
815 double amin = scan.Fval();
818 std::vector<std::pair<double, double> >
result = scan(ipar, nstep-1, xmin, xmax);
822 if (result.size() != nstep) {
823 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Invalid result from MnParameterScan");
827 std::sort(result.begin(), result.end() );
830 for (
unsigned int i = 0;
i < nstep; ++
i ) {
831 x[
i] = result[
i].first;
832 y[
i] = result[
i].second;
837 if (scan.Fval() < amin ) {
838 if (PrintLevel() > 0) MN_INFO_MSG2(
"HybridMinimizer::Scan",
"A new minimum has been found");
839 fState.SetValue(ipar, scan.Parameters().Value(ipar) );
851 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" no function minimum existing. Must minimize function before");
856 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
"Invalid function minimum");
869 MnPrint::SetLevel( PrintLevel() );
872 if (Precision() > 0)
fState.SetPrecision(Precision());
879 std::vector<std::pair<double,double> >
result = contour(ipar,jpar, npoints);
880 if (result.size() !=
npoints) {
881 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" Invalid result from MnContours");
885 x[
i] = result[
i].first;
886 y[
i] = result[
i].second;
902 MN_ERROR_MSG2(
"HybridMinimizer::Hesse",
"FCN function has not been set");
906 int strategy = Strategy();
907 int maxfcn = MaxFunctionCalls();
912 MnPrint::SetLevel( PrintLevel() );
915 if (Precision() > 0)
fState.SetPrecision(Precision());
917 ROOT::Minuit2::MnHesse hesse( strategy );
934 if (PrintLevel() >= 3) {
939 if (!
fState.HasCovariance() ) {
941 if (PrintLevel() > 0) MN_INFO_MSG2(
"HybridMinimizer::Hesse",
"Hesse failed ");
946 if (
fMinimum->Error().HesseFailed() ) hstatus = 1;
947 if (
fMinimum->Error().InvertFailed() ) hstatus = 2;
948 else if (!(
fMinimum->Error().IsPosDef()) ) hstatus = 3;
950 fStatus += 100*hstatus;
967 if (
fMinimum->HasAccurateCovar() )
return 3;
968 else if (
fMinimum->HasMadePosDefCovar() )
return 2;
969 else if (
fMinimum->HasValidCovariance() )
return 1;
970 else if (
fMinimum->HasCovariance() )
return 0;
975 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)
std::vector< std::vector< double > > tmp
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 )