Hi all,
I would like to use the BFGS2 algorithm provided by the GSL minimizer library for a multidimensional minimization. I have optimized functions which return the gradient of my function, as well as an optimized function that returns the function value and its gradient. As indicated in the Math::Minimizer class, I need to derive a class from ROOT::Math::IGradientFunctionMultiDim and overload the Gradient and FdF functions. This is done here:
#include "Math/IFunction.h"
struct JppGradEFunc : public ROOT::Math::IGradientFunctionMultiDimTempl<double>
{
JppShowerE_simple* pdf;
virtual ROOT::Math::IGradientFunctionMultiDimTempl<double> *Clone() const { return new JppGradEFunc(*this); }
virtual unsigned int NDim () const { return 7; }
virtual double DoEval(const double *x) const
{
double res = pdf -> eval_lik( pow( 10, x[0] ), x[1], x[2], x[3], x[4], x[5], x[6] ); //use pdf here
cout << "res DoEval: " << res << " x[0]: " << x[0] << " x[1]: " << x[1] << " x[2]: " << x[2] << " x[3]: " << x[3] << " x[4]: " << x[4] << " x[5]: " << x[5] << " x[6]: " << x[6] << endl;
return res;
}
virtual double operator()(const double *x) const
{
double res = pdf -> eval_lik( pow( 10, x[0] ), x[1], x[2], x[3], x[4], x[5], x[6] ); //use pdf here
cout << "res operator(): " << res << " x[0]: " << x[0] << " x[1]: " << x[1] << " x[2]: " << x[2] << " x[3]: " << x[3] << " x[4]: " << x[4] << " x[5]: " << x[5] << " x[6]: " << x[6] << endl;
return res;
}
virtual double DoDerivative(const double *x,
unsigned int icoord) const
{
std::pair< double, vector< double > > res = pdf -> eval_lik_grad( pow( 10, x[0] ), x[1], x[2], x[3], x[4], x[5], x[6] );
res.second[0] *= pow( 10, x[0] ) * 2.3025850929940; //ln(10), dE/dlogE
cout << "res DoDerivative: " << res.second[icoord] << " x[0]: " << x[0] << " x[1]: " << x[1] << " x[2]: " << x[2] << " x[3]: " << x[3] << " x[4]: " << x[4] << " x[5]: " << x[5] << " x[6]: " << x[6] << endl;
return res.second[icoord];
}
virtual void FdF (const double* x, double& f, double* df) const
{
std::pair< double, vector< double > > res = pdf -> eval_lik_grad( pow( 10, x[0] ), x[1], x[2], x[3], x[4], x[5], x[6] );
f = res.first;
res.second[0] *= pow( 10, x[0] ) * 2.3025850929940; //ln(10), dE/dlogE
for( uint ii = 0; ii != 7; ii++ ) df[ii] = res.second[ii];
print ( "fdf", f, df[0], df[1], df[2], df[3], df[4], df[5], df[6] );
}
virtual void Gradient (const double* x, double* df) const
{
std::pair< double, vector< double > > res = pdf -> eval_lik_grad( pow( 10, x[0] ), x[1], x[2], x[3], x[4], x[5], x[6] );
res.second[0] *= pow( 10, x[0] ) * 2.3025850929940; //ln(10), dE/dlogE
for( uint ii = 0; ii != 7; ii++ ) df[ii] = res.second[ii];
print ( "Gradient", df[0], df[1], df[2], df[3], df[4], df[5], df[6] );
}
};
Unfortunately, here is a typical output of the minimizer:
res DoEval: 5158.01 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: 42.5176 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: -3.98599 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: 25.6745 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: 1.80081 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: -42.2422 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: 9.89843 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
res DoDerivative: 16.6893 x[0]: 3.56329 x[1]: -406.648 x[2]: 54.4139 x[3]: 217.13 x[4]: 1.87961 x[5]: 2.83086 x[6]: 10.0575
The Gradient and FdF functions are not used at all! What gives?
I did attempt to use Migrad from Minuit2. In that case, the Gradient function was indeed used, but not the FdF function.
Thank you in advance for the help!
ROOT Version: 6.22/06
Platform: Not Provided
Compiler: g++ 4.8.5