Numerical minimization without having to define parameters globally

I have a list of events that for each event I have to perform numerical minimization on with a function that takes in several parameters which are constants that are used to define the function (see below code). Following the tutorials on this page https://root.cern.ch/numerical-minimization, the below code is a general idea of what I want to accomplish.

I am hesitant to follow the multi-dimensional examples on that page since my function is not multi-dimensional since all I am doing is passing in constants used to to define a 1D function. I’ve gotten past this by setting global variables, but I would need to reset the global variables in every loop iteration for each event, so if at all possible I would like to know if there is a more elegant approach.

I also came across this page: https://root.cern.ch/doc/master/classTF1.html#F5 while looking around, and this comes close to what I want to accomplish but I would like to know if I can use a TF1 in my code below.

Thanks in advance!

#include "Math/Functor.h"
#include "Math/BrentMinimizer1D.h"
 
using namespace TMath;
Int_t a = -9;
Int_t b = 5;

double myfunc(double x) {
    return 1 + a*x + b*x*x;
}

void NumMinimize(){
    ROOT::Math::Functor1D func(&myfunc);

    ROOT::Math::BrentMinimizer1D bm;
    bm.SetFunction(func, -4,4);
    bm.Minimize(10,0,0);

    cout << "f(" << bm.XMinimum() << ") = " <<bm.FValMinimum() << endl;
 }

ROOT Version: 6.20/02

@moneta can probably give you some hints

#include "Math/Functor.h"
#include "Math/BrentMinimizer1D.h"

#include <iostream>

class myfunc {
public:
  double a;
  double b;
  
  // constructors are not needed but may be useful to set default values
  myfunc(): a(-4.), b(1.) {}
  myfunc(double A, double B): a(A), b(B) {}
  
  double operator() (double x) {
    return 1. + a*x + b*x*x;
  }
};

void NumMinimize() {
  myfunc mf; // the default constructor sets a = -4. and b = 1.
  
  ROOT::Math::Functor1D func(mf); // func uses a private copy of mf
  
  ROOT::Math::BrentMinimizer1D bm;
  bm.SetFunction(func, -10,10);
  
  // when a = -4. and b = 1. then f(2.) = -3.
  bm.Minimize(10,0,0);
  std::cout << "f(" << bm.XMinimum() << ") = " << bm.FValMinimum() << std::endl;
  
  // when a = -9. and b = 5. then f(0.9) = -3.05
  mf.a = -9.; mf.b = 5.;
  func = mf; // renew func's private copy after parameters' modification
  bm.Minimize(10,0,0);
  std::cout << "f(" << bm.XMinimum() << ") = " << bm.FValMinimum() << std::endl;
}
1 Like

Concerning your question about TF1, yes, you can use a TF1, but you cannot really use the ROOT::Math::Functor1D, because you will not be able to see the parameters change later. The Functor1D performs a copy of the TF1 object.
The solution is to use the ROOT::Math::WrappedTF1 class and then use the 1D minimisation algorithm. Here is the example

TF1 f1("f1","1.+[a]*x+[b]*x^2");
ROOT::Math::WrappedTF1 func(f1);
f1.SetParameter("a",-9);
f1.SetParameter("b",5);

Lorenzo