60 state.
Edm(),
static_cast<int>(state.
NFcn())}, state.
Trafo());
69 static_cast<int>(state.
NFcn())},
85 unsigned int maxcalls)
const
91 return ComputeAnalytical(mfcn.
Fcn(), st, trafo);
95 return ComputeNumerical(mfcn, st, trafo, maxcalls,
fStrategy);
108 const MnMachinePrecision &prec = trafo.
Precision();
110 std::unique_ptr<AnalyticalGradientCalculator> hc;
112 hc = std::make_unique<ExternalInternalGradientCalculator>(fcn,trafo);
114 hc = std::make_unique<AnalyticalGradientCalculator>(fcn,trafo);
119 print.Error(
"Error computing analytical Hessian. MnHesse fails and will return a null matrix");
124 for (
unsigned int i = 0; i <
n; i++)
131 print.Debug(
"Original error matrix", vhmat);
134 vhmat = tmpErr.InvHessian();
136 print.Debug(
"PosDef error matrix", vhmat);
138 int ifail =
Invert(vhmat);
141 print.Warn(
"Matrix inversion fails; will return diagonal matrix");
144 for (
unsigned int j = 0; j <
n; j++) {
145 tmpsym(j,j) = 1. / g2(j);
154 if (tmpErr.IsMadePosDef()) {
156 double edm = estim.Estimate(
gr,
err);
163 double edm = estim.Estimate(
gr,
err);
165 print.Debug(
"Hessian is ACCURATE. New state:",
"\n First derivative:", st.
Gradient().
Grad(),
166 "\n Covariance matrix:", vhmat,
"\n Edm:", edm);
172 unsigned int maxcalls,
MnStrategy const &strat)
178 ROOT::Math::Util::TimingScope timingScope([&print](std::string
const& s){ print.Info(s); },
"Done after");
184 double amin = mfcnCaller(st.Vec());
185 double aimsag = std::sqrt(prec.Eps2()) * (std::fabs(amin) + mfcn.Up());
189 unsigned int n = st.Parameters().Vec().size();
191 maxcalls = 200 + 100 *
n + 5 *
n *
n;
202 if (st.Gradient().IsAnalytical()) {
203 print.Info(
"Using analytical gradient but a numerical Hessian calculator - it could be not optimal");
210 print.Warn(
"Analytical calculator ",grd,
" numerical ",tmp.Grad(),
" g2 ",g2);
215 print.Debug(
"Gradient is", st.Gradient().IsAnalytical() ?
"analytical" :
"numerical",
"\n point:",
x,
216 "\n fcn :", amin,
"\n grad :", grd,
"\n step :", gst,
"\n g2 :", g2);
218 for (
unsigned int i = 0; i <
n; i++) {
221 double dmin = 8. * prec.Eps2() * (std::fabs(xtf) + prec.Eps2());
222 double d = std::fabs(gst(i));
226 print.Debug(
"Derivative parameter", i,
"d =",
d,
"dmin =", dmin);
228 for (
unsigned int icyc = 0; icyc < strat.HessianNCycles(); icyc++) {
232 for (
unsigned int multpy = 0; multpy < 5; multpy++) {
238 sag = 0.5 * (fs1 + fs2 - 2. * amin);
240 print.Debug(
"cycle", icyc,
"mul", multpy,
"\tsag =", sag,
"d =",
d);
245 if (trafo.Parameter(i).HasLimits()) {
259 print.Warn(
"2nd derivative zero for parameter", trafo.Name(trafo.ExtOfInt(i)),
260 "; MnHesse fails and will return diagonal matrix");
262 for (
unsigned int j = 0; j <
n; j++) {
263 double tmp = g2(j) < prec.Eps2() ? 1. : 1. / g2(j);
264 vhmat(j, j) = tmp < prec.Eps2() ? 1. : tmp;
271 double g2bfor = g2(i);
272 g2(i) = 2. * sag / (
d *
d);
273 grd(i) = (fs1 - fs2) / (2. *
d);
278 d = std::sqrt(2. * aimsag / std::fabs(g2(i)));
279 if (trafo.Parameter(i).HasLimits())
280 d = std::min(0.5,
d);
284 print.Debug(
"g1 =", grd(i),
"g2 =", g2(i),
"step =", gst(i),
"d =",
d,
"diffd =", std::fabs(
d - dlast) /
d,
285 "diffg2 =", std::fabs(g2(i) - g2bfor) / g2(i));
288 if (std::fabs((
d - dlast) /
d) < strat.HessianStepTolerance())
290 if (std::fabs((g2(i) - g2bfor) / g2(i)) < strat.HessianG2Tolerance())
292 d = std::min(
d, 10. * dlast);
293 d = std::max(
d, 0.1 * dlast);
296 if (mfcn.NumOfCalls() > maxcalls) {
299 print.Warn(
"Maximum number of allowed function calls exhausted; will return diagonal matrix");
301 for (
unsigned int j = 0; j <
n; j++) {
302 double tmp = g2(j) < prec.Eps2() ? 1. : 1. / g2(j);
303 vhmat(j, j) = tmp < prec.Eps2() ? 1. : tmp;
307 st.Edm(), mfcn.NumOfCalls());
311 print.Debug(
"Second derivatives", g2);
313 if (strat.RefineGradientInHessian()) {
324 bool doCentralFD = strat.HessianCentralFDMixedDerivatives();
327 unsigned int startParIndexOffDiagonal = mpiprocOffDiagonal.StartElementIndex();
328 unsigned int endParIndexOffDiagonal = mpiprocOffDiagonal.EndElementIndex();
330 unsigned int offsetVect = 0;
331 for (
unsigned int in = 0; in < startParIndexOffDiagonal; in++)
332 if ((in + offsetVect) % (
n - 1) == 0)
333 offsetVect += (in + offsetVect) / (
n - 1);
335 for (
unsigned int in = startParIndexOffDiagonal; in < endParIndexOffDiagonal; in++) {
337 int i = (in + offsetVect) / (
n - 1);
338 if ((in + offsetVect) % (
n - 1) == 0)
340 int j = (in + offsetVect) % (
n - 1) + 1;
342 if ((i + 1) == j || in == startParIndexOffDiagonal)
347 double fs1 = mfcnCaller(
x);
349 double elem = (fs1 + amin - yy(i) - yy(j)) / (dirin(i) * dirin(j));
356 double fs3 = mfcnCaller(
x);
359 double fs4 = mfcnCaller(
x);
362 double fs2 = mfcnCaller(
x);
364 double elem = (fs1 - fs2 - fs3 + fs4)/(4.*dirin(i)*dirin(j));
368 if (j % (
n - 1) == 0 || in == endParIndexOffDiagonal - 1)
372 mpiprocOffDiagonal.SyncSymMatrixOffDiagonal(vhmat);
380 print.Debug(
"Original error matrix", vhmat);
384 if (strat.HessianForcePosDef()) {
385 vhmat = tmpErr.InvHessian();
388 print.Debug(
"PosDef error matrix", vhmat);
390 int ifail =
Invert(vhmat);
393 print.Warn(
"Matrix inversion fails; will return diagonal matrix");
396 for (
unsigned int j = 0; j <
n; j++) {
397 double tmp = g2(j) < prec.Eps2() ? 1. : 1. / g2(j);
398 tmpsym(j, j) = tmp < prec.Eps2() ? 1. : tmp;
409 if (tmpErr.IsMadePosDef()) {
411 double edm = estim.Estimate(
gr,
err);
417 double edm = estim.Estimate(
gr,
err);
419 print.Debug(
"Hessian is ACCURATE. New state:",
"\n First derivative:", grd,
"\n Second derivative:", g2,
420 "\n Gradient step:", gst,
"\n Covariance matrix:", vhmat,
"\n Edm:", edm);
Interface (abstract class) defining the function to be minimized, which has to be implemented by the ...
virtual double Up() const =0
Error definition of the function.
virtual bool HasHessian() const
virtual GradientParameterSpace gradParameterSpace() const
virtual bool HasGradient() const
bool IsAnalytical() const
const MnAlgebraicVector & Grad() const
class holding the full result of the minimization; both internal and external (MnUserParameterState) ...
void Add(const MinimumState &state, Status status=MnValid)
add latest minimization state (for example add Hesse result after Migrad)
const MnUserParameterState & UserState() const
const MinimumState & State() const
HessianGradientCalculator: class to calculate Gradient for Hessian.
unsigned int size() const
MinimumError keeps the inv.
const MnAlgebraicVector & Vec() const
MinimumState keeps the information (position, Gradient, 2nd deriv, etc) after one minimization step (...
const MinimumParameters & Parameters() const
const FunctionGradient & Gradient() const
Wrapper class to FCNBase interface used internally by Minuit.
const FCNBase & Fcn() const
MnUserParameterState operator()(const FCNBase &, const MnUserParameterState &, unsigned int maxcalls=0) const
FCN + MnUserParameterState.
Sets the relative floating point (double) arithmetic precision.
Force the covariance matrix to be positive defined by adding extra terms in the diagonal.
API class for defining four levels of strategies: low (0), medium (1), high (2), very high (>=3); act...
class which holds the external user and/or internal Minuit representation of the parameters and error...
unsigned int NFcn() const
unsigned int VariableParameters() const
const std::vector< double > & IntParameters() const
const MnUserTransformation & Trafo() const
class performing the numerical gradient calculation
int Invert(LASymMatrix &)
LAVector MnAlgebraicVector
LASymMatrix MnAlgebraicSymMatrix