28 std::span<const double> pdir,
double tlr,
unsigned int maxcalls)
const
36 unsigned int npar = par.size();
37 unsigned int nfcn = 0;
40 double mgr_tlr = 0.5 * tlr;
47 double tlf = tlr * up;
49 unsigned int maxitr = 30;
51 double aminsv =
fFval;
52 double aim = aminsv + up;
56 std::array<double, 3> alsb{0., 0., 0.};
57 std::array<double, 3> flsb{0., 0., 0.};
59 MnPrint print(
"MnFunctionCross");
61 print.
Debug([&](std::ostream &os) {
62 for (
unsigned int i = 0; i < par.size(); ++i)
63 os <<
"Parameter " << par[i] <<
" value " << pmid[i] <<
" dir " << pdir[i] <<
" function min = " << aminsv
64 <<
" contour value aim = (fmin + up) = " << aim;
70 for (
unsigned int i = 0; i < par.size(); i++) {
71 unsigned int kex = par[i];
73 double zmid = pmid[i];
74 double zdir = pdir[i];
84 aulim = std::min(aulim, (zlim - zmid) / zdir);
93 aulim = std::min(aulim, (zlim - zmid) / zdir);
98 print.
Debug(
"Largest allowed aulim", aulim);
101 if (limset && npar == 1) {
102 print.
Warn(
"Parameter is at limit", pmid[0],
"delta", pdir[0]);
106 if (aulim < aopt + tla)
111 print.
Info([&](std::ostream &os) {
112 os <<
"Run Migrad with fixed parameters:";
113 for (
unsigned i = 0; i < npar; ++i)
114 os <<
"\n Pos " << par[i] <<
": " <<
fState.
Name(par[i]) <<
" = " << pmid[i];
117 for (
unsigned int i = 0; i < npar; i++)
130 print.
Warn(
"New minimum found while scanning parameter", par.front(),
"new value =", min0.
Fval(),
131 "old value =",
fFval);
138 if (limset ==
true && min0.
Fval() < aim)
143 flsb[0] = min0.
Fval();
144 flsb[0] = std::max(flsb[0], aminsv + 0.1 * up);
145 aopt = std::sqrt(up / (flsb[0] - aminsv)) - 1.;
146 if (std::fabs(flsb[0] - aim) < tlf)
159 print.
Debug(
"flsb[0]", flsb[0],
"aopt", aopt);
161 print.
Info([&](std::ostream &os) {
162 os <<
"Run Migrad again (2nd) with fixed parameters:";
163 for (
unsigned i = 0; i < npar; ++i)
164 os <<
"\n Pos " << par[i] <<
": " <<
fState.
Name(par[i]) <<
" = " << pmid[i] + (aopt)*pdir[i];
167 for (
unsigned int i = 0; i < npar; i++)
168 migrad.
SetValue(par[i], pmid[i] + (aopt)*pdir[i]);
181 if (limset ==
true && min1.
Fval() < aim)
186 flsb[1] = min1.
Fval();
187 double dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
189 print.
Debug(
"aopt", aopt,
"min1Val", flsb[1],
"dfda", dfda);
194 print.
Debug(
"dfda < 0 - iterate from", ipt,
"to max of", maxitr);
197 unsigned int maxlk = maxitr - ipt;
198 for (
unsigned int it = 0; it < maxlk; it++) {
202 aopt = alsb[0] + 0.2 * (it + 1);
209 print.
Info([&](std::ostream &os) {
210 os <<
"Run Migrad again (iteration " << it <<
" ) :";
211 for (
unsigned i = 0; i < npar; ++i)
212 os <<
"\n parameter " << par[i] <<
" (" <<
fState.
Name(par[i]) <<
") fixed to "
213 << pmid[i] + (aopt)*pdir[i];
216 for (
unsigned int i = 0; i < npar; i++)
217 migrad.
SetValue(par[i], pmid[i] + (aopt)*pdir[i]);
219 min1 = migrad(maxcalls, mgr_tlr);
230 if (limset ==
true && min1.
Fval() < aim)
234 flsb[1] = min1.
Fval();
235 dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
238 print.
Debug(
"aopt", aopt,
"min1Val", flsb[1],
"dfda", dfda);
251 aopt = alsb[1] + (aim - flsb[1]) / dfda;
253 print.
Debug(
"dfda > 0 : aopt", aopt);
255 double fdist = std::min(std::fabs(aim - flsb[0]), std::fabs(aim - flsb[1]));
256 double adist = std::min(std::fabs(aopt - alsb[0]), std::fabs(aopt - alsb[1]));
258 if (std::fabs(aopt) > 1.)
259 tla = tlr * std::fabs(aopt);
260 if (adist < tla && fdist < tlf)
264 double bmin = std::min(alsb[0], alsb[1]) - 1.;
267 double bmax = std::max(alsb[0], alsb[1]) + 1.;
277 print.
Info([&](std::ostream &os) {
278 os <<
"Run Migrad again (3rd) with fixed parameters:";
279 for (
unsigned i = 0; i < npar; ++i)
280 os <<
"\n Pos " << par[i] <<
": " <<
fState.
Name(par[i]) <<
" = " << pmid[i] + (aopt)*pdir[i];
283 for (
unsigned int i = 0; i < npar; i++)
284 migrad.
SetValue(par[i], pmid[i] + (aopt)*pdir[i]);
297 if (limset ==
true && min2.
Fval() < aim)
302 flsb[2] = min2.
Fval();
306 double ecarmn = std::fabs(flsb[2] - aim);
308 unsigned int ibest = 2;
309 unsigned int iworst = 0;
310 unsigned int noless = 0;
312 for (
unsigned int i = 0; i < 3; i++) {
313 double ecart = std::fabs(flsb[i] - aim);
314 if (ecart > ecarmx) {
318 if (ecart < ecarmn) {
326 print.
Debug(
"have three points : noless < aim; noless", noless,
"ibest", ibest,
"iworst", iworst);
331 if (noless == 1 || noless == 2)
334 if (noless == 0 && ibest != 2)
338 if (noless == 3 && ibest != 2) {
342 print.
Debug(
"All three points below - look again fir positive slope");
348 flsb[iworst] = flsb[2];
349 alsb[iworst] = alsb[2];
350 dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]);
352 print.
Debug(
"New straight line using point 1-2; dfda", dfda);
366 print.
Debug(
"Parabola fit: iteration", ipt);
368 double coeff1 = parbol.
C();
369 double coeff2 = parbol.
B();
370 double coeff3 = parbol.
A();
371 double determ = coeff2 * coeff2 - 4. * coeff3 * (coeff1 - aim);
373 print.
Debug(
"Parabola fit: a =", coeff3,
"b =", coeff2,
"c =", coeff1,
"determ =", determ);
376 if (determ < prec.
Eps())
378 double rt = std::sqrt(determ);
379 double x1 = (-coeff2 + rt) / (2. * coeff3);
380 double x2 = (-coeff2 - rt) / (2. * coeff3);
381 double s1 = coeff2 + 2. *
x1 * coeff3;
382 double s2 = coeff2 + 2. *
x2 * coeff3;
384 print.
Debug(
"Parabola fit: x1",
x1,
"x2",
x2,
"s1",
s1,
"s2", s2);
387 print.
Warn(
"Problem 1");
397 print.
Debug(
"Parabola fit: aopt", aopt,
"slope", slope);
401 if (std::fabs(aopt) > 1.)
402 tla = tlr * std::fabs(aopt);
404 print.
Debug(
"Delta(aopt)", std::fabs(aopt - alsb[ibest]),
"tla", tla,
"Delta(F)", std::fabs(flsb[ibest] - aim),
407 if (std::fabs(aopt - alsb[ibest]) < tla && std::fabs(flsb[ibest] - aim) < tlf)
415 unsigned int ileft = 3;
416 unsigned int iright = 3;
417 unsigned int iout = 3;
420 ecarmn = std::fabs(aim - flsb[0]);
421 for (
unsigned int i = 0; i < 3; i++) {
422 double ecart = std::fabs(flsb[i] - aim);
423 if (ecart < ecarmn) {
432 else if (flsb[i] > flsb[iright])
438 }
else if (ileft == 3)
440 else if (flsb[i] < flsb[ileft])
448 print.
Debug(
"ileft", ileft,
"iright", iright,
"iout", iout,
"ibest", ibest);
452 if (ecarmx > 10. * std::fabs(flsb[iout] - aim))
453 aopt = 0.5 * (aopt + 0.5 * (alsb[iright] + alsb[ileft]));
456 double smalla = 0.1 * tla;
457 if (slope * smalla > tlf)
458 smalla = tlf / slope;
459 double aleft = alsb[ileft] + smalla;
460 double aright = alsb[iright] - smalla;
468 aopt = 0.5 * (aleft + aright);
478 print.
Info([&](std::ostream &os) {
479 os <<
"Run Migrad again at new point (#iter = " << ipt+1 <<
" ):";
480 for (
unsigned i = 0; i < npar; ++i)
481 os <<
"\n\t - parameter " << par[i] <<
" fixed to " << pmid[i] + (aopt)*pdir[i];
484 for (
unsigned int i = 0; i < npar; i++)
485 migrad.
SetValue(par[i], pmid[i] + (aopt)*pdir[i]);
487 min2 = migrad(maxcalls, mgr_tlr);
498 if (limset ==
true && min2.
Fval() < aim)
504 flsb[iout] = min2.
Fval();
506 }
while (ipt < maxitr);
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
virtual double Up() const =0
Error definition of the function.
class holding the full result of the minimization; both internal and external (MnUserParameterState) ...
bool HasReachedCallLimit() const
const MnUserParameterState & UserState() const
double LowerLimit() const
double UpperLimit() const
bool HasLowerLimit() const
bool HasUpperLimit() const
void SetValue(unsigned int, double)
MnCross operator()(std::span< const unsigned int >, std::span< const double >, std::span< const double >, double, unsigned int) const
const MnUserParameterState & fState
const MnStrategy & fStrategy
Sets the relative floating point (double) arithmetic precision.
double Eps() const
eps returns the smallest possible number so that 1.+eps > 1.
API class for minimization using Variable Metric technology ("MIGRAD"); allows for user interaction: ...
This class defines a parabola of the form a*x*x + b*x + c.
double B() const
Accessor to the coefficient of the linear term.
double C() const
Accessor to the coefficient of the constant term.
double A() const
Accessor to the coefficient of the quadratic term.
void Debug(const Ts &... args)
void Info(const Ts &... args)
void Warn(const Ts &... args)
API class for defining four levels of strategies: low (0), medium (1), high (2), very high (>=3); act...
unsigned int Strategy() const
const MnMachinePrecision & Precision() const
const MnUserParameters & Parameters() const
const MinuitParameter & Parameter(unsigned int i) const
const char * Name(unsigned int) const
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...