Solving non linear system with ROOT::Math::GSLMultiRootFinder

Hello, first of all, happy new year to everyone!

I have to solve 4 variable non linear equation systems.
I found the class “ROOT::Math::GSLMultiRootFinder” that could do that for me.
It seems to find the common root of several functions.

Here is a code that shows how I want to use the class.

#include "RConfigure.h"

#ifdef R__HAS_MATHMORE
#include "Math/MultiRootFinder.h"
#endif
#include "Math/WrappedMultiTF1.h"
#include "TF2.h"
#include "TError.h"

// example of using multi root finder based on GSL
// need to use an algorithm not requiring the derivative
//like hybrids (default), hybrid, dnewton, broyden

using namespace ROOT::Math;

	double equation (double *x, double *p1 ) {
	return ( (x[0]*(x[2]*p1[0]-p1[1]+x[3])/sqrt(1+pow(x[2],2))+x[1]*pow((x[2]*p1[0]-p1[1]+x[3])/sqrt(1+pow(x[2],2)),2))-(x[0]*(x[2]*p1[2]-p1[3]+x[3])/sqrt(1+pow(x[2],2))+x[1]*pow((x[2]*p1[2]-p1[3]+x[3])/sqrt(1+pow(x[2],2)),2))-p1[4] );
}
void exampleMultiRoot(const char * algo = 0, int printlevel = 1) {

#ifndef R__HAS_MATHMORE
   Error("exampleMultiRoot","libMathMore is not available - cannot run this tutorial");
   return;
#endif

   ROOT::Math::MultiRootFinder r(algo);
   //defining the function
   TF1 * f1 = new TF1("f1",equation,0,100,5);
   TF1 * f2 = new TF1("f2",equation,0,100,5);
   TF1 * f3 = new TF1("f3",equation,0,100,5);
   TF1 * f4 = new TF1("f4",equation,0,100,5);
   f1->SetParameters(1,0,3,4,5);
   f2->SetParameters(1,2,3,4,4);
   f3->SetParameters(2,3,4,5,2);
   f4->SetParameters(3,4,5,6,0);
   // wrap the functions
   
   ROOT::Math::WrappedMultiTF1 g1(*f1,4);
   ROOT::Math::WrappedMultiTF1 g2(*f2,4);
   ROOT::Math::WrappedMultiTF1 g3(*f3,4);
   ROOT::Math::WrappedMultiTF1 g4(*f4,4);
   r.AddFunction(g1);
   r.AddFunction(g2);
   r.AddFunction(g3);
   r.AddFunction(g4);   
   r.SetPrintLevel(printlevel);

   // starting point
   double x0[4]={-1,-1,-1,-1};
   r.Solve(x0);
}

The code compiles and gives a results.

GSLMultiRootFinder::Solve:hybrids max iterations 100 and  tolerance 1e-06
Info in <ROOT::Math::GSLMultiRootFinder::Solve>: The iteration converged
GSL Algorithm used is :  hybrids
Number of iterations  =  15
Root values     = x[0] =      3.68559   x[1] =      0.36675   x[2] =     -5.31663   x[3] =    -0.916183   
Function values = f[0] = -8.15298e-08   f[1] = -3.14831e-08   f[2] = -6.44772e-09   f[3] =  1.85877e-08 

Something seems strange.
To enter the functions in the solver, I have to use the command ROOT::Math::WrappedMultiTF1. Nevertheless, as I’m trying to solve 4 variable system, the functions are also 4 dimensional, it seems I can’t define theme as TF1.

Is there a ROOT::Math::WrappedMultiTF1 like class that could work with TFormula (tried to look for it but I didn’t find anything)?

As you can see in my code I tricked it by using a pointer as the variable of the TF1, but i’m not sur of what happen then. And if it works, what does the “0,100” of TF1 * f1 = new TF1(“f1”,equation,0,100,5) constrains (some value of the root are not in this interval)?

Thank you in advance for your consideration,
Lucien Causse.


_ROOT Version: 6.08/04
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)


@moneta can surely help.

Hello Lucien,
Happy new year !!!

Here are the answers to your questions:

  • The solver is for a system of N equations with N variables. Each equation is a function, for this reason the GSLMultiRootFinder requires as input N different function objects. What you are doing is correct

No, but you can create a TF1 from a formula string (using TFormula), this is also very conveninent

The way you create the function is correct. [0,100] is the range in x of the TF1 function, but it is not used by the algorithm, so those values are not relevant. [5] is the number of parameters of the function.
Actually, if you create the TF1 from a formula, you woul dnot need to pass the range and the number of parameters.

Hope this answer to your questions.
Best regards

Lorenzo

1 Like