|
||||
File indexing completed on 2025-01-30 10:22:05
0001 // @(#)root/mathcore:$Id$ 0002 // Authors: L. Moneta 11/2006 0003 0004 /********************************************************************** 0005 * * 0006 * Copyright (c) 2006 , LCG ROOT MathLib Team * 0007 * * 0008 * * 0009 **********************************************************************/ 0010 0011 // Header file for function interfaces 0012 // 0013 // Generic Interfaces for one or multi-dimensional functions 0014 // 0015 // Created by: Lorenzo Moneta : Wed Nov 13 2006 0016 // 0017 // 0018 #ifndef ROOT_Math_IFunction 0019 #define ROOT_Math_IFunction 0020 0021 /** 0022 @defgroup CppFunctions Function Classes and Interfaces 0023 0024 Interfaces (abstract classes) and Base classes used in MathCore and MathMore numerical methods 0025 for describing function classes. They define function and gradient evaluation and as well the 0026 functionality for dealing with parameters in the case of parametric functions which are used for 0027 fitting and data modeling. 0028 Included are also adapter classes, such as functors, to wrap generic callable C++ objects 0029 in the desired interface. 0030 0031 @ingroup MathCore 0032 */ 0033 0034 #include "Math/IFunctionfwd.h" 0035 0036 0037 namespace ROOT { 0038 namespace Math { 0039 0040 /** 0041 @defgroup GenFunc Generic Function Evaluation Interfaces 0042 Interface classes for evaluation of function object classes in one or multi-dimensions. 0043 @ingroup CppFunctions 0044 */ 0045 0046 //___________________________________________________________________________________ 0047 /** 0048 Documentation for the abstract class IBaseFunctionMultiDim. 0049 Interface (abstract class) for generic functions objects of multi-dimension 0050 Provides a method to evaluate the function given a vector of coordinate values, 0051 by implementing operator() (const double *). 0052 In addition it defines the interface for copying functions via the pure virtual method Clone() 0053 and the interface for getting the function dimension via the NDim() method. 0054 Derived classes must implement the pure private virtual method DoEval(const double *) for the 0055 function evaluation in addition to NDim() and Clone(). 0056 0057 @ingroup GenFunc 0058 */ 0059 0060 template<class T> 0061 class IBaseFunctionMultiDimTempl { 0062 0063 public: 0064 0065 typedef T BackendType; 0066 typedef IBaseFunctionMultiDimTempl<T> BaseFunc; 0067 0068 virtual ~IBaseFunctionMultiDimTempl() = default; 0069 0070 /// Clone a function. 0071 /// Each derived class must implement their version of the Clone method. 0072 virtual IBaseFunctionMultiDimTempl<T> *Clone() const = 0; 0073 0074 /// Retrieve the dimension of the function. 0075 virtual unsigned int NDim() const = 0; 0076 0077 /// Evaluate the function at a point x[]. 0078 /// Use the pure virtual private method DoEval which must be implemented by the sub-classes. 0079 T operator()(const T *x) const { return DoEval(x); } 0080 0081 #ifdef LATER 0082 /// Template method to evaluate the function using the begin of an iterator. 0083 /// User is responsible to provide correct size for the iterator. 0084 template <class Iterator> 0085 T operator()(const Iterator it) const { return DoEval(&(*it)); } 0086 #endif 0087 0088 // Indicate whether this class supports gradient calculations, i.e., 0089 // if it inherits from ROOT::Math::IGradientFunctionMultiDim. 0090 virtual bool HasGradient() const { return false; } 0091 0092 private: 0093 0094 /// Implementation of the evaluation function. Must be implemented by derived classes. 0095 virtual T DoEval(const T *x) const = 0; 0096 }; 0097 0098 0099 //___________________________________________________________________________________ 0100 /** 0101 Interface (abstract class) for generic functions objects of one-dimension 0102 Provides a method to evaluate the function given a value (simple double) 0103 by implementing operator() (const double ). 0104 In addition it defines the interface for copying functions via the pure virtual method Clone(). 0105 Derived classes must implement the pure virtual private method DoEval(double ) for the 0106 function evaluation in addition to Clone(). 0107 An interface for evaluating the function passing a vector (like for multidim functions) is also 0108 provided 0109 0110 @ingroup GenFunc 0111 */ 0112 class IBaseFunctionOneDim { 0113 0114 public: 0115 0116 typedef IBaseFunctionOneDim BaseFunc; 0117 0118 virtual ~IBaseFunctionOneDim() = default; 0119 0120 /// Clone a function. 0121 /// Each derived class will implement their version of the private DoClone method. 0122 virtual IBaseFunctionOneDim *Clone() const = 0; 0123 0124 /// Evaluate the function at a point x. 0125 /// Use the a pure virtual private method DoEval which must be implemented by sub-classes. 0126 double operator()(double x) const { return DoEval(x); } 0127 0128 /// Evaluate the function at a point x[]. 0129 /// Compatible method with multi-dimensional functions. 0130 double operator()(const double *x) const { return DoEval(*x); } 0131 0132 // Indicate whether this class supports gradient calculations, i.e., 0133 // if it inherits from ROOT::Math::IGradientFunctionOneDim. 0134 virtual bool HasGradient() const { return false; } 0135 0136 private: 0137 0138 /// implementation of the evaluation function. Must be implemented by derived classes 0139 virtual double DoEval(double x) const = 0; 0140 }; 0141 0142 0143 //-------- GRAD functions--------------------------- 0144 0145 0146 0147 //___________________________________________________________________________________ 0148 /** 0149 Interface (abstract class) for multi-dimensional functions providing a gradient calculation. 0150 The method ROOT::Math::IFunction::Gradient calculates the full gradient vector, 0151 ROOT::Math::IFunction::Derivative calculates the partial derivative for each coordinate and 0152 ROOT::Math::Fdf calculates the gradient and the function value at the same time. 0153 The pure private virtual method DoDerivative() must be implemented by the derived classes, while 0154 Gradient and FdF are by default implemented using DoDerivative, butthey can be overloaded by the 0155 derived classes to improve the efficiency in the derivative calculation. 0156 0157 Gradient interface (abstract class) defining the signature for calculating the gradient of a 0158 multi-dimensional function. 0159 Three methods are provided: 0160 - Gradient(const double *x, double * grad) evaluate the full gradient vector at the vector value x 0161 - Derivative(const double * x, int icoord) evaluate the partial derivative for the icoord coordinate 0162 - FdF(const double *x, double &f, double * g) evaluate at the same time gradient and function/ 0163 0164 @ingroup GenFunc 0165 */ 0166 0167 template <class T> 0168 class IGradientFunctionMultiDimTempl : virtual public IBaseFunctionMultiDimTempl<T> { 0169 0170 public: 0171 typedef IBaseFunctionMultiDimTempl<T> BaseFunc; 0172 typedef IGradientFunctionMultiDimTempl<T> BaseGrad; 0173 0174 0175 /// Evaluate all the vector of function derivatives (gradient) at a point x. 0176 /// Derived classes must re-implement it if more efficient than evaluating one at a time 0177 virtual void Gradient(const T *x, T *grad) const 0178 { 0179 unsigned int ndim = NDim(); 0180 for (unsigned int icoord = 0; icoord < ndim; ++icoord) { 0181 grad[icoord] = Derivative(x, icoord); 0182 } 0183 } 0184 0185 /// In some cases, the gradient algorithm will use information from the previous step, these can be passed 0186 /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size 0187 /// so that these can be passed forward again as well at the call site, if necessary. 0188 virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const 0189 { 0190 unsigned int ndim = NDim(); 0191 for (unsigned int icoord = 0; icoord < ndim; ++icoord) { 0192 grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep); 0193 } 0194 } 0195 0196 using BaseFunc::NDim; 0197 0198 /// Optimized method to evaluate at the same time the function value and derivative at a point x. 0199 /// Often both value and derivatives are needed and it is often more efficient to compute them at the same time. 0200 /// Derived class should implement this method if performances play an important role and if it is faster to 0201 /// evaluate value and derivative at the same time 0202 virtual void FdF(const T *x, T &f, T *df) const 0203 { 0204 f = BaseFunc::operator()(x); 0205 Gradient(x, df); 0206 } 0207 0208 /// Return the partial derivative with respect to the passed coordinate. 0209 T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); } 0210 0211 /// In some cases, the derivative algorithm will use information from the previous step, these can be passed 0212 /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size 0213 /// so that these can be passed forward again as well at the call site, if necessary. 0214 T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2, 0215 T *previous_gstep) const 0216 { 0217 return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep); 0218 } 0219 0220 bool HasGradient() const { return true; } 0221 0222 virtual bool returnsInMinuit2ParameterSpace() const { return false; } 0223 0224 private: 0225 /// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class. 0226 virtual T DoDerivative(const T *x, unsigned int icoord) const = 0; 0227 0228 /// In some cases, the derivative algorithm will use information from the previous step, these can be passed 0229 /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size 0230 /// so that these can be passed forward again as well at the call site, if necessary. 0231 virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/, 0232 T * /*previous_g2*/, T * /*previous_gstep*/) const 0233 { 0234 return DoDerivative(x, icoord); 0235 } 0236 }; 0237 0238 0239 //___________________________________________________________________________________ 0240 /** 0241 Interface (abstract class) for one-dimensional functions providing a gradient calculation. 0242 The method ROOT::Math::IFunction::Derivative calculates the derivative and 0243 ROOT::Math::Fdf calculates the derivative and the function values at the same time. 0244 The pure private virtual method DoDerivative() must be implemented by the derived classes, while 0245 FdF is by default implemented using DoDerivative, but it can be overloaded by the 0246 derived classes to improve the efficiency in the derivative calculation. 0247 0248 Specialized Gradient interface(abstract class) for one dimensional functions 0249 It provides a method to evaluate the derivative of the function, Derivative and a 0250 method to evaluate at the same time the function and the derivative FdF 0251 0252 @ingroup GenFunc 0253 */ 0254 class IGradientFunctionOneDim : virtual public IBaseFunctionOneDim { 0255 0256 public: 0257 0258 typedef IBaseFunctionOneDim BaseFunc; 0259 typedef IGradientFunctionOneDim BaseGrad; 0260 0261 /// Return the derivative of the function at a point x 0262 /// Use the private method DoDerivative 0263 double Derivative(double x) const { return DoDerivative(x); } 0264 0265 /// Compatibility method with multi-dimensional interface for partial derivative. 0266 double Derivative(const double *x) const { return DoDerivative(*x); } 0267 0268 /// Compatibility method with multi-dimensional interface for Gradient. 0269 void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); } 0270 0271 /// Optimized method to evaluate at the same time the function value and derivative at a point x. 0272 /// Often both value and derivatives are needed and it is often more efficient to compute them at the same time. 0273 /// Derived class should implement this method if performances play an important role and if it is faster to 0274 /// evaluate value and derivative at the same time. 0275 virtual void FdF(double x, double &f, double &df) const 0276 { 0277 f = operator()(x); 0278 df = Derivative(x); 0279 } 0280 0281 /// Compatibility method with multi-dimensional interface for Gradient and function evaluation. 0282 void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); } 0283 0284 bool HasGradient() const override { return true; } 0285 0286 private: 0287 0288 /// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class. 0289 virtual double DoDerivative(double x) const = 0; 0290 }; 0291 0292 0293 0294 } // namespace Math 0295 } // namespace ROOT 0296 0297 #endif /* ROOT_Math_IFunction */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |