Skip to content

Commit 5bc22e4

Browse files
committed
[Math] Move gradient methods to IBaseFunction classes
Move the gradient-related methods from the `IGradientFunctionMultiDimTempl` to the `IBaseFunctionMultiDimTempl` base class, and the same for the 1D version. This makes the `IGradientFunction` classes pure "indicator" classes that indicate whether the gradient is implemented by the user or not. The actual function interface is unified in the IBaseFunctions. This fixes the problem that the override keywords could not be used consistently in I*Function-derived classes where the base class was templated to be either `IBaseFunction` or `IGradientFunction`.
1 parent 0737de3 commit 5bc22e4

File tree

7 files changed

+90
-110
lines changed

7 files changed

+90
-110
lines changed

math/mathcore/inc/Fit/Chi2FCN.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class Chi2FCN : public BasicFCN<DerivFunType, ModelFunType, BinData> {
120120
}
121121

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

152152
// for derivatives
153-
virtual double DoDerivative(const double * x, unsigned int icoord) const {
153+
double DoDerivative(const double * x, unsigned int icoord) const override {
154154
Gradient(x, fGrad.data());
155155
return fGrad[icoord];
156156
}

math/mathcore/inc/Fit/LogLikelihoodFCN.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class LogLikelihoodFCN : public BasicFCN<DerivFunType,ModelFunType,UnBinData> {
124124
}
125125

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

160160
// for derivatives
161-
virtual double DoDerivative(const double * x, unsigned int icoord) const {
161+
double DoDerivative(const double * x, unsigned int icoord) const override {
162162
Gradient(x, &fGrad[0]);
163163
return fGrad[icoord];
164164
}

math/mathcore/inc/Fit/PoissonLikelihoodFCN.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class PoissonLikelihoodFCN : public BasicFCN<DerivFunType,ModelFunType,BinData>
124124
}
125125

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

194194
// for derivatives
195-
virtual double DoDerivative(const double * x, unsigned int icoord) const {
195+
double DoDerivative(const double * x, unsigned int icoord) const override {
196196
Gradient(x, &fGrad[0]);
197197
return fGrad[icoord];
198198
}

math/mathcore/inc/Math/IFunction.h

Lines changed: 83 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,66 @@ namespace ROOT {
9191
// if it inherits from ROOT::Math::IGradientFunctionMultiDim.
9292
virtual bool HasGradient() const { return false; }
9393

94-
private:
94+
virtual bool returnsInMinuit2ParameterSpace() const { return false; }
95+
96+
/// Evaluate all the vector of function derivatives (gradient) at a point x.
97+
/// Derived classes must re-implement it if more efficient than evaluating one at a time
98+
virtual void Gradient(const T *x, T *grad) const
99+
{
100+
unsigned int ndim = NDim();
101+
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
102+
grad[icoord] = Derivative(x, icoord);
103+
}
104+
}
105+
106+
/// In some cases, the gradient algorithm will use information from the previous step, these can be passed
107+
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
108+
/// so that these can be passed forward again as well at the call site, if necessary.
109+
virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const
110+
{
111+
unsigned int ndim = NDim();
112+
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
113+
grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep);
114+
}
115+
}
116+
117+
/// Optimized method to evaluate at the same time the function value and derivative at a point x.
118+
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
119+
/// Derived class should implement this method if performances play an important role and if it is faster to
120+
/// evaluate value and derivative at the same time
121+
virtual void FdF(const T *x, T &f, T *df) const
122+
{
123+
f = operator()(x);
124+
Gradient(x, df);
125+
}
126+
127+
/// Return the partial derivative with respect to the passed coordinate.
128+
T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); }
129+
130+
/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
131+
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
132+
/// so that these can be passed forward again as well at the call site, if necessary.
133+
T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2,
134+
T *previous_gstep) const
135+
{
136+
return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep);
137+
}
95138

139+
private:
96140
/// Implementation of the evaluation function. Must be implemented by derived classes.
97141
virtual T DoEval(const T *x) const = 0;
142+
143+
/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
144+
virtual T DoDerivative(const T * /*x*/, unsigned int /*icoord*/) const { return {}; }
145+
146+
/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
147+
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
148+
/// so that these can be passed forward again as well at the call site, if necessary.
149+
virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/,
150+
T * /*previous_g2*/, T * /*previous_gstep*/) const
151+
{
152+
return DoDerivative(x, icoord);
153+
}
98154
};
99155

100156

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

194+
/// Return the derivative of the function at a point x
195+
/// Use the private method DoDerivative
196+
double Derivative(double x) const { return DoDerivative(x); }
197+
198+
/// Compatibility method with multi-dimensional interface for partial derivative.
199+
double Derivative(const double *x) const { return DoDerivative(*x); }
200+
201+
/// Compatibility method with multi-dimensional interface for Gradient.
202+
void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); }
203+
204+
/// Optimized method to evaluate at the same time the function value and derivative at a point x.
205+
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
206+
/// Derived class should implement this method if performances play an important role and if it is faster to
207+
/// evaluate value and derivative at the same time.
208+
virtual void FdF(double x, double &f, double &df) const
209+
{
210+
f = operator()(x);
211+
df = Derivative(x);
212+
}
213+
214+
/// Compatibility method with multi-dimensional interface for Gradient and function evaluation.
215+
void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); }
216+
138217
private:
139218

140219
/// implementation of the evaluation function. Must be implemented by derived classes
141220
virtual double DoEval(double x) const = 0;
221+
222+
/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
223+
virtual double DoDerivative(double) const { return 0.; }
142224
};
143225

144226

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

172254
public:
173-
typedef IBaseFunctionMultiDimTempl<T> BaseFunc;
174-
typedef IGradientFunctionMultiDimTempl<T> BaseGrad;
175-
176-
177-
/// Evaluate all the vector of function derivatives (gradient) at a point x.
178-
/// Derived classes must re-implement it if more efficient than evaluating one at a time
179-
virtual void Gradient(const T *x, T *grad) const
180-
{
181-
unsigned int ndim = NDim();
182-
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
183-
grad[icoord] = Derivative(x, icoord);
184-
}
185-
}
186-
187-
/// In some cases, the gradient algorithm will use information from the previous step, these can be passed
188-
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
189-
/// so that these can be passed forward again as well at the call site, if necessary.
190-
virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const
191-
{
192-
unsigned int ndim = NDim();
193-
for (unsigned int icoord = 0; icoord < ndim; ++icoord) {
194-
grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep);
195-
}
196-
}
197-
198-
using BaseFunc::NDim;
199-
200-
/// Optimized method to evaluate at the same time the function value and derivative at a point x.
201-
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
202-
/// Derived class should implement this method if performances play an important role and if it is faster to
203-
/// evaluate value and derivative at the same time
204-
virtual void FdF(const T *x, T &f, T *df) const
205-
{
206-
f = BaseFunc::operator()(x);
207-
Gradient(x, df);
208-
}
209-
210-
/// Return the partial derivative with respect to the passed coordinate.
211-
T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); }
212-
213-
/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
214-
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
215-
/// so that these can be passed forward again as well at the call site, if necessary.
216-
T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2,
217-
T *previous_gstep) const
218-
{
219-
return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep);
220-
}
221255

222256
bool HasGradient() const override { return true; }
223-
224-
virtual bool returnsInMinuit2ParameterSpace() const { return false; }
225-
226-
private:
227-
/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
228-
virtual T DoDerivative(const T *x, unsigned int icoord) const = 0;
229-
230-
/// In some cases, the derivative algorithm will use information from the previous step, these can be passed
231-
/// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
232-
/// so that these can be passed forward again as well at the call site, if necessary.
233-
virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/,
234-
T * /*previous_g2*/, T * /*previous_gstep*/) const
235-
{
236-
return DoDerivative(x, icoord);
237-
}
238257
};
239258

240259

@@ -257,38 +276,7 @@ namespace ROOT {
257276

258277
public:
259278

260-
typedef IBaseFunctionOneDim BaseFunc;
261-
typedef IGradientFunctionOneDim BaseGrad;
262-
263-
/// Return the derivative of the function at a point x
264-
/// Use the private method DoDerivative
265-
double Derivative(double x) const { return DoDerivative(x); }
266-
267-
/// Compatibility method with multi-dimensional interface for partial derivative.
268-
double Derivative(const double *x) const { return DoDerivative(*x); }
269-
270-
/// Compatibility method with multi-dimensional interface for Gradient.
271-
void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); }
272-
273-
/// Optimized method to evaluate at the same time the function value and derivative at a point x.
274-
/// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
275-
/// Derived class should implement this method if performances play an important role and if it is faster to
276-
/// evaluate value and derivative at the same time.
277-
virtual void FdF(double x, double &f, double &df) const
278-
{
279-
f = operator()(x);
280-
df = Derivative(x);
281-
}
282-
283-
/// Compatibility method with multi-dimensional interface for Gradient and function evaluation.
284-
void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); }
285-
286279
bool HasGradient() const override { return true; }
287-
288-
private:
289-
290-
/// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
291-
virtual double DoDerivative(double x) const = 0;
292280
};
293281

294282

math/mathmore/src/GSLNLSMinimizer.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class FitTransformFunction : public FMFunc {
106106

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

109-
double DoDerivative(const double * /* x */, unsigned int /*icoord*/) const
109+
double DoDerivative(const double * /* x */, unsigned int /*icoord*/) const override
110110
{
111111
// not used
112112
throw std::runtime_error("FitTransformFunction::DoDerivative");

roottest/root/meta/typelist.v5.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ basic_istream<char,char_traits<char> >::traits_type
134134
vector<pair<int,int>,allocator<pair<int,int> > >::size_type
135135
ROOT::Fit::DataRange::RangeSet
136136
TVirtualCollectionProxy::CreateIterators_t
137-
ROOT::Math::IGradientFunctionMultiDim::BaseFunc
138137
timespec_t
139138
Float_t
140139
ROOT::Fit::LogLikelihoodFCN<ROOT::Math::IGradientFunctionMultiDim>::BaseObjFunction
@@ -271,7 +270,6 @@ FontH_t
271270
ROOT::Math::KDTree<ROOT::Math::TDataPoint<1,double> >::value_type
272271
char*
273272
vector<double,allocator<double> >::value_type
274-
ROOT::Math::IGradientFunctionOneDim::BaseFunc
275273
istream
276274
TTabCom::TContainer
277275
Ssiz_t
@@ -299,14 +297,12 @@ basic_stringbuf<char,char_traits<char>,allocator<char> >::char_type
299297
ROOT::TSchemaRule::RuleType_t
300298
vector<TString,allocator<TString> >::value_type
301299
UShort_t
302-
ROOT::Math::IGradientFunctionMultiDim::BaseGrad
303300
ROOT::Math::BasicFitMethodFunction<ROOT::Math::IBaseFunctionMultiDim>::BaseFunction
304301
basic_ostream<char,char_traits<char> >::char_type
305302
vector<int,allocator<int> >::const_reference
306303
string::const_iterator
307304
ROOT::Fit::PoissonLLFunction
308305
vector<string,allocator<string> >::const_iterator
309-
ROOT::Math::IGradientFunctionOneDim::BaseGrad
310306
TVirtualFitter::FCNFunc_t
311307
KeySym_t
312308
string::difference_type

roottest/root/meta/typelist_win32.v5.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ basic_istream<char,char_traits<char> >::traits_type
133133
vector<pair<int,int>,allocator<pair<int,int> > >::size_type
134134
ROOT::Fit::DataRange::RangeSet
135135
TVirtualCollectionProxy::CreateIterators_t
136-
ROOT::Math::IGradientFunctionMultiDim::BaseFunc
137136
timespec_t
138137
Float_t
139138
ROOT::Fit::LogLikelihoodFCN<ROOT::Math::IGradientFunctionMultiDim>::BaseObjFunction
@@ -271,7 +270,6 @@ FontH_t
271270
ROOT::Math::KDTree<ROOT::Math::TDataPoint<1,double> >::value_type
272271
char*
273272
vector<double,allocator<double> >::value_type
274-
ROOT::Math::IGradientFunctionOneDim::BaseFunc
275273
istream
276274
TTabCom::TContainer
277275
Ssiz_t
@@ -299,14 +297,12 @@ basic_stringbuf<char,char_traits<char>,allocator<char> >::char_type
299297
ROOT::TSchemaRule::RuleType_t
300298
vector<TString,allocator<TString> >::value_type
301299
UShort_t
302-
ROOT::Math::IGradientFunctionMultiDim::BaseGrad
303300
ROOT::Math::BasicFitMethodFunction<ROOT::Math::IBaseFunctionMultiDim>::BaseFunction
304301
basic_ostream<char,char_traits<char> >::char_type
305302
vector<int,allocator<int> >::const_reference
306303
string::const_iterator
307304
ROOT::Fit::PoissonLLFunction
308305
vector<string,allocator<string> >::const_iterator
309-
ROOT::Math::IGradientFunctionOneDim::BaseGrad
310306
TVirtualFitter::FCNFunc_t
311307
KeySym_t
312308
string::difference_type

0 commit comments

Comments
 (0)