//https://root.cern.ch/root/html/ROOT__Math__GSLMultiRootFinder.html:
//solves a non-linear system of equations...
//x[0]=t0 / x[1]=x / x[2]=y / x[3]=z: 0=c^2*x[0]^2 - (Rx.x-x[1])^2 - (Rx.y-x[2])^2 - (Rx.z-x[3])^2
// example of using multiroot finder
// based on GSL algorithm
//
// The MultiRootFinder is based on GSL and it requires the MathMore library
// installed
//
// Usage:
// >.x exampleMultiRoot.C()
// or
// >.x exampleMultiRoot(algoname,printlevel)
//
// where algoname is for an algorithm not using the derivatives:
// hybridS (default) , hybrid, dnewton, broyden
//
#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
const Float_t cmpernano=TMath::C()*1e-9;
double ctsqr0 (double *x, double *p0 ) {
return cmpernano*(p0[0]-x[0])*cmpernano*(p0[0]-x[0]) - (p0[1]-x[1])*(p0[1]-x[1]) - (p0[2]-x[2])*(p0[2]-x[2]) - (p0[3]-x[3])*(p0[3]-x[3]);}
double ctsqr1 (double *x, double *p1 ) {
return cmpernano*(p1[0]-x[0])*cmpernano*(p1[0]-x[0]) - (p1[1]-x[1])*(p1[1]-x[1]) - (p1[2]-x[2])*(p1[2]-x[2]) - (p1[3]-x[3])*(p1[3]-x[3]);}
double ctsqr2 (double *x, double *p2 ) {
return cmpernano*(p2[0]-x[0])*cmpernano*(p2[0]-x[0]) - (p2[1]-x[1])*(p2[1]-x[1]) - (p2[2]-x[2])*(p2[2]-x[2]) - (p2[3]-x[3])*(p2[3]-x[3]);}
double ctsqr3 (double *x, double *p3 ) {
return cmpernano*(p3[0]-x[0])*cmpernano*(p3[0]-x[0]) - (p3[1]-x[1])*(p3[1]-x[1]) - (p3[2]-x[2])*(p3[2]-x[2]) - (p3[3]-x[3])*(p3[3]-x[3]);}
void exampleMultiRoot(const char * algo=0, int printlevel=3) {
#ifndef R__HAS_MATHMORE
Error("exampleMultiRoot","libMathMore is not available - cannot run this tutorial");
#else
ROOT::Math::MultiRootFinder r(algo);
//defining the function
TF1 *ctsqr0 = new TF1("ctsqr0", ctsqr0, 0, 0, 4);
TF1 *ctsqr1 = new TF1("ctsqr1", ctsqr1, 0, 0, 4);
TF1 *ctsqr2 = new TF1("ctsqr2", ctsqr2, 0, 0, 4);
TF1 *ctsqr3 = new TF1("ctsqr3", ctsqr3, 0, 0, 4);
//fake parameters - source at 0 0 0 0
//parameters are: hittime / x / y / z
ctsqr0->SetParameters(0,0,0,3.333);
ctsqr0->SetParameters(0,0,3.333,0);
ctsqr0->SetParameters(0,3.3333,0,0);
ctsqr0->SetParameters(10,0,0,6.666);
// wrap the functions
ROOT::Math::WrappedMultiTF1 g0(*ctsqr0, 4);
ROOT::Math::WrappedMultiTF1 g1(*ctsqr1, 4);
ROOT::Math::WrappedMultiTF1 g2(*ctsqr2, 4);
ROOT::Math::WrappedMultiTF1 g3(*ctsqr3, 4);
r.AddFunction(g0);
r.AddFunction(g1);
r.AddFunction(g2);
r.AddFunction(g3);
r.SetPrintLevel(printlevel);
// starting point - This starting point is the solution and when used here, program converges.
double x0[4]={-10,-1,-2,-1};
/*
root [0] .x exampleMultiRoot.C("kDNewton",1)
GSLMultiRootFinder::Solve:dnewton max iterations 100 and tolera1e-06
Info in : The iteration converged
GSL Algorithm used is : dnewton
Number of iterations = 4
Root values = x[0] = 0.249173 x[1] = -0.557852 x[2] = 0.926722 x[3] = 0.370827 x[4] = 0.130852 x[5] = 0.833278 x[6] = -0.714794 x[7] = 0.475908
Function values = f[0] = -4.58058e-10 f[1] = 4.58043e-10 f[2] = -5.12292e-10 f[3] = 5.12289e-10 f[4] = 2.1217e-10 f[5] = -2.12151e-10 f[6] = 8.80505e-11 f[7] = 1.00293e-10
*/
// With this starting value, program does not converge.
// double x0[8]={ 0.01, -0.02, 0.06, 0.01, 0., 0.01, -0.09, 0.02};
/*
root [0] .x exampleMultiRoot.C("kDNewton",1)
GSLMultiRootFinder::Solve:dnewton max iterations 100 and tolerance 1e-06
Info in : exceeded max iterations, reached tolerance is not sufficient; absTol = 1e-06
*/
r.Solve(x0);
#endif
}