ROOT::Math::Minimizer with Minuit spontaneously fixes certain parameters

Hello,

One-line Description:
The ROOT::Math::Minimizer object is fixing function parameters that need to be variable and it’s unclear how to force these parameters to behave as variables.

Longer description:
I am attempting to minimize (with the ROOT::Math::Minimizer) a custom function that compares a sum of filtered component histograms and a goal histogram with a chi-square statistic.

hist_test = sum(  filter( hist_i )  ) // sum over i
val_to_be_minimized = chi_square( hist_test, hist_goal )

The filter effect and relative heights of the component histograms (hist_i) are parameters for the minimization. I am using the ROOT::Math::Minimizer object to do this minimization, trying to copy the example at https://root.cern.ch/root/html534/tutorials/fit/NumericalMinimization.C.html

The challenge I’m facing is that the minimizer is fixing parameters 0, 8,and 10 (1, 9, and 11) without my calling a function like FixVariable. When I try to release these parameters, it prints “PARAMETER 1/9/11 IS CONSTANT. IGNORED.”

I’ve included the portion of my code that makes and calls the ROOT::Math::Minimizer object. Can someone clarify what’s fixing these parameters and how to make them properly variable again?

  const char * minName = "Minuit";
  const char *algoName = "";
  
  ROOT::Math::Minimizer* min =
    ROOT::Math::Factory::CreateMinimizer(minName, algoName);

  // set tolerance , etc...
  min->SetMaxFunctionCalls(1000000); // for Minuit/Minuit2
  min->SetMaxIterations(10000);  // for GSL
  min->SetTolerance(.0001); //previously -1. Online NumbericalMinimizaiton example has .001
  min->SetPrintLevel(3);

  // create funciton wrapper for minmizer
  // a IMultiGenFunction type
  ROOT::Math::Functor f(&HC,&HistoCompare::minimize,13);
  // step length
  double step[13] = {.2,4e-4,1.3e-2,8e-4,7e-4,2e-3,1e-3,1e-3,5e-2,1e-2,1e-2,1e-2,0.1};
  // starting point
  double variable[13] = {-6.4, 3.35e-02, 1.99e+04, 3.06e+04, 4.17e+03, 8.48e3, 6.87e+03, 6.02e+03, -20., 1.0813, -20., 1.0846, 0.};

  min->SetFunction(f);

  // Set the free variables to be minimized!
  min->SetVariable(0,"sigma1",   variable[0], step[0]);
  min->SetVariable(1,"sigma2",   variable[1], step[1]);
  min->SetVariable(2,"LiS",      variable[2], step[2]);
  min->SetVariable(3,"AS",       variable[3], step[3]);
  min->SetVariable(4,"S",        variable[4], step[4]);
  min->SetVariable(5,"Li",       variable[5], step[5]);
  min->SetVariable(6,"A",        variable[6], step[6]);
  min->SetVariable(7,"G",        variable[7], step[7]);
  min->SetVariable(8,"ELi1",     variable[8], step[8]);
  min->SetVariable(9,"ELi2",     variable[9], step[9]);
  min->SetVariable(10,"EA1",     variable[10],step[10]);
  min->SetVariable(11,"EA2",     variable[11],step[11]);
  min->SetVariable(12,"ELiA-eps",variable[12],step[12]);

  // print warning if variables are fixed
  for(int i=0;i<13;i++){
    if(min->IsFixedVariable(i))
      fprintf(stderr,"\nWARNING: variable %d was fixed.\n\n",i);
  }

  // do the minimization
  min->Minimize();

with the output:

** 2 **SET NOGRAD
PARAMETER DEFINITIONS:
NO. NAME VALUE STEP SIZE LIMITS
1 sigma1 -6.40000e+00 constant
2 sigma2 3.35000e-02 1.16750e-02 no limits
3 LiS 1.99000e+04 9.95010e+02 no limits
4 AS 3.06000e+04 1.53001e+03 no limits
5 S 4.17000e+03 2.08510e+02 no limits
6 Li 8.48000e+03 4.24010e+02 no limits
7 A 6.87000e+03 3.43510e+02 no limits
8 G 6.02000e+03 3.01010e+02 no limits
9 ELi1 -2.00000e+01 constant
10 ELi2 1.08130e+00 6.40650e-02 no limits
11 EA1 -2.00000e+02 constant
12 EA2 1.08460e+00 6.42300e-02 no limits
13 ELiA-eps 0.00000e+00 1.00000e-02 no limits


ROOT Version: 6.04/02
Platform: linuxx8664gcc
Compiler: gcc version 4.9.2 (Debian 4.9.2-10+deb8u2)


I’ve noticed that changing the starting values for one of these forced constant variables

min->SetVariable(0,"sigma1",   variable[0], step[0]);

to

min->SetVariable(0,"sigma1",   variable[1], step[1]);

fixes things for that variable.

I’ve found the solution. I excluded a portion of code that throws out the hard-coded step values and replaced it with something like:

step[i] = 0.01*variable[i] + 1e-3

where the step is some percentage of the starting value plus epsilon (to prevent a step size of zero). The negative variable[i] values were the ones that were being converted to constants. My problem was fixed by changing the above snippet to:

step[i] = abs(0.01*variable[i]) + 1e-3

which forces each value of step[i] to be positive. I guess negative step values force the parameter as a constant and not a variable.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.