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"
48 using namespace ROOT::Minuit2;
54 int prevErrorIgnoreLevel = gErrorIgnoreLevel;
55 if (prevErrorIgnoreLevel < 1001) {
56 gErrorIgnoreLevel = 1001;
57 return prevErrorIgnoreLevel;
63 gErrorIgnoreLevel =
value;
95 std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower );
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);
183 fState.Add(name.c_str(), val);
188 unsigned int minuit2Index =
fState.Index(name.c_str() );
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);
196 fState.RemoveLimits(ivar);
203 if (!
SetVariable(ivar, name, val, step) )
return false;
204 fState.SetLowerLimit(ivar, lower);
210 if (!
SetVariable(ivar, name, val, step) )
return false;
211 fState.SetUpperLimit(ivar, upper);
219 if (!
SetVariable(ivar, name, val, step) )
return false;
220 fState.SetLimits(ivar, lower, upper);
230 ivar =
fState.Index(name.c_str() );
239 return fState.GetName(ivar);
246 return fState.Trafo().FindIndex(name);
252 if (ivar >=
fState.MinuitParameters().size() )
return false;
253 fState.SetValue(ivar, val);
259 unsigned int n =
fState.MinuitParameters().size();
260 if (n== 0)
return false;
261 for (
unsigned int ivar = 0; ivar <
n; ++ivar)
262 fState.SetValue(ivar, x[ivar]);
272 fMinuitFCN =
new ROOT::Minuit2::FCNAdapter<ROOT::Math::IMultiGenFunction> (func, ErrorDef() );
276 const ROOT::Math::FitMethodFunction * fcnfunc =
dynamic_cast<const ROOT::Math::FitMethodFunction *
>(&func);
278 MN_ERROR_MSG(
"HybridMinimizer: Wrong Fit method function for Fumili");
281 fMinuitFCN =
new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodFunction> (*fcnfunc,
fDim, ErrorDef() );
290 fMinuitFCN =
new ROOT::Minuit2::FCNGradAdapter<ROOT::Math::IMultiGradFunction> (func, ErrorDef() );
294 const ROOT::Math::FitMethodGradFunction * fcnfunc =
dynamic_cast<const ROOT::Math::FitMethodGradFunction*
>(&func);
296 MN_ERROR_MSG(
"HybridMinimizer: Wrong Fit method function for Fumili");
299 fMinuitFCN =
new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodGradFunction> (*fcnfunc,
fDim, ErrorDef() );
307 MN_ERROR_MSG2(
"HybridMinimizer::Minimize",
"FCN function has not been set");
318 int maxfcn = MaxFunctionCalls();
319 double tol = Tolerance();
320 int strategyLevel = Strategy();
323 if (PrintLevel() >=1) {
325 int maxfcn_used = maxfcn;
326 if (maxfcn_used == 0) {
327 int nvar =
fState.VariableParameters();
328 maxfcn_used = 200 + 100*nvar + 5*nvar*nvar;
336 MnPrint::SetLevel(PrintLevel() );
342 if (Precision() > 0)
fState.SetPrecision(Precision());
345 ROOT::Minuit2::MnStrategy strategy(strategyLevel);
346 ROOT::Math::IOptions * minuit2Opt = ROOT::Math::MinimizerOptions::FindDefault(
"Minuit2");
349 int nGradCycles = strategy.GradientNCycles();
350 int nHessCycles = strategy.HessianNCycles();
351 int nHessGradCycles = strategy.HessianGradientNCycles();
353 double gradTol = strategy.GradientTolerance();
354 double gradStepTol = strategy.GradientStepTolerance();
355 double hessStepTol = strategy.HessianStepTolerance();
356 double hessG2Tol = strategy.HessianG2Tolerance();
358 minuit2Opt->GetValue(
"GradientNCycles",nGradCycles);
359 minuit2Opt->GetValue(
"HessianNCycles",nHessCycles);
360 minuit2Opt->GetValue(
"HessianGradientNCycles",nHessGradCycles);
362 minuit2Opt->GetValue(
"GradientTolerance",gradTol);
363 minuit2Opt->GetValue(
"GradientStepTolerance",gradStepTol);
364 minuit2Opt->GetValue(
"HessianStepTolerance",hessStepTol);
365 minuit2Opt->GetValue(
"HessianG2Tolerance",hessG2Tol);
367 strategy.SetGradientNCycles(nGradCycles);
368 strategy.SetHessianNCycles(nHessCycles);
369 strategy.SetHessianGradientNCycles(nHessGradCycles);
371 strategy.SetGradientTolerance(gradTol);
372 strategy.SetGradientStepTolerance(gradStepTol);
373 strategy.SetHessianStepTolerance(hessStepTol);
374 strategy.SetHessianG2Tolerance(hessStepTol);
376 if (PrintLevel() > 0) {
383 const ROOT::Minuit2::FCNGradientBase * gradFCN =
dynamic_cast<const ROOT::Minuit2::FCNGradientBase *
>(
fMinuitFCN );
387 ROOT::Minuit2::FunctionMinimum
min =
GetMinimizer()->Minimize(*gradFCN,
fState, strategy, maxfcn, tol);
388 fMinimum =
new ROOT::Minuit2::FunctionMinimum (min);
392 fMinimum =
new ROOT::Minuit2::FunctionMinimum (min);
396 if (
fMinimum->IsValid() && IsValidError() &&
fMinimum->State().Error().Dcovar() != 0 ) {
398 ROOT::Minuit2::MnHesse hesse(strategy );
415 int debugLevel = PrintLevel();
416 if (debugLevel >= 3) {
438 if (min.HasMadePosDefCovar() ) {
439 txt =
"Covar was made pos def";
442 if (min.HesseFailed() ) {
443 txt =
"Hesse is not valid";
446 if (min.IsAboveMaxEdm() ) {
447 txt =
"Edm is above max";
450 if (min.HasReachedCallLimit() ) {
451 txt =
"Reached call limit";
456 bool validMinimum = min.IsValid();
459 if (fStatus != 0 && debugLevel > 0) MN_INFO_MSG2(
"HybridMinimizer::Minimize",txt);
465 txt =
"unknown failure";
469 MN_INFO_MSG2(
"HybridMinimizer::Minimize",msg);
513 const std::vector<MinuitParameter> & paramsObj =
fState.MinuitParameters();
514 if (paramsObj.size() == 0)
return 0;
515 assert(
fDim == paramsObj.size());
519 for (
unsigned int i = 0;
i <
fDim; ++
i) {
529 const std::vector<MinuitParameter> & paramsObj =
fState.MinuitParameters();
530 if (paramsObj.size() == 0)
return 0;
531 assert(
fDim == paramsObj.size());
535 for (
unsigned int i = 0;
i <
fDim; ++
i) {
536 const MinuitParameter & par = paramsObj[
i];
537 if (par.IsFixed() || par.IsConst() )
549 if ( i >=
fDim || i >=
fDim)
return 0;
550 if ( !
fState.HasCovariance() )
return 0;
551 if (
fState.Parameter(i).IsFixed() ||
fState.Parameter(i).IsConst() )
return 0;
552 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
return 0;
553 unsigned int k =
fState.IntOfExt(i);
554 unsigned int l =
fState.IntOfExt(j);
560 if ( !
fState.HasCovariance() )
return false;
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) { cov[
i*fDim +
j] = 0; }
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);
588 if ( !
fState.HasCovariance() )
return false;
589 for (
unsigned int i = 0;
i <
fDim; ++
i) {
590 if (
fState.Parameter(
i).IsFixed() ||
fState.Parameter(
i).IsConst() ) {
591 for (
unsigned int j = 0;
j <
fDim; ++
j) { hess[
i*fDim +
j] = 0; }
594 unsigned int l =
fState.IntOfExt(
i);
595 for (
unsigned int j = 0;
j <
fDim; ++
j) {
598 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
603 unsigned int m =
fState.IntOfExt(j);
616 if ( i >=
fDim || i >=
fDim)
return 0;
617 if ( !
fState.HasCovariance() )
return 0;
618 if (
fState.Parameter(i).IsFixed() ||
fState.Parameter(i).IsConst() )
return 0;
619 if (
fState.Parameter(j).IsFixed() ||
fState.Parameter(j).IsConst() )
return 0;
620 unsigned int k =
fState.IntOfExt(i);
621 unsigned int l =
fState.IntOfExt(j);
622 double cij =
fState.IntCovariance()(
k,
l);
624 if (tmp > 0 )
return cij/
tmp;
633 if ( i >=
fDim || i >=
fDim)
return 0;
635 if ( !
fState.HasGlobalCC() )
return 0;
636 if (
fState.Parameter(i).IsFixed() ||
fState.Parameter(i).IsConst() )
return 0;
637 unsigned int k =
fState.IntOfExt(i);
638 return fState.GlobalCC().GlobalCC()[
k];
647 errLow = 0; errUp = 0;
648 bool runLower = runopt != 2;
649 bool runUpper = runopt != 1;
654 if (
fState.Parameter(i).IsConst() ||
fState.Parameter(i).IsFixed() ) {
658 int debugLevel = PrintLevel();
660 MnPrint::SetLevel( debugLevel );
668 MN_ERROR_MSG(
"HybridMinimizer::GetMinosErrors: failed - no function minimum existing");
673 MN_ERROR_MSG(
"HybridMinimizer::MINOS failed due to invalid function minimum");
686 if (Precision() > 0)
fState.SetPrecision(Precision());
694 int maxfcn = MaxFunctionCalls();
695 double tol = Tolerance();
704 if (PrintLevel() >=1) {
706 int maxfcn_used = maxfcn;
707 if (maxfcn_used == 0) {
708 int nvar =
fState.VariableParameters();
709 maxfcn_used = 2*(nvar+1)*(200 + 100*nvar + 5*nvar*nvar);
716 if (runLower) low = minos.Loval(i,maxfcn,tol);
717 if (runUpper) up = minos.Upval(i,maxfcn,tol);
719 ROOT::Minuit2::MinosError me(i,
fMinimum->UserState().Value(i),low,
up);
727 if (debugLevel >= 1) {
757 bool lowerInvalid = (runLower && !me.LowerValid() );
758 bool upperInvalid = (runUpper && !me.UpperValid() );
760 if (lowerInvalid || upperInvalid ) {
768 if (me.AtLowerMaxFcn() ) mstatus |= 4;
769 if (me.LowerNewMin() ) mstatus |= 8;
773 if (me.AtUpperMaxFcn() ) mstatus |= 4;
774 if (me.UpperNewMin() ) mstatus |= 8;
777 fStatus += 10*mstatus;
783 bool isValid = (runLower && me.LowerValid() ) || (runUpper && me.UpperValid() );
794 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Function must be set before using Scan");
798 if ( ipar >
fState.MinuitParameters().size() ) {
799 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Invalid number. Minimizer variables must be set before using Scan");
806 MnPrint::SetLevel( PrintLevel() );
810 if (Precision() > 0)
fState.SetPrecision(Precision());
813 double amin = scan.Fval();
816 std::vector<std::pair<double, double> >
result = scan(ipar, nstep-1, xmin, xmax);
820 if (result.size() != nstep) {
821 MN_ERROR_MSG2(
"HybridMinimizer::Scan",
" Invalid result from MnParameterScan");
825 std::sort(result.begin(), result.end() );
828 for (
unsigned int i = 0;
i < nstep; ++
i ) {
829 x[
i] = result[
i].first;
830 y[
i] = result[
i].second;
835 if (scan.Fval() < amin ) {
836 if (PrintLevel() > 0) MN_INFO_MSG2(
"HybridMinimizer::Scan",
"A new minimum has been found");
837 fState.SetValue(ipar, scan.Parameters().Value(ipar) );
849 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" no function minimum existing. Must minimize function before");
854 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
"Invalid function minimum");
867 MnPrint::SetLevel( PrintLevel() );
870 if (Precision() > 0)
fState.SetPrecision(Precision());
877 std::vector<std::pair<double,double> >
result = contour(ipar,jpar, npoints);
878 if (result.size() != npoints) {
879 MN_ERROR_MSG2(
"HybridMinimizer::Contour",
" Invalid result from MnContours");
882 for (
unsigned int i = 0;
i < npoints; ++
i ) {
883 x[
i] = result[
i].first;
884 y[
i] = result[
i].second;
900 MN_ERROR_MSG2(
"HybridMinimizer::Hesse",
"FCN function has not been set");
904 int strategy = Strategy();
905 int maxfcn = MaxFunctionCalls();
910 MnPrint::SetLevel( PrintLevel() );
913 if (Precision() > 0)
fState.SetPrecision(Precision());
915 ROOT::Minuit2::MnHesse hesse( strategy );
932 if (PrintLevel() >= 3) {
937 if (!
fState.HasCovariance() ) {
939 if (PrintLevel() > 0) MN_INFO_MSG2(
"HybridMinimizer::Hesse",
"Hesse failed ");
944 if (
fMinimum->Error().HesseFailed() ) hstatus = 1;
945 if (
fMinimum->Error().InvertFailed() ) hstatus = 2;
946 else if (!(
fMinimum->Error().IsPosDef()) ) hstatus = 3;
948 fStatus += 100*hstatus;
965 if (
fMinimum->HasAccurateCovar() )
return 3;
966 else if (
fMinimum->HasMadePosDefCovar() )
return 2;
967 else if (
fMinimum->HasValidCovariance() )
return 1;
968 else if (
fMinimum->HasCovariance() )
return 0;
973 return fState.CovarianceStatus();
virtual bool GetHessianMatrix(double *h) const
virtual bool GetMinosError(unsigned int i, double &errLow, double &errUp, int=0)
virtual bool SetVariableValue(unsigned int ivar, double val)
set variable
ROOT::Minuit2::MnUserParameterState fState
ROOT::Minuit2::FCNBase * fMinuitFCN
ROOT::Minuit2::FunctionMinimum * fMinimum
HybridMinimizer(EMinimizerType type=kMigrad)
virtual double Correlation(unsigned int i, unsigned int j) const
virtual const double * X() const
return pointer to X values at the minimum
void SetMinimizerType(EMinimizerType type)
virtual bool SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower)
set lower limit variable (override if minimizer supports them )
std::vector< double > fErrors
bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum &min)
examine the minimum result
virtual bool Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin=0, double xmax=0)
virtual void SetMinimizer(ROOT::Minuit2::ModularFunctionMinimizer *m)
virtual std::string VariableName(unsigned int ivar) const
get name of variables (override if minimizer support storing of variable names)
Abs< T >::type abs(const T &t)
virtual ~HybridMinimizer()
virtual bool SetFixedVariable(unsigned int, const std::string &, double)
set fixed variable (override if minimizer supports them )
virtual int VariableIndex(const std::string &name) const
HybridMinimizer & operator=(const HybridMinimizer &rhs)
int TurnOffPrintInfoLevel()
virtual void SetFunction(const ROOT::Math::IMultiGenFunction &func)
set the function to minimize
std::vector< double > fValues
virtual bool SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper)
set upper limit variable (override if minimizer supports them )
virtual void PrintResults()
print result of minimization
void RestoreGlobalPrintLevel(int)
std::vector< std::vector< double > > tmp
ROOT::Minuit2::ModularFunctionMinimizer * fMinimizer
virtual bool SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double, double)
set upper/lower limited variable (override if minimizer supports them )
virtual bool Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj)
virtual bool SetVariableValues(const double *val)
virtual double GlobalCC(unsigned int i) const
virtual bool SetVariable(unsigned int ivar, const std::string &name, double val, double step)
set free variable
virtual const ROOT::Minuit2::ModularFunctionMinimizer * GetMinimizer() const
virtual bool GetCovMatrix(double *cov) const
virtual int CovMatrixStatus() const
virtual const ROOT::Minuit2::FCNBase * GetFCN() const
virtual double CovMatrix(unsigned int i, unsigned int j) const
virtual const double * Errors() const
return errors at the minimum