From 8b19015bba7aea13596ceda2316f583579f046dc Mon Sep 17 00:00:00 2001 From: moneta Date: Fri, 20 Oct 2023 20:00:17 +0200 Subject: [PATCH 1/6] [minuit2] Fix searching of a new point in MnContour When searching for a new point between p1 and p2, if MnCross fails, retry using a position closer to p1 instead of the middle. Thsi is what is done in old TMinuit. Minuit2 was trying to switch direction of the search and this was causing finding points in the opposite side of contour and messing up the order. Improve also debugging of MnContour --- math/minuit2/src/MnContours.cxx | 119 +++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 40 deletions(-) diff --git a/math/minuit2/src/MnContours.cxx b/math/minuit2/src/MnContours.cxx index d181c52ba5ea3..17af4c4a34fa3 100644 --- a/math/minuit2/src/MnContours.cxx +++ b/math/minuit2/src/MnContours.cxx @@ -40,6 +40,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int unsigned int nfcn = 0; MnPrint print("MnContours"); + print.Debug("MnContours: finding ",npoints," contours points for ",px,py," at level ",fFCN.Up()," from value ",fMinimum.Fval()); std::vector> result; result.reserve(npoints); @@ -47,50 +48,67 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int // double edmmax = 0.5*0.05*fFCN.Up()*1.e-3; // double toler = 0.05; - double toler = 0.1; // use same default value as in Minos - - // get first four points - // std::cout<<"MnContours: get first 4 params."< ex = meX(); + std::pair ex = mex(); + + print.Debug("Minos error for p0: ",ex.first,ex.second); - MinosError meY = minos.Minos(py); - nfcn += meY.NFcn(); - if (!meY.IsValid()) { + MinosError mey = minos.Minos(py); + nfcn += mey.NFcn(); + if (!mey.IsValid()) { print.Error("unable to find second two points"); - return ContoursError(px, py, result, meX, meY, nfcn); + return ContoursError(px, py, result, mex, mey, nfcn); } - std::pair ey = meY(); + std::pair ey = mey(); - MnMigrad migrad(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1)))); + print.Debug("Minos error for p0: ",ey.first,ey.second); - migrad.Fix(px); - migrad.SetValue(px, valx + ex.second); - FunctionMinimum exy_up = migrad(); - nfcn += exy_up.NFcn(); - if (!exy_up.IsValid()) { - print.Error("unable to find Upper y Value for x Parameter", px); - return ContoursError(px, py, result, meX, meY, nfcn); - } + // if Minos is not at limits we can use migrad to find the other corresponding point coordinate + MnMigrad migrad0(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1)))); - migrad.SetValue(px, valx + ex.first); - FunctionMinimum exy_lo = migrad(); + + // start from minimizing in p1 and fixing p0 to Minos value + migrad0.Fix(px); + migrad0.SetValue(px, valx + ex.first); + FunctionMinimum exy_lo = migrad0(); nfcn += exy_lo.NFcn(); if (!exy_lo.IsValid()) { print.Error("unable to find Lower y Value for x Parameter", px); - return ContoursError(px, py, result, meX, meY, nfcn); + return ContoursError(px, py, result, mex, mey, nfcn); } + print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_lo.UserState().Value(py),"fcn = ",exy_lo.Fval()); + + migrad0.SetValue(px, valx + ex.second); + FunctionMinimum exy_up = migrad0(); + nfcn += exy_up.NFcn(); + if (!exy_up.IsValid()) { + print.Error("unable to find Upper y Value for x Parameter", px); + return ContoursError(px, py, result, mex, mey, nfcn); + } + print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_up.UserState().Value(py),"fcn = ",exy_up.Fval()); + + MnMigrad migrad1(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy() - 1)))); migrad1.Fix(py); migrad1.SetValue(py, valy + ey.second); @@ -98,17 +116,21 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int nfcn += eyx_up.NFcn(); if (!eyx_up.IsValid()) { print.Error("unable to find Upper x Value for y Parameter", py); - return ContoursError(px, py, result, meX, meY, nfcn); + return ContoursError(px, py, result, mex, mey, nfcn); } + print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_up.UserState().Value(px),"fcn = ",eyx_up.Fval()); migrad1.SetValue(py, valy + ey.first); FunctionMinimum eyx_lo = migrad1(); nfcn += eyx_lo.NFcn(); if (!eyx_lo.IsValid()) { print.Error("unable to find Lower x Value for y Parameter", py); - return ContoursError(px, py, result, meX, meY, nfcn); + return ContoursError(px, py, result, mex, mey, nfcn); } + print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_lo.UserState().Value(px),"fcn = ",eyx_lo.Fval()); + + double scalx = 1. / (ex.second - ex.first); double scaly = 1. / (ey.second - ey.first); @@ -119,7 +141,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int MnUserParameterState upar = fMinimum.UserState(); - print.Info("List of found points", '\n', " Parameter x is", upar.Name(px), '\n', " Parameter y is", upar.Name(py), + print.Debug("List of first 4 found contour points", '\n', " Parameter x is", upar.Name(px), '\n', " Parameter y is", upar.Name(py), '\n', result[0], '\n', result[1], '\n', result[2], '\n', result[3]); upar.Fix(px); @@ -130,15 +152,17 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int par[1] = py; MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy); + // find the remaining points of the contour for (unsigned int i = 4; i < npoints; i++) { + // find the two neighbouring points with largest separation auto idist1 = result.end() - 1; auto idist2 = result.begin(); double dx = idist1->first - (idist2)->first; double dy = idist1->second - (idist2)->second; double bigdis = scalx * scalx * dx * dx + scaly * scaly * dy * dy; - for (auto ipair = result.begin(); ipair != result.end() - 1; ++ipair) { + for (auto ipair = result.begin(); ipair != result.end() - 1; ++ipair) { double distx = ipair->first - (ipair + 1)->first; double disty = ipair->second - (ipair + 1)->second; double dist = scalx * scalx * distx * distx + scaly * scaly * disty * disty; @@ -157,11 +181,17 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int if (nfcn > maxcalls) { print.Error("maximum number of function calls exhausted"); - return ContoursError(px, py, result, meX, meY, nfcn); + return ContoursError(px, py, result, mex, mey, nfcn); } + print.Debug("Find new contour point between points with max sep: (",idist1->first,", ",idist1->second,") and (", + idist2->first,", ",idist2->second,") with weights ",a1,a2); + // find next point between the found 2 with max separation + // start from point situated at the middle (a1,a2=0.5) + // and direction double xmidcr = a1 * idist1->first + a2 * (idist2)->first; double ymidcr = a1 * idist1->second + a2 * (idist2)->second; + // direction is the perpendicular one double xdir = (idist2)->second - idist1->second; double ydir = idist1->first - (idist2)->first; double scalfac = sca * std::max(std::fabs(xdir * scalx), std::fabs(ydir * scaly)); @@ -177,30 +207,39 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int MnCross opt = cross(par, pmid, pdir, toler, maxcalls); nfcn += opt.NFcn(); if (!opt.IsValid()) { - // if(a1 > 0.5) { - if (sca < 0.) { + if(a1 > 0.5) { + // LM 20/10/23 : remove switch of direction and look instead closer (this is what is done in TMinuit) + // should we try again closer to P2 (e.g. a1=0.25, a2 = 0.75) if failing? + //if (sca < 0.) { print.Error("unable to find point on Contour", i + 1, '\n', "found only", i, "points"); - return ContoursError(px, py, result, meX, meY, nfcn); + return ContoursError(px, py, result, mex, mey, nfcn); } - // a1 = 0.75; - // a2 = 0.25; - // std::cout<<"*****switch direction"< Date: Fri, 20 Oct 2023 20:18:46 +0200 Subject: [PATCH 2/6] [minuit2] Fix a bug in computing Minos error when close to the limit The computed value of the Minos error was WRONG when parameter+error is over the limit, but the minos point is before the limit. Thsi can happen for example when computing a limit on a fraction parameter that is bound to be less than 1. --- math/minuit2/inc/Minuit2/MinosError.h | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/math/minuit2/inc/Minuit2/MinosError.h b/math/minuit2/inc/Minuit2/MinosError.h index 4f540c0758374..df06b5bbf9825 100644 --- a/math/minuit2/inc/Minuit2/MinosError.h +++ b/math/minuit2/inc/Minuit2/MinosError.h @@ -55,8 +55,16 @@ class MinosError { { if (AtLowerLimit()) return LowerState().Parameter(Parameter()).LowerLimit() - fMinParValue; - if (LowerValid()) - return -1. * LowerState().Error(Parameter()) * (1. + fLower.Value()); + if (LowerValid()) { + // Minos error is value - error - aopt * error where aopt is MnCross.Value() + // If value - error is below the limit, error must be truncated at limit + double err = LowerState().Error(Parameter()); + double lowLimit = LowerState().Parameter(Parameter()).LowerLimit(); + // error is in this case truncated + if (fMinParValue - err < lowLimit) + err = fMinParValue - lowLimit; + return -1. * err * (1. + fLower.Value()); + } // return Hessian Error in case is invalid return -LowerState().Error(Parameter()); } @@ -64,8 +72,16 @@ class MinosError { { if (AtUpperLimit()) return UpperState().Parameter(Parameter()).UpperLimit() - fMinParValue; - if (UpperValid()) - return UpperState().Error(Parameter()) * (1. + fUpper.Value()); + if (UpperValid()) { + // Minos error is value + error + aopt * error where aopt is MnCross.Value() + // If value + error is over the limit, err must be truncated at limit + double err = UpperState().Error(Parameter()); + double upLimit = UpperState().Parameter(Parameter()).UpperLimit(); + // error is in this case truncated + if (fMinParValue + err > upLimit) + err = upLimit - fMinParValue; + return err * (1. + fUpper.Value()); + } // return Hessian Error in case is invalid return UpperState().Error(Parameter()); } From ad882005f4390dd30a756077003a1a3276059654 Mon Sep 17 00:00:00 2001 From: moneta Date: Sat, 21 Oct 2023 19:45:51 +0200 Subject: [PATCH 3/6] [minuit2] Use an value of 1 for the covariance estimated in MnSeed when g2 is zero When g2 is zero better using an arbitrary value of 1 in the covariance then a very large one, which can be problematic. This commit restores what is so far used in the legacy TMinuit --- math/minuit2/src/MnSeedGenerator.cxx | 12 ++++++------ math/minuit2/src/NegativeG2LineSearch.cxx | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/math/minuit2/src/MnSeedGenerator.cxx b/math/minuit2/src/MnSeedGenerator.cxx index aebc0bfc3ccb5..aac6ab3170dd2 100644 --- a/math/minuit2/src/MnSeedGenerator.cxx +++ b/math/minuit2/src/MnSeedGenerator.cxx @@ -69,8 +69,8 @@ operator()(const MnFcn &fcn, const GradientCalculator &gc, const MnUserParameter dcovar = 0.; } else { for (unsigned int i = 0; i < n; i++) - mat(i, i) = (std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : - (dgrad.G2()(i) >= 0) ? 1./prec.Eps2() : -1./prec.Eps2()); + // if G2 is small better using an arbitrary value (e.g. 1) + mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : 1.0; } MinimumError err(mat, dcovar); @@ -177,6 +177,7 @@ MinimumSeed MnSeedGenerator::operator()(const MnFcn &fcn, const AnalyticalGradie // do this only when we have not computed the Hessian or always ? if (!computedHessian) { // check if minimum state has covariance - if not use computed G2 + // should maybe this an option, sometimes is not good to re-use existing covariance if (st.HasCovariance()) { print.Info("Using existing covariance matrix"); for (unsigned int i = 0; i < n; i++) @@ -185,10 +186,9 @@ MinimumSeed MnSeedGenerator::operator()(const MnFcn &fcn, const AnalyticalGradie dcovar = 0.; } else { for (unsigned int i = 0; i < n; i++) { - // should not use a cut-off here like 1./prec.Eps() - mat(i, i) = (std::fabs(grad.G2()(i)) > prec.Eps2() ? 1. / grad.G2()(i) - : (grad.G2()(i) >= 0) ? 1. / prec.Eps2() - : -1. / prec.Eps2()); + // if G2 is very small, better using an arbitrary value (e.g. 1.) + mat(i, i) = std::fabs(grad.G2()(i)) > prec.Eps2() ? 1. / grad.G2()(i) + : 1.0; } dcovar = 1.; } diff --git a/math/minuit2/src/NegativeG2LineSearch.cxx b/math/minuit2/src/NegativeG2LineSearch.cxx index dacee38261aed..af32fbe6db7bf 100644 --- a/math/minuit2/src/NegativeG2LineSearch.cxx +++ b/math/minuit2/src/NegativeG2LineSearch.cxx @@ -121,8 +121,8 @@ MinimumState NegativeG2LineSearch::operator()(const MnFcn &fcn, const MinimumSta print.Debug("Approximate new covariance after NegativeG2LS using only G2"); MnAlgebraicSymMatrix mat(n); for (unsigned int i = 0; i < n; i++) { - mat(i, i) = (std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : - (dgrad.G2()(i) >= 0) ? 1./prec.Eps2() : -1./prec.Eps2()); + mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : + 1; // use an arbitrary value (e.g. 1) } MinimumError err(mat, 1.); From fc1c2e52c4cab14bfe1d869a199676261fbbce38 Mon Sep 17 00:00:00 2001 From: moneta Date: Tue, 24 Oct 2023 17:13:02 +0200 Subject: [PATCH 4/6] [minuit2] Fix in Minos Error for limits needs to take care when limits are not present In this case the limit value is zero, so a special treatment is needed to check if a limit is present or not Add also suggestion by Jonas review --- math/minuit2/inc/Minuit2/MinosError.h | 13 ++++------ math/minuit2/src/MnContours.cxx | 34 +++++++++++++-------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/math/minuit2/inc/Minuit2/MinosError.h b/math/minuit2/inc/Minuit2/MinosError.h index df06b5bbf9825..85b2ea39baad8 100644 --- a/math/minuit2/inc/Minuit2/MinosError.h +++ b/math/minuit2/inc/Minuit2/MinosError.h @@ -59,10 +59,9 @@ class MinosError { // Minos error is value - error - aopt * error where aopt is MnCross.Value() // If value - error is below the limit, error must be truncated at limit double err = LowerState().Error(Parameter()); - double lowLimit = LowerState().Parameter(Parameter()).LowerLimit(); - // error is in this case truncated - if (fMinParValue - err < lowLimit) - err = fMinParValue - lowLimit; + // error is truncated if over the limit + if (LowerState().Parameter(Parameter()).HasLowerLimit()) + err = std::min(err, fMinParValue - LowerState().Parameter(Parameter()).LowerLimit()); return -1. * err * (1. + fLower.Value()); } // return Hessian Error in case is invalid @@ -76,10 +75,8 @@ class MinosError { // Minos error is value + error + aopt * error where aopt is MnCross.Value() // If value + error is over the limit, err must be truncated at limit double err = UpperState().Error(Parameter()); - double upLimit = UpperState().Parameter(Parameter()).UpperLimit(); - // error is in this case truncated - if (fMinParValue + err > upLimit) - err = upLimit - fMinParValue; + if (UpperState().Parameter(Parameter()).HasUpperLimit()) + err = std::min(err, UpperState().Parameter(Parameter()).UpperLimit() - fMinParValue); return err * (1. + fUpper.Value()); } // return Hessian Error in case is invalid diff --git a/math/minuit2/src/MnContours.cxx b/math/minuit2/src/MnContours.cxx index 17af4c4a34fa3..95cd0956c2c25 100644 --- a/math/minuit2/src/MnContours.cxx +++ b/math/minuit2/src/MnContours.cxx @@ -63,23 +63,23 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int print.Debug("Run Minos to find first 4 contour points. Current minimum is : ",valx,valy); - MinosError mex = minos.Minos(px); - nfcn += mex.NFcn(); - if (!mex.IsValid()) { + MinosError mnex = minos.Minos(px); + nfcn += mnex.NFcn(); + if (!mnex.IsValid()) { print.Error("unable to find first two points"); - return ContoursError(px, py, result, mex, mex, nfcn); + return ContoursError(px, py, result, mnex, mnex, nfcn); } - std::pair ex = mex(); + std::pair ex = mnex(); print.Debug("Minos error for p0: ",ex.first,ex.second); - MinosError mey = minos.Minos(py); - nfcn += mey.NFcn(); - if (!mey.IsValid()) { + MinosError mney = minos.Minos(py); + nfcn += mney.NFcn(); + if (!mney.IsValid()) { print.Error("unable to find second two points"); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } - std::pair ey = mey(); + std::pair ey = mney(); print.Debug("Minos error for p0: ",ey.first,ey.second); @@ -94,7 +94,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int nfcn += exy_lo.NFcn(); if (!exy_lo.IsValid()) { print.Error("unable to find Lower y Value for x Parameter", px); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_lo.UserState().Value(py),"fcn = ",exy_lo.Fval()); @@ -104,7 +104,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int nfcn += exy_up.NFcn(); if (!exy_up.IsValid()) { print.Error("unable to find Upper y Value for x Parameter", px); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p1 found for p0 set to ",migrad0.Value(px)," is ",exy_up.UserState().Value(py),"fcn = ",exy_up.Fval()); @@ -116,7 +116,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int nfcn += eyx_up.NFcn(); if (!eyx_up.IsValid()) { print.Error("unable to find Upper x Value for y Parameter", py); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_up.UserState().Value(px),"fcn = ",eyx_up.Fval()); @@ -125,7 +125,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int nfcn += eyx_lo.NFcn(); if (!eyx_lo.IsValid()) { print.Error("unable to find Lower x Value for y Parameter", py); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Minimum p0 found for p1 set to ",migrad1.Value(py)," is ",eyx_lo.UserState().Value(px),"fcn = ",eyx_lo.Fval()); @@ -181,7 +181,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int if (nfcn > maxcalls) { print.Error("maximum number of function calls exhausted"); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } print.Debug("Find new contour point between points with max sep: (",idist1->first,", ",idist1->second,") and (", @@ -212,7 +212,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int // should we try again closer to P2 (e.g. a1=0.25, a2 = 0.75) if failing? //if (sca < 0.) { print.Error("unable to find point on Contour", i + 1, '\n', "found only", i, "points"); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } a1 = 0.75; a2 = 0.25; @@ -239,7 +239,7 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int for (size_t i = 0; i < result.size(); i++) print.Debug("point ",i,result[i]); - return ContoursError(px, py, result, mex, mey, nfcn); + return ContoursError(px, py, result, mnex, mney, nfcn); } } // namespace Minuit2 From 5f7feef9538c22ec7ffd495982c0a98ad3f3d9be Mon Sep 17 00:00:00 2001 From: moneta Date: Tue, 24 Oct 2023 17:18:18 +0200 Subject: [PATCH 5/6] [roofit][tutorials] Do not force using Minuit for contour tutorial After previous commits finding the contour works now in Minuit2 --- tutorials/roofit/rf601_intminuit.C | 3 --- tutorials/roofit/rf601_intminuit.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/tutorials/roofit/rf601_intminuit.C b/tutorials/roofit/rf601_intminuit.C index 8bf5d2e54abc2..77b7f329d621a 100644 --- a/tutorials/roofit/rf601_intminuit.C +++ b/tutorials/roofit/rf601_intminuit.C @@ -54,9 +54,6 @@ void rf601_intminuit() // Create MINUIT interface object RooMinimizer m(*nll); - // The contour algorithm in Minuit2 does not work for this tutorial - m.setMinimizerType("Minuit"); - // Activate verbose logging of MINUIT parameter space stepping m.setVerbose(true); diff --git a/tutorials/roofit/rf601_intminuit.py b/tutorials/roofit/rf601_intminuit.py index 8cb56a0821615..169fecff430bf 100644 --- a/tutorials/roofit/rf601_intminuit.py +++ b/tutorials/roofit/rf601_intminuit.py @@ -46,9 +46,6 @@ # Create MINUIT interface object m = ROOT.RooMinimizer(nll) -# The contour algorithm in Minuit2 does not work for this tutorial -m.setMinimizerType("Minuit") - # Activate verbose logging of MINUIT parameter space stepping m.setVerbose(True) From 0d4ce45db384468b853e0d711746e52c74fa6112 Mon Sep 17 00:00:00 2001 From: moneta Date: Tue, 24 Oct 2023 23:18:53 +0200 Subject: [PATCH 6/6] [minuit2] Use a lower tolerance for deciding if using 1./g2 in the seed covariance Use precision.Eps() instead of precision.Eps2() for threshold for the lower values for the initial seed covariance matrix --- math/minuit2/src/MnSeedGenerator.cxx | 4 ++-- math/minuit2/src/NegativeG2LineSearch.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/math/minuit2/src/MnSeedGenerator.cxx b/math/minuit2/src/MnSeedGenerator.cxx index aac6ab3170dd2..ed942c65294a6 100644 --- a/math/minuit2/src/MnSeedGenerator.cxx +++ b/math/minuit2/src/MnSeedGenerator.cxx @@ -70,7 +70,7 @@ operator()(const MnFcn &fcn, const GradientCalculator &gc, const MnUserParameter } else { for (unsigned int i = 0; i < n; i++) // if G2 is small better using an arbitrary value (e.g. 1) - mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : 1.0; + mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps() ? 1. / dgrad.G2()(i) : 1.0; } MinimumError err(mat, dcovar); @@ -187,7 +187,7 @@ MinimumSeed MnSeedGenerator::operator()(const MnFcn &fcn, const AnalyticalGradie } else { for (unsigned int i = 0; i < n; i++) { // if G2 is very small, better using an arbitrary value (e.g. 1.) - mat(i, i) = std::fabs(grad.G2()(i)) > prec.Eps2() ? 1. / grad.G2()(i) + mat(i, i) = std::fabs(grad.G2()(i)) > prec.Eps() ? 1. / grad.G2()(i) : 1.0; } dcovar = 1.; diff --git a/math/minuit2/src/NegativeG2LineSearch.cxx b/math/minuit2/src/NegativeG2LineSearch.cxx index af32fbe6db7bf..88fe8b3b6112a 100644 --- a/math/minuit2/src/NegativeG2LineSearch.cxx +++ b/math/minuit2/src/NegativeG2LineSearch.cxx @@ -121,7 +121,7 @@ MinimumState NegativeG2LineSearch::operator()(const MnFcn &fcn, const MinimumSta print.Debug("Approximate new covariance after NegativeG2LS using only G2"); MnAlgebraicSymMatrix mat(n); for (unsigned int i = 0; i < n; i++) { - mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps2() ? 1. / dgrad.G2()(i) : + mat(i, i) = std::fabs(dgrad.G2()(i)) > prec.Eps() ? 1. / dgrad.G2()(i) : 1; // use an arbitrary value (e.g. 1) }