Minuit Minimizer Contour ignores ErrorDef / gives "wrong" contour

I first posted this topic on the general forum [cannot add link due to being a new user], but did so at the beginning of the Christmas holidays and got no replies. I am afraid it might have been automatically locked before the relevant people could see it. I hope posting it again here is not frowned upon (moderators could remove the previous topic if it helps?).


I am running into an issue when running Minuit2 “Contour” function, in which the output points do not have the desired “height”, which I previously set with SetErrorDef(). I am changing ErrorDef based on my weak attempt at interpreting the code - the documentation itself refers to ErrorUp, but it does not appear anywhere else, as far as I can tell.

Here is a snippet of code to ilustrate what I am trying to do:

/*** Initialize minimizer, variables ***/
ROOT::Math::Minimizer* rootmin = ROOT::Math::Factory::CreateMinimizer("Minuit2","Combined");

rootmin->SetMaxFunctionCalls(100000);
rootmin->SetMaxIterations(100000);
rootmin->SetTolerance(0.02);
rootmin->SetFunction(LFunc);
//LFunc is a log-likelihood ( -2*log(L) ) function/functor defined earlier in the code

rootmin->SetLimitedVariable(0,"Variable0",pars[0],0.1,0.01, 1e4); 
rootmin->SetLimitedVariable(1,"Variable1",pars[1],0.1,0.01, 1e4);
rootmin->SetLimitedVariable(2,"Variable2",pars[2],0.1,0.01, 1e4);
rootmin->SetLimitedVariable(3,"Variable3",pars[3],0.1,0.01, 1e4);
//pars, holding initial guesses for fit, is also defined earlier

/*** Run minimiser, contour ***/
double Delta2LogL = 2.7;
rootmin->SetErrorDef(Delta2LogL);
rootmin->Minimize();
cout << "  Value of minimum log-Likelihood : " << rootmin->MinValue() << endl;
double varcont0_pts[npointscont];
double varcont1_pts[npointscont];
unsigned int npoints = 100;
rootmin->Contour(0, 1, npoints, varcont0_pts, varcont1_pts);

So now varcont0_pts and varcont1_pts hold the coordinates of the contour, which I would expect all have a minimum log-likelihood that is Delta2LogL points above the minimum found by the minimiser.

However, if I do the following:

size_t i_cont = 0; //choose any value between 0 and 99
rootmin->SetVariableValue(0, varcont0_pts[i_cont]);
rootmin->FixVariable(0);
rootmin->SetVariableValue(1, varcont1_pts[i_cont]);
rootmin->FixVariable(1);
rootmin->Minimize();
cout << "  Value of log-Likelihood at contour : " << rootmin->MinValue() << endl;

I find that the difference in log-likelihood (between the minimum and the points in the contour) is not what I asked for with SetErrorDef(). In fact, I find the same contour points no matter what value I request for the difference.

I assume I am not using the minimizer properly somehow, but I don’t know how to proceed from here. Could anyone help me?

Thank you for your time!

I guess @moneta can help you.

Hi,
Which ROOT version are you using ? I think there was a bug in setting the ErrorDef for the contour and it was fixed in a recent version

Lorenzo

Hello!

I don’t remember if there was something done about this for ROOT 6.26, but at least in the development cycle for ROOT 6.28 we have merged this PR by Lorenzo in RooFit:

So maybe you have to do the same in your code as we did in RooFit: redoing rootmin->SetErrorDef() after your call to rootmin->Contour()?

The ROOT version we have running is 6.18. Would that be from before the bug was fixed? I will try to get it updated to the latest version in our environment.

I will try that too and see what happens, thank you for the tip!

@jonas : I tried to redo rootmin->SetErrorDef() after calling rootmin->Contour(), but did not see any difference in the results. Thanks for the suggestion though!

@moneta : So I got to run the code with ROOT 6.26 (updating to C++14 in the process). The results are still the same (i.e. contours that ignore the requested ErrorDef value) , but now I get a new error message:

Error in : MnContours unable to find point on Contour 5
found only 4 points
Error in : Minuit2Minimizer::Contour Invalid result from MnContours

Just in case the problem was that the contour was outside the allowed parameter range, I checked the value and Minos error for the requested value of ErrorDef, and got the following:

var1 range : 136039 +116246 -56438
var2 range : 91.8551 +29.8892 -22.1713

For each variable, first value is the one that minimised the likelihood function, second/third values are the positive/negative Minos errors. So we are not particularly close to the limits set on the variables, which are [0,4e7] for the first and [0.01,1e4] for the second.

Could I have some tips on how to proceed from here?

So, for the sake of future people that might come across this, the issue seemed to be that the function to minimise had very unusual correlations between parameters as we move away from the minimum. So Contour was failing to find more than a handful of points, if that. MinosErrors was also behaving erratically, sometimes giving values that landed the relevant parameter outside the range allowed in the fit. The behaviour of either was somewhat arbitrary, modifying the value of ErrorUp slightly could make it work properly when it didn’t before, and viceversa.

Eventually I kludged together a solution by fixing one variable before running Contour, repeating the process with different values for the fixed variable, and comparing results. Ultimately the issue was likely that the data did not constrain the model enough, given the behaviour of the model away from the minimum.

Hi,

Thank you for the explanations. This makes sense. If you want to share the code her, it might be useful for improving the contour finding code

Best regards

Lorenzo