Skip to content

[Math] Move gradient methods to IBaseFunction classes #19070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions math/mathcore/inc/Fit/Chi2FCN.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Chi2FCN : public BasicFCN<DerivFunType, ModelFunType, BinData> {
}

// need to be virtual to be instantiated
virtual void Gradient(const double *x, double *g) const {
void Gradient(const double *x, double *g) const override {
// evaluate the chi2 gradient
FitUtil::Evaluate<T>::EvalChi2Gradient(BaseFCN::ModelFunction(), BaseFCN::Data(), x, g, fNEffPoints,
fExecutionPolicy);
Expand Down Expand Up @@ -150,7 +150,7 @@ class Chi2FCN : public BasicFCN<DerivFunType, ModelFunType, BinData> {
}

// for derivatives
virtual double DoDerivative(const double * x, unsigned int icoord) const {
double DoDerivative(const double * x, unsigned int icoord) const override {
Gradient(x, fGrad.data());
return fGrad[icoord];
}
Expand Down
4 changes: 2 additions & 2 deletions math/mathcore/inc/Fit/LogLikelihoodFCN.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class LogLikelihoodFCN : public BasicFCN<DerivFunType,ModelFunType,UnBinData> {
}

// need to be virtual to be instantiated
virtual void Gradient(const double *x, double *g) const {
void Gradient(const double *x, double *g) const override {
// evaluate the chi2 gradient
FitUtil::Evaluate<typename BaseFCN::T>::EvalLogLGradient(BaseFCN::ModelFunction(), BaseFCN::Data(), x, g,
fNEffPoints, fExecutionPolicy);
Expand Down Expand Up @@ -158,7 +158,7 @@ class LogLikelihoodFCN : public BasicFCN<DerivFunType,ModelFunType,UnBinData> {
}

// for derivatives
virtual double DoDerivative(const double * x, unsigned int icoord) const {
double DoDerivative(const double * x, unsigned int icoord) const override {
Gradient(x, &fGrad[0]);
return fGrad[icoord];
}
Expand Down
4 changes: 2 additions & 2 deletions math/mathcore/inc/Fit/PoissonLikelihoodFCN.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class PoissonLikelihoodFCN : public BasicFCN<DerivFunType,ModelFunType,BinData>
}

/// evaluate gradient
virtual void Gradient(const double *x, double *g) const
void Gradient(const double *x, double *g) const override
{
// evaluate the Poisson gradient
FitUtil::Evaluate<typename BaseFCN::T>::EvalPoissonLogLGradient(BaseFCN::ModelFunction(), BaseFCN::Data(), x, g,
Expand Down Expand Up @@ -192,7 +192,7 @@ class PoissonLikelihoodFCN : public BasicFCN<DerivFunType,ModelFunType,BinData>
}

// for derivatives
virtual double DoDerivative(const double * x, unsigned int icoord) const {
double DoDerivative(const double * x, unsigned int icoord) const override {
Gradient(x, &fGrad[0]);
return fGrad[icoord];
}
Expand Down
178 changes: 83 additions & 95 deletions math/mathcore/inc/Math/IFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,66 @@ namespace ROOT {
// if it inherits from ROOT::Math::IGradientFunctionMultiDim.
virtual bool HasGradient() const { return false; }

private:
virtual bool returnsInMinuit2ParameterSpace() const { return false; }

/// Evaluate all the vector of function derivatives (gradient) at a point x.
/// Derived classes must re-implement it if more efficient than evaluating one at a time
virtual void Gradient(const T *x, T *grad) const
{
unsigned int ndim = NDim();
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
grad[icoord] = Derivative(x, icoord);
}
}

/// In some cases, the gradient algorithm will use information from the previous step, these can be passed
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
/// so that these can be passed forward again as well at the call site, if necessary.
virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const
{
unsigned int ndim = NDim();
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep);
}
}

/// Optimized method to evaluate at the same time the function value and derivative at a point x.
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
/// Derived class should implement this method if performances play an important role and if it is faster to
/// evaluate value and derivative at the same time
virtual void FdF(const T *x, T &f, T *df) const
{
f = operator()(x);
Gradient(x, df);
}

/// Return the partial derivative with respect to the passed coordinate.
T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); }

/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
/// so that these can be passed forward again as well at the call site, if necessary.
T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2,
T *previous_gstep) const
{
return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep);
}

private:
/// Implementation of the evaluation function. Must be implemented by derived classes.
virtual T DoEval(const T *x) const = 0;

/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
virtual T DoDerivative(const T * /*x*/, unsigned int /*icoord*/) const { return {}; }

/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
/// so that these can be passed forward again as well at the call site, if necessary.
virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/,
T * /*previous_g2*/, T * /*previous_gstep*/) const
{
return DoDerivative(x, icoord);
}
};


Expand Down Expand Up @@ -135,10 +191,36 @@ namespace ROOT {
// if it inherits from ROOT::Math::IGradientFunctionOneDim.
virtual bool HasGradient() const { return false; }

/// Return the derivative of the function at a point x
/// Use the private method DoDerivative
double Derivative(double x) const { return DoDerivative(x); }

/// Compatibility method with multi-dimensional interface for partial derivative.
double Derivative(const double *x) const { return DoDerivative(*x); }

/// Compatibility method with multi-dimensional interface for Gradient.
void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); }

/// Optimized method to evaluate at the same time the function value and derivative at a point x.
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
/// Derived class should implement this method if performances play an important role and if it is faster to
/// evaluate value and derivative at the same time.
virtual void FdF(double x, double &f, double &df) const
{
f = operator()(x);
df = Derivative(x);
}

/// Compatibility method with multi-dimensional interface for Gradient and function evaluation.
void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); }

private:

/// implementation of the evaluation function. Must be implemented by derived classes
virtual double DoEval(double x) const = 0;

/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
virtual double DoDerivative(double) const { return 0.; }
};


Expand Down Expand Up @@ -170,71 +252,8 @@ namespace ROOT {
class IGradientFunctionMultiDimTempl : virtual public IBaseFunctionMultiDimTempl<T> {

public:
typedef IBaseFunctionMultiDimTempl<T> BaseFunc;
typedef IGradientFunctionMultiDimTempl<T> BaseGrad;


/// Evaluate all the vector of function derivatives (gradient) at a point x.
/// Derived classes must re-implement it if more efficient than evaluating one at a time
virtual void Gradient(const T *x, T *grad) const
{
unsigned int ndim = NDim();
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
grad[icoord] = Derivative(x, icoord);
}
}

/// In some cases, the gradient algorithm will use information from the previous step, these can be passed
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
/// so that these can be passed forward again as well at the call site, if necessary.
virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const
{
unsigned int ndim = NDim();
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep);
}
}

using BaseFunc::NDim;

/// Optimized method to evaluate at the same time the function value and derivative at a point x.
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
/// Derived class should implement this method if performances play an important role and if it is faster to
/// evaluate value and derivative at the same time
virtual void FdF(const T *x, T &f, T *df) const
{
f = BaseFunc::operator()(x);
Gradient(x, df);
}

/// Return the partial derivative with respect to the passed coordinate.
T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); }

/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
/// so that these can be passed forward again as well at the call site, if necessary.
T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2,
T *previous_gstep) const
{
return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep);
}

bool HasGradient() const override { return true; }

virtual bool returnsInMinuit2ParameterSpace() const { return false; }

private:
/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
virtual T DoDerivative(const T *x, unsigned int icoord) const = 0;

/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
/// so that these can be passed forward again as well at the call site, if necessary.
virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/,
T * /*previous_g2*/, T * /*previous_gstep*/) const
{
return DoDerivative(x, icoord);
}
};


Expand All @@ -257,38 +276,7 @@ namespace ROOT {

public:

typedef IBaseFunctionOneDim BaseFunc;
typedef IGradientFunctionOneDim BaseGrad;

/// Return the derivative of the function at a point x
/// Use the private method DoDerivative
double Derivative(double x) const { return DoDerivative(x); }

/// Compatibility method with multi-dimensional interface for partial derivative.
double Derivative(const double *x) const { return DoDerivative(*x); }

/// Compatibility method with multi-dimensional interface for Gradient.
void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); }

/// Optimized method to evaluate at the same time the function value and derivative at a point x.
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
/// Derived class should implement this method if performances play an important role and if it is faster to
/// evaluate value and derivative at the same time.
virtual void FdF(double x, double &f, double &df) const
{
f = operator()(x);
df = Derivative(x);
}

/// Compatibility method with multi-dimensional interface for Gradient and function evaluation.
void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); }

bool HasGradient() const override { return true; }

private:

/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
virtual double DoDerivative(double x) const = 0;
};


Expand Down
2 changes: 1 addition & 1 deletion math/mathmore/src/GSLNLSMinimizer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class FitTransformFunction : public FMFunc {

double DoEval(const double *x) const override { return fFunc(fTransform->Transformation(x)); }

double DoDerivative(const double * /* x */, unsigned int /*icoord*/) const
double DoDerivative(const double * /* x */, unsigned int /*icoord*/) const override
{
// not used
throw std::runtime_error("FitTransformFunction::DoDerivative");
Expand Down
2 changes: 1 addition & 1 deletion roofit/roofit/test/GaussFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class GaussFunction : public ROOT::Math::IParamMultiGradFunction {
return a * std::exp(-0.5 * y * y);
}

double DoDerivative(const double *x, unsigned int icoord) const
double DoDerivative(const double *x, unsigned int icoord) const override
{
(void)icoord;
assert(icoord == 0);
Expand Down
6 changes: 3 additions & 3 deletions roottest/root/meta/execTypedefList.C
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,17 @@ int execTypedefList() {
// res = check_target("std::list<std::string>::const_iterator","list<string>::const_iterator"); if (res) return res;

#if defined(_MSC_VER)
res = check_file("typelist_win32.v5.txt",340); if (res) return res;
res = check_file("typelist_win32.v5.txt",336); if (res) return res;
#if __cplusplus > 201402L
res = check_file("typelist_win32.v6.cxx17.txt",1408); if (res) return res;
#else
res = check_file("typelist_win32.v6.txt",1420); if (res) return res;
#endif
#elif defined(R__MACOSX) && __cplusplus > 201402L
res = check_file("typelist.v5.txt",340); if (res) return res;
res = check_file("typelist.v5.txt",336); if (res) return res;
res = check_file("typelist.v6.cxx17.txt",1310); if (res) return res;
#else
res = check_file("typelist.v5.txt",340); if (res) return res;
res = check_file("typelist.v5.txt",336); if (res) return res;
res = check_file("typelist.v6.txt",1322); if (res) return res;
#endif

Expand Down
4 changes: 0 additions & 4 deletions roottest/root/meta/typelist.v5.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ basic_istream<char,char_traits<char> >::traits_type
vector<pair<int,int>,allocator<pair<int,int> > >::size_type
ROOT::Fit::DataRange::RangeSet
TVirtualCollectionProxy::CreateIterators_t
ROOT::Math::IGradientFunctionMultiDim::BaseFunc
timespec_t
Float_t
ROOT::Fit::LogLikelihoodFCN<ROOT::Math::IGradientFunctionMultiDim>::BaseObjFunction
Expand Down Expand Up @@ -271,7 +270,6 @@ FontH_t
ROOT::Math::KDTree<ROOT::Math::TDataPoint<1,double> >::value_type
char*
vector<double,allocator<double> >::value_type
ROOT::Math::IGradientFunctionOneDim::BaseFunc
istream
TTabCom::TContainer
Ssiz_t
Expand Down Expand Up @@ -299,14 +297,12 @@ basic_stringbuf<char,char_traits<char>,allocator<char> >::char_type
ROOT::TSchemaRule::RuleType_t
vector<TString,allocator<TString> >::value_type
UShort_t
ROOT::Math::IGradientFunctionMultiDim::BaseGrad
ROOT::Math::BasicFitMethodFunction<ROOT::Math::IBaseFunctionMultiDim>::BaseFunction
basic_ostream<char,char_traits<char> >::char_type
vector<int,allocator<int> >::const_reference
string::const_iterator
ROOT::Fit::PoissonLLFunction
vector<string,allocator<string> >::const_iterator
ROOT::Math::IGradientFunctionOneDim::BaseGrad
TVirtualFitter::FCNFunc_t
KeySym_t
string::difference_type
Expand Down
4 changes: 0 additions & 4 deletions roottest/root/meta/typelist_win32.v5.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ basic_istream<char,char_traits<char> >::traits_type
vector<pair<int,int>,allocator<pair<int,int> > >::size_type
ROOT::Fit::DataRange::RangeSet
TVirtualCollectionProxy::CreateIterators_t
ROOT::Math::IGradientFunctionMultiDim::BaseFunc
timespec_t
Float_t
ROOT::Fit::LogLikelihoodFCN<ROOT::Math::IGradientFunctionMultiDim>::BaseObjFunction
Expand Down Expand Up @@ -271,7 +270,6 @@ FontH_t
ROOT::Math::KDTree<ROOT::Math::TDataPoint<1,double> >::value_type
char*
vector<double,allocator<double> >::value_type
ROOT::Math::IGradientFunctionOneDim::BaseFunc
istream
TTabCom::TContainer
Ssiz_t
Expand Down Expand Up @@ -299,14 +297,12 @@ basic_stringbuf<char,char_traits<char>,allocator<char> >::char_type
ROOT::TSchemaRule::RuleType_t
vector<TString,allocator<TString> >::value_type
UShort_t
ROOT::Math::IGradientFunctionMultiDim::BaseGrad
ROOT::Math::BasicFitMethodFunction<ROOT::Math::IBaseFunctionMultiDim>::BaseFunction
basic_ostream<char,char_traits<char> >::char_type
vector<int,allocator<int> >::const_reference
string::const_iterator
ROOT::Fit::PoissonLLFunction
vector<string,allocator<string> >::const_iterator
ROOT::Math::IGradientFunctionOneDim::BaseGrad
TVirtualFitter::FCNFunc_t
KeySym_t
string::difference_type
Expand Down
Loading