Home | News | Documentation | Download

Solve equation with RootFinder

Hi everyone. I have problem to deal, in which I have to solve a complicated non-linear equation. I plan to solve it with Bisection method (numerical algorithms). Firstly, I try solving a very simple equation with Bisection method. I read documentation RootFinder. I a little bit undersand. Therefore there is some error. Could you please help me? This is my code.

#include <iostream>
#include <Math/RootFinderAlgorithms.h>
#include <TF1.h>
#include <Math/RootFinder.h>
using namespace ROOT::Math;
using namespace std;

double myfunc(double x) 
{
    return 3*x - 10;
}

void find_root()
{
    RootFinder *k = new RootFinder();
    k->SetMethod(RootFinder::kGSL_BISECTION);
    k->SetFunction(myfunc, 1, 10);

    double c = k->Root();
    cout << c << endl;
}

Hi,

You need to use the ROOT::Math::Functor1D class to wrap your function pointer in the right function object required by the ROOT Finder and to call RootFinder::Solve().
Here is a snippet of working code:

#include <iostream>
#include <Math/RootFinderAlgorithms.h>
#include <TF1.h>
#include <Math/RootFinder.h>
#include <Math/Functor.h>
using namespace ROOT::Math;
using namespace std;

double myfunc(double x) 
{
    return 3*x - 10;
}

void find_root()
{
    RootFinder *k = new RootFinder();
    k->SetMethod(RootFinder::kGSL_BISECTION);
    ROOT::Math::Functor1D f(&myfunc);
    k->SetFunction(f, 1, 10);
    k->Solve();

    double c = k->Root();
    cout << c << endl;
}

Lorenzo

Thank you, Lorenzo. It worked well. I still have a question. When I try solve a equation with Newton method, I use the ROOT::Math::GradFunctor1D to wrap my derivative, but there is some error. Could you please put where is my mistake? Here is my code.

#include <iostream>
#include <Math/RootFinderAlgorithms.h>
#include <TF1.h>
#include <Math/RootFinder.h>
#include <Math/Functor.h>
using namespace ROOT::Math;
using namespace std;

double myfunc(double x) 
{
    return x*x - 3*x - 3; 
}

double derivative(double x)
{
    return 2*x - 3;
}

void find_root()
{
    RootFinder *k = new RootFinder();
    k->SetMethod(RootFinder::kGSL_NEWTON);
    ROOT::Math::Functor1D f(&myfunc);
    ROOT::Math::GradFunctor1D g(&derivative);
    k->SetFunction(f, 2, 5);
    k->SetFunction(g, 4);
    k->Solve(f,g);

    double c = k->Root();
    cout << c << endl;
}

Hi,
for using the derivatives, here is the correct code:

    RootFinder *k = new RootFinder();
    k->SetMethod(RootFinder::kGSL_NEWTON);
    // create gradient functor passing both a pointer to a function implementing function evaluation and
   // a pointer to a function implementing the derivative 
    ROOT::Math::GradFunctor1D g(&myfunc, &derivative);
    k->SetFunction(g, 4);
    k->Solve();

Lorenzo

Thank you, Lorenzo for your supporting. I got a lot of knowledge from you.

Hi Lorenzo. When I solve equation system with numerical method, I wrap TF2 object by ROOT::Math::WrappedMultiTF1, but there are some warnings and no roots. What can I do to deal with the problem? Thank you.

Warning: template pair duplicate definition C:\root_v5.34.36/cint\cint\stl\_pair.h(31)
Warning: template reverse_iterator duplicate definition C:\root_v5.34.36/cint\cint\stl\_iterator.h(269)
Warning: template allocator duplicate definition C:\root_v5.34.36/cint\cint\stl\defalloc.h(134)
Warning: template vector duplicate definition C:\root_v5.34.36/cint\cint\stl\_vector.h(44)

Here is my code.

#include <iostream>
#include <Math/RootFinderAlgorithms.h>
#include <TF1.h>
#include <Math/RootFinder.h>
#include <Math/GSLMultiRootFinder.h>
#include <Math/Functor.h>
#include <Math/WrappedMultiTF1.h>
using namespace ROOT::Math;
using namespace std;

void find_root_multi()
{

    ROOT::Math::GSLMultiRootFinder *r = new ROOT::Math::GSLMultiRootFinder(ROOT::Math::GSLMultiRootFinder::kHybrid);
    TF2 *f1 = new TF2("f1", "[0]*x + [1]*y", -5, 5, -5, 5);
    TF2 *f2 = new TF2("f2", "[0]*x + [1]*y - 2", -5, 5, -5, 5);
    f1->SetParameters(1, 2);
    f2->SetParameters(2, -3);

    ROOT::Math::WrappedMultiTF1 g1(*f1, 2);
    ROOT::Math::WrappedMultiTF1 g2(*f2, 2);

    r->AddFunction(g1);
    r->AddFunction(g2);

    double x0[2] = {-3.5, 2.2};
    r->Solve(x0);
    cout << r->X() << endl;
}

Hi,
The code seems correct to me, apart from the printing of the ROOT. Now in the multi-dim case , a pointer to a vector of roots is returned in the function r->X().
So you should print the roots by doing :

cout << r->X()[0] << "  " << r->X()[1] << endl;

I see also you are using a very old version, 5.34.36 and that might explains the warnings. I think in that case you need to compile the code and not work with cint.

Lorenzo

Hi Lorenzo. It works done. Thanks for your help.
I am using a old version because it properly work on win 10. I spent much time installing newer version of Root (file .exe) on win 10, but there were some same errors. So that I decided to use that version.