Numerical Minimization with ROOT::Math::Functor

Hi,

I am trying to use the example provided in NumericalMinimization.C in the fit tutorials to minimize a python function.
I start with the RosenBrock function from the example but get an error with the line
f = ROOT.Math.Functor(Rosenbrock(),2).

For the Rosenbrock function in python, i used the linear class as a model from this link:
root.cern.ch/svn/roottest/trunk … ontests.py

I use ROOT v5-30-02 and python 2.7.
The python code and the relevant error are below.

class RosenBrock:
    def __call__(self,args):
        x = args[0]
        y = args[1];
        tmp1 = y-x*x;
        tmp2 = 1-x;
        return 100*tmp1*tmp1+tmp2*tmp2;
def NumericalMinimization():
    min = ROOT.Math.Factory.CreateMinimizer("GSLMultiMin", "BFGS")
    min.SetMaxFunctionCalls(1000000)
    min.SetMaxIterations(100000)
    min.SetTolerance(0.001)
    min.SetPrintLevel(1)

    f = ROOT.Math.Functor(Rosenbrock(),2)

    step = [0.01,0.01]
    variable = [-1.0,1.2]
 
    min.SetFunction(f)
 
    # Set the free variables to be minimized!
    min.SetVariable(0,"x",variable[0], step[0])
    min.SetVariable(1,"y",variable[1], step[1])
 
    min.Minimize()
  Functor::Functor(void* p, unsigned int dim, const char* className = 0, const char* methodName = 0) => could not convert argument 1

I tried a few things but couldn’t get it to work. Is it possible and if so how can it be done?

Thanks in advance!

A colleague suggested using a class that inherits from TPyMultiGenFunction and pass it directly to
the SetFunction call.

His code reproduced below seems to work exactly as intended:

import ROOT as r


class Rosenbrock( r.TPyMultiGenFunction ):
    def __init__( self ):
        print "CREATED"
        r.TPyMultiGenFunction.__init__( self, self )

    def NDim( self ):
        print 'PYTHON NDim called'
        return 2

    def DoEval( self, args ):
        x = args[0]
        y = args[1];
        tmp1 = y-x*x;
        tmp2 = 1-x;
        return 100*tmp1*tmp1+tmp2*tmp2;



if __name__ == "__main__":
    min = r.Math.Factory.CreateMinimizer("GSLMultiMin", "BFGS")
    min.SetMaxFunctionCalls(1000000)
    min.SetMaxIterations(100000)
    min.SetTolerance(0.001)
    min.SetPrintLevel(1)
    rose = Rosenbrock()

    step = [0.01,0.01]
    variable = [-1.0,1.2]

    min.SetFunction(rose)

    # Set the free variables to be minimized!
    min.SetVariable(0,"x",variable[0], step[0])
    min.SetVariable(1,"y",variable[1], step[1])

    min.Minimize()

Cheers

Hi everyone,

I am aware that this is a super old topic, but I am trying to do the very same and I ran into similar troubles.

I am trying the exact same thing as pkmas explained, I would like to translate the example NumericalMinimization.C into python. I also setup a class that inherits from TPyMultiGenFunction (see the reply above this one), but I get the following error when setting the function:

min.SetFunction(rosenbrock)
TypeError: none of the 2 overloaded methods succeeded. Full details:
  attempt to access a null-pointer
  void ROOT::Math::Minimizer::SetFunction(const ROOT::Math::IGradientFunctionMultiDimTempl<double>& func) =>
    could not convert argument 1

This could be because the approach from above is quite old, maybe things changed (?) - does anyone know how to resolve this?

I am using Root version 6.18.

Thanks and Cheers!

1 Like