Pass an TGraph2D array as argument to a minimization function

Hi everybody,

I wonder if it is possible to pass more arguments to a function that shall be minimized.

Here is a more detailed description of my problem:
So far I used in my minimization algorithm a function (ML in the small example) to which I pass an array of numbers. This works fine. Now I wonder if it possible to pass, next to an array of numbers, another array of TGraphs2D. Here I am stuck.

I read that a solution could be to define a own functor class (MLfunction) and define the operator of the class in the way I want (with two arguments). Then I have to call the class as if it was a function. Here is the problem: I do not understand, how to set the operator of the class as function of the minimizer. Maybe somebody has an idea what to do or can explain me better the situation of using classes as if they were functions (I do not have experience with that) and arguments of functors.

Below you find a small example code (very simple) to illustrate my problem: When I set ML as function to minimum with an array of number as argument, it works fine, but I would like to know how to pass the array g to ML.

#include <TStyle.h>
#include <TMath.h>
#include <TFile.h>
#include <TCanvas.h>
#include <TF2.h>
#include "TVirtualFitter.h"
#include "TGraph2D.h"
#include "Minuit2/Minuit2Minimizer.h"
#include "Math/Functor.h"
#include <TRandom.h>

#include <stdlib.h>
#include <stack>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <cmath> 
#include <stdio.h>
using namespace std;

class MLfunction{
public:
	double operator()(const double *param, TGraph2D** g)
	{
		Double_t val = 0;
		Double_t p[3];
		Double_t x=param[4];
		Double_t y=param[5];
  
		for(int k=0; k<3; k++){
			p[k]=param[k];
			val=g[k]->Interpolate(x, y)+p[k]; //this what I want to do in the minimization function; interpolating with a TGraph2D
		}
		return val;
	}
};

//double ML(const double *param, TGraph2D** g)
double ML(const double *param)
{
	Double_t val = 0;
	Double_t p[3];
	Double_t x=param[4];
	Double_t y=param[5];
  
	for(int k=0; k<3; k++){
		p[k]=param[k];
		//val=g[k]->Interpolate(x, y)+p[k];
		val=p[k];
	}
	return val;
}

int Example(){
	
	TRandom r;
	TGraph2D *g[3];
	TF2 *gaus2D = new TF2("gaus2D","[0]*TMath::Gaus(sqrt(pow(x-[1],2)+pow(y-[3],2)),0,[2])", 0, 10, 0, 10);
	gaus2D->SetParameters(1, 5, 1, 5);
	Double_t x,y,z;
	for(Int_t i=0; i<3; i++){
		g[i] = new TGraph2D();
		for (Int_t N=0; N<1000; N++) {
			gaus2D->GetRandom2(x,y);
			z = gaus2D->Eval(x,y);
			g[i]->SetPoint(N,x,y,z);
		}
	}
	
	/*TCanvas *c = new TCanvas("c","",400,400);
	g[1]->Draw("P");*/
					
	ROOT::Minuit2::Minuit2Minimizer minimum ( ROOT::Minuit2::kMigrad );
	
	for(Int_t l=0; l<10; l++){								
		const double stepsize=0.1;	
							
		minimum.SetMaxFunctionCalls(1000);
		minimum.SetMaxIterations(10);
		minimum.SetTolerance(0.01);
		minimum.SetStorageLevel(0);
		minimum.SetPrintLevel(-1);
		gErrorIgnoreLevel = 1001;
		
		double step[5];
		double variable[5];
      
		step[0]=0.1;
		step[1]=0.1;
		step[2]=0.1;
		step[3]=0.1;
		step[4]=0.1;
      
		variable[0]=0.5;
		variable[1]=2;
		variable[2]=0.01;
		
		//Without TGraph2D -> works		
		ROOT::Math::Functor f(&ML,5);
		minimum.SetFunction(f);
			
		//With TGraph2D as argument -> does not work
		/*MLfunction ML;
		ROOT::Math::Functor f(&ML(variable,g),8);
		minimum.SetFunction(f);*/

      
		minimum.SetFixedVariable(0, "p1", variable[0]); // new fixed variable
		minimum.SetFixedVariable(1, "p2", variable[1]); // new fixed variable
		minimum.SetFixedVariable(2, "p3", variable[2]); // new fixed variable
		minimum.SetVariable(3,"x",l, step[3]);
		minimum.SetVariable(4,"y",l, step[4]);
						
		minimum.Minimize();
      
		if ( minimum.Edm()  < 1.E-6){
			const double *xs = minimum.X();
				
			cout << xs[3] << " " << xs[4] << endl;
			minimum.Clear();
		}
	}
	
	return 0;
}

I would be very happy and thankful if somebody could help me.
Kind regards!
__
Please read tips for efficient and successful posting and posting code

ROOT Version: 5.34.32
Platform: Not Provided
Compiler: Not Provided


@moneta can perhaps answer, but I see you are using ROOT 5, please consider upgrading to a more recent version since ROOT 5 is unfortunately no longer supported.

Thanks for your reply. I have to use ROOT 5 because of other software I am working with.

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

@moneta might still be able to answer.

Hi,
If you want to pass an array of TGraph2D objects in your minimization function, the correct approach is to use a functor. But you should keep the same signature of the functor MLfunction::operator()(const double *p) as in your free function ML , and pass the TGraph2D objects in the constructor of MLFunction. Example:

class MLfunction{
   TGraph2D **fGraphs; 

public:
      
        MLFunction(TGraph2D **g) : fGraphs(g) {} 

	double operator()(const double *param)
	{
		Double_t val = 0;
		Double_t p[3];
		Double_t x=param[4];
		Double_t y=param[5];
  
		for(int k=0; k<3; k++){
			p[k]=param[k];
			val=fGraphs[k]->Interpolate(x, y)+p[k]; //this what I want to do in the minimization function; interpolating with a TGraph2D
		}
		return val;
	}
};

and later when using your functor:

   MLFunction ml(g); 
   ROOT::Math::Functor f(ml,8);
   minimum.SetFunction(f);

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