Updating code to use TVirtualFitter instead of TFitterMinuit

Dear all,

I have been attempting to migrate some code to TVirtualFitter that was built using TFitterMinuit, and am having little success. The original code is[code]class MinLogLike: public ROOT::Minuit2::FCNBase{

private:
vector costhetax_posi;
vector costhetay_posi;
vector costhetaz_posi;

vector costhetax_nega;
vector costhetay_nega;
vector costhetaz_nega;

public:
MinLogLike(vector cosx_posi,vector cosy_posi,vector cosz_posi,vector cosx_nega,vector cosy_nega,vector cosz_nega){
costhetax_posi=cosx_posi;
costhetay_posi=cosy_posi;
costhetaz_posi=cosz_posi;
costhetax_nega=cosx_nega;
costhetay_nega=cosy_nega;
costhetaz_nega=cosz_nega;
}
double operator() (const std::vector &x) const {
double sposi = 0.0, snega = 0.0;
for (Int_t i=0; i<costhetax_posi.size(); i++) {
sposi+=-TMath::Log((1.0+x[0]*costhetax_posi[i]+x[1]*costhetaz_posi[i]+x[2]*costhetay_posi[i]));
}
for (Int_t i=0; i<costhetax_nega.size(); i++) {
snega+=-TMath::Log((1.0-x[0]*costhetax_nega[i]-x[1]*costhetaz_nega[i]+x[2]*costhetay_nega[i]));
}
return sposi+snega;
}

double Up() const { return 0.5; }
};[/code]

and the class used later as TFitterMinuit* pMinuit = new TFitterMinuit(); MinLogLike minloglike(cosx_posi,cosy_posi,cosz_posi,cosx_nega,cosy_nega,cosz_nega); pMinuit->SetMinuitFCN(&minloglike);

Trying to update this code has proven quite troublesome for me. There appears to be two places where I am struggling. The first place is in the class definition and the second place is calling the class. My original idea in updating this code was to just update the class definitions and function call/options. Currently, here is my updated code:

[code]#include ā€œTVirtualFitter.hā€
#include ā€œTMinuit.hā€
#include ā€œMath/Minimizer.hā€

//#include "TFitterMinuit.h"
using namespace std;
class MinLogLike: public ROOT::Math::Minimizer{

private:
vector costhetax_posi;
vector costhetay_posi;
vector costhetaz_posi;

vector costhetax_nega;
vector costhetay_nega;
vector costhetaz_nega;

public:
MinLogLike(vector cosx_posi,vector cosy_posi,vector cosz_posi,vector cosx_nega,vector cosy_nega,vector cosz_nega){
costhetax_posi=cosx_posi;
costhetay_posi=cosy_posi;
costhetaz_posi=cosz_posi;
costhetax_nega=cosx_nega;
costhetay_nega=cosy_nega;
costhetaz_nega=cosz_nega;
}
double operator() (const std::vector &x) const {
double sposi = 0.0, snega = 0.0;
for (Int_t i=0; i<costhetax_posi.size(); i++) {
sposi+=-TMath::Log((1.0+x[0]*costhetax_posi[i]+x[1]*costhetaz_posi[i]+x[2]*costhetay_posi[i]));
}
for (Int_t i=0; i<costhetax_nega.size(); i++) {
snega+=-TMath::Log((1.0-x[0]*costhetax_nega[i]-x[1]*costhetaz_nega[i]+x[2]*costhetay_nega[i]));
}
return sposi+snega;
}

double Up() const { return 0.5; }
};[/code]

and [code] TVirtualFitter *pMinuit = TVirtualFitter::Fitter(0, 6);//Fitter with up to 6 params

MinLogLike minloglike(cosx_posi,cosy_posi,cosz_posi,cosx_nega,cosy_nega,cosz_nega);
pMinuit->SetFCN(&minloglike);[/code]

When I attempt to run the macro, I receive the following errors:

[quote]/Users/Colin/Desktop/final_skim/Observables/2d/unprimed/root6/hist_2d_fit.C:172:16: error:
variable type ā€˜MinLogLikeā€™ is an abstract class
MinLogLike minloglike(cosx_posi,cosy_posi,cosz_posi,cosx_nega,cosy_nā€¦
^
/opt/local/root-6.06.02/include/Math/Minimizer.h:128:17: note: unimplemented
pure virtual method ā€˜SetFunctionā€™ in 'MinLogLikeā€™
virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func) = 0;
^
/opt/local/root-6.06.02/include/Math/Minimizer.h:161:17: note: unimplemented
pure virtual method ā€˜SetVariableā€™ in 'MinLogLikeā€™
virtual bool SetVariable(unsigned int ivar, const std::string & nameā€¦
^
/opt/local/root-6.06.02/include/Math/Minimizer.h:253:18: note: unimplemented
pure virtual method ā€˜Minimizeā€™ in 'MinLogLikeā€™
virtual bool Minimize() = 0;
^
/opt/local/root-6.06.02/include/Math/Minimizer.h:256:19: note: unimplemented
pure virtual method ā€˜MinValueā€™ in 'MinLogLikeā€™
virtual double MinValue() const = 0;
^
/opt/local/root-6.06.02/include/Math/Minimizer.h:259:28: note: unimplemented
pure virtual method ā€˜Xā€™ in 'MinLogLikeā€™
virtual const double * X() const = 0;
^
/opt/local/root-6.06.02/include/Math/Minimizer.h:275:25: note: unimplemented
pure virtual method ā€˜NDimā€™ in 'MinLogLikeā€™
virtual unsigned int NDim() const = 0;[/quote]

Iā€™ve tried some different class definitions and calls, but all result in an error. I havenā€™t been able to find anything in the forums that directly deal with an issue like this. Can anyone provide any help on this migration to TVirtualFitter from TFitterMinuit?

Hi,

Lorenzo is the expert here, and heā€™s on vacation, I believe until Monday. I will ask him to have a look at thisā€¦

Cheers, Axel

Hi,

First of all you should migrate from TFitterMinuit to the ROOT::Math::Minimizer and not TVirtualFitter.
TFitterMinuit implements the TVirtualFitter interface.

The thing to do is first to adapt the objective function interface and then you can use the ROOT::Math::MInimizer class to minimise the function.

You can make the MinLogLike class implementing the ROOT::Math::IbaseFunctionMultiDim interface, see
root.cern.ch/root/htmldoc/guide ā€¦ interfaces

and you can do this directly or by wrapping it using the ROOT::Math::Functor class (easier solution).

In the second case just rename the member function in the MinLogLike class from

double operator() (const std::vector<double> &x) const {....}

to

double operator() (const double * x) const {.....
}

then you do, following for example the tutorial NumericalMinimization.C
see root.cern.ch/doc/master/Numeric ā€¦ on_8C.html

  ROOT::Math::Minimizer* minim = ROOT::Math::Factory::CreateMinimizer("Minuit2", "Migrad");
  MinLogLike nll(.....);
   ROOT::Math::Functor f(nll,ndimension);
   minim->SetFunction(nll); 
   // set the fitting parameters (variable of the objective functions)
   
   minim->SetVariable(0,.....)
   minim->SetVariable(0,.....)
   
   minim->Minimize(); 
      

I hope you can now update your code. In case you have still problems, please let me know

Best Regards

Lorenzo

1 Like

Thank you very much for the help, Lorenzo! To clarify some things, when you say to use ROOT::Math::Functor class, that means when I define the class MinLogLike, it should look like

correct? Using ROOT::Math::IGradientFunctionMultiDim or ROOT::Math::Minimizer still caused some errors.

Adjusting the code as per your suggestions before and following the example given, I get

[code] ROOT::Math::Minimizer* minim = ROOT::Math::factory::CreateMinimizer(ā€œMinuit2ā€, ā€œMigradā€);

MinLogLike nll(cosx_posi,cosy_posi,cosz_posi,cosx_nega,cosy_nega,cosz_nega);

int ndimension=6;
ROOT::Math::Functor f(nll,ndimension);

minim->SetFunction(nll);

minim->SetVariable(0, "cx", 0, 0.1);
minim->SetVariable(1, "cz", 0.3, 0.1);
minim->SetVariable(2, "py", 0, 0.1);

minim->Minimize();[/code]

This results in a segmentation violation when I run the macro at minim->SetFunction(nll);. Any idea what may be causing this?