Skip to content

Commit efa865a

Browse files
committed
[minuit2] Implement review comments from Axel.
Remove goto statement and fix a bug in the order of the two contour limit points
1 parent 9503127 commit efa865a

File tree

3 files changed

+79
-69
lines changed

3 files changed

+79
-69
lines changed

math/minuit2/inc/Minuit2/MinuitParameter.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class MinuitParameter {
9696
unsigned int Number() const { return fNum; }
9797
// new API returning a string
9898
const std::string &GetName() const { return fName; }
99-
// return const char * for mantaining backward compatibility
99+
// return const char * for maintaining backward compatibility
100100
const char *Name() const { return fName.c_str(); }
101101

102102
double Value() const { return fValue; }
@@ -107,8 +107,10 @@ class MinuitParameter {
107107

108108
void SetValue(double val) {
109109
fValue = val;
110-
if (fLoLimValid && val < fLoLimit) fValue = fLoLimit;
111-
if (fUpLimValid && val > fUpLimit) fValue = fUpLimit;
110+
if (fLoLimValid && val < fLoLimit)
111+
fValue = fLoLimit;
112+
else if (fUpLimValid && val > fUpLimit)
113+
fValue = fUpLimit;
112114
}
113115
void SetError(double err) { fError = err; }
114116
void SetLimits(double low, double up)

math/minuit2/src/MnApplication.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ FunctionMinimum MnApplication::operator()(unsigned int maxfcn, double toler)
4141
if (npar == 0) {
4242
double fval = fcn(fState.Params());
4343
print.Info("Function has zero parameters - returning current function value - ",fval);
44-
// create a valid Minuit-Parameter objects with just the function value
45-
MinimumParameters mparams(fval,MinimumParameters::MnValid);
44+
// create a valid Minuit-Parameter object with just the function value
45+
MinimumParameters mparams(fval, MinimumParameters::MnValid);
4646
MinimumState mstate(mparams, 0., 1 );
4747
return FunctionMinimum( MinimumSeed(mstate, fState.Trafo()), fcn.Up());
4848
}

math/minuit2/src/MnContours.cxx

Lines changed: 72 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,13 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int
104104
return (status) ? vmid[0] + crossResult.Value() * vdir[0] : 0;
105105
};
106106

107-
// function to find teh contour points at the border of p1 after the minimization in p2
107+
// function to find the contour points at the border of p1 after the minimization in p2
108108
auto findContourPointsAtBorder = [&](unsigned int p1, unsigned int p2, double p1Limit, FunctionMinimum & minp2, bool order) {
109109
// we are at the limit in p1
110110
ustate.SetValue(p1, p1Limit);
111111
ustate.Fix(p1);
112-
bool ret1, ret2 = false;
112+
bool ret1 = false;
113+
bool ret2 = false;
113114
double deltaFCN = fMinimum.Fval() + fFCN.Up()- minp2.UserState().Fval();
114115
double pmid = minp2.UserState().Value(p2); // starting point for search
115116
double pdir = minp2.UserState().Error(p2) * deltaFCN/fFCN.Up(); // direction for the search
@@ -125,19 +126,20 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int
125126
} else if (!ret1 && ret2) {
126127
yvalues.push_back(y2);
127128
} else {
128-
// otherwise use both points:
129-
yvalues.push_back(y1);
130129
// if points are not the same use both
131130
if (std::abs(y1-y2) > 0.0001 * fMinimum.UserState().Error(p2)) {
132131
// order them in increasing/decreasing y depending on order flag
133132
int orderDir = (order) ? 1 : -1;
134-
if (orderDir*(y2-y1) > 0)
133+
if (orderDir*(y2-y1) > 0) {
134+
yvalues.push_back(y1);
135135
yvalues.push_back(y2);
136-
else {
136+
} else {
137137
yvalues.push_back(y2);
138138
yvalues.push_back(y1);
139139
}
140140
}
141+
else
142+
yvalues.push_back(y1);
141143
}
142144
print.Debug("Found contour point at the border: ",ustate.Value(p1)," , ",yvalues[0]);
143145
if (yvalues.size() > 1) print.Debug("Found additional point at : ",ustate.Value(p1)," , ",yvalues[1]);
@@ -297,68 +299,74 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int
297299
double a2 = 0.5;
298300
double sca = 1.;
299301

300-
L300:
302+
bool validPoint = false;
301303

302-
if (nfcn > maxcalls) {
303-
print.Error("maximum number of function calls exhausted");
304-
return ContoursError(px, py, result, mnex, mney, nfcn);
305-
}
304+
do {
306305

307-
print.Debug("Find new contour point between points with max sep: (",idist1->first,", ",idist1->second,") and (",
308-
idist2->first,", ",idist2->second,") with weights ",a1,a2);
309-
// find next point between the found 2 with max separation
310-
// start from point situated at the middle (a1,a2=0.5)
311-
// and direction
312-
double xmidcr = a1 * idist1->first + a2 * (idist2)->first;
313-
double ymidcr = a1 * idist1->second + a2 * (idist2)->second;
314-
// direction is the perpendicular one
315-
double xdir = (idist2)->second - idist1->second;
316-
double ydir = idist1->first - (idist2)->first;
317-
double scalfac = sca * std::max(std::fabs(xdir * scalx), std::fabs(ydir * scaly));
318-
double xdircr = xdir / scalfac;
319-
double ydircr = ydir / scalfac;
320-
std::vector<double> pmid(2);
321-
pmid[0] = xmidcr;
322-
pmid[1] = ymidcr;
323-
std::vector<double> pdir(2);
324-
pdir[0] = xdircr;
325-
pdir[1] = ydircr;
326-
327-
print.Debug("calling MnCross with pmid: ",pmid[0],pmid[1], "and pdir ",pdir[0],pdir[1]);
328-
MnCross opt = cross(par, pmid, pdir, toler, maxcalls);
329-
nfcn += opt.NFcn();
330-
if (!opt.IsValid() || opt.AtLimit()) {
331-
// Exclude also case where we are at limits since point is not in that case
332-
// on teh contour. If we are at limit maybe we should try more?
333-
if(a1 > 0.5) {
334-
a1 = 0.25;
335-
a2 = 0.75;
336-
print.Debug("Unable to find point, try closer to p2 with weight values",a1,a2);
337-
goto L300;
338-
}
339-
if (a1 < 0.3) {
340-
print.Info("Unable to find point on Contour", i + 1, '\n', "found only", i, "points");
306+
if (nfcn > maxcalls) {
307+
print.Error("maximum number of function calls exhausted");
341308
return ContoursError(px, py, result, mnex, mney, nfcn);
342309
}
343-
a1 = 0.75;
344-
a2 = 0.25;
345-
print.Debug("Unable to find point, try closer to p1 with weight values",a1,a2);
346-
//std::cout<<"*****switch direction"<<std::endl;
347-
//sca = -1.;
348-
goto L300;
349-
}
350-
double aopt = opt.Value();
351-
int pos = result.size();
352-
if (idist2 == result.begin()) {
353-
result.emplace_back(xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr);
354-
print.Info(result.back());
355-
} else {
356-
print.Info(*idist2);
357-
auto itr = result.insert(idist2, {xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr});
358-
pos = std::distance(result.begin(),itr);
359-
}
360-
print.Info("Found new point - pos: ",pos,result[pos], "fcn = ",opt.State().Fval());
361-
}
310+
311+
print.Debug("Find new contour point between points with max sep: (",idist1->first,", ",idist1->second,") and (",
312+
idist2->first,", ",idist2->second,") with weights ",a1,a2);
313+
// find next point between the found 2 with max separation
314+
// start from point situated at the middle (a1,a2=0.5)
315+
// and direction
316+
double xmidcr = a1 * idist1->first + a2 * (idist2)->first;
317+
double ymidcr = a1 * idist1->second + a2 * (idist2)->second;
318+
// direction is the perpendicular one
319+
double xdir = (idist2)->second - idist1->second;
320+
double ydir = idist1->first - (idist2)->first;
321+
double scalfac = sca * std::max(std::fabs(xdir * scalx), std::fabs(ydir * scaly));
322+
double xdircr = xdir / scalfac;
323+
double ydircr = ydir / scalfac;
324+
std::vector<double> pmid(2);
325+
pmid[0] = xmidcr;
326+
pmid[1] = ymidcr;
327+
std::vector<double> pdir(2);
328+
pdir[0] = xdircr;
329+
pdir[1] = ydircr;
330+
331+
print.Debug("calling MnCross with pmid: ",pmid[0],pmid[1], "and pdir ",pdir[0],pdir[1]);
332+
MnCross opt = cross(par, pmid, pdir, toler, maxcalls);
333+
nfcn += opt.NFcn();
334+
if (!opt.IsValid() || opt.AtLimit()) {
335+
// Exclude also case where we are at limits since point is not in that case
336+
// on the contour. If we are at limit maybe we should try more?
337+
if (a1 < 0.3) {
338+
// here when having tried with a1=0.5, a1 = 0.75 and a1=0.25
339+
print.Info("Unable to find point on Contour", i + 1, '\n', "found only", i, "points");
340+
return ContoursError(px, py, result, mnex, mney, nfcn);
341+
} else if (a1 > 0.5) {
342+
a1 = 0.25;
343+
a2 = 0.75;
344+
print.Debug("Unable to find point, try closer to p2 with weight values",a1,a2);
345+
} else {
346+
a1 = 0.75;
347+
a2 = 0.25;
348+
print.Debug("Unable to find point, try closer to p1 with weight values",a1,a2);
349+
//std::cout<<"*****switch direction"<<std::endl;
350+
//sca = -1.;
351+
}
352+
} else {
353+
// a point is found
354+
double aopt = opt.Value();
355+
int pos = result.size();
356+
if (idist2 == result.begin()) {
357+
result.emplace_back(xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr);
358+
print.Info(result.back());
359+
} else {
360+
print.Info(*idist2);
361+
auto itr = result.insert(idist2, {xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr});
362+
pos = std::distance(result.begin(),itr);
363+
}
364+
print.Info("Found new point - pos: ",pos,result[pos], "fcn = ",opt.State().Fval());
365+
validPoint = true;
366+
}
367+
// loop until a valid point has been found
368+
} while (!validPoint);
369+
} // end loop on points
362370

363371
print.Info("Number of contour points =", result.size());
364372

0 commit comments

Comments
 (0)