File indexing completed on 2025-10-27 08:58:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef ROOT_Minuit2_FCNGradAdapter
0011 #define ROOT_Minuit2_FCNGradAdapter
0012
0013 #include "Minuit2/FCNBase.h"
0014 #include "Minuit2/MnPrint.h"
0015
0016 #include <vector>
0017 #include <functional>
0018
0019 namespace ROOT {
0020
0021 namespace Minuit2 {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 template <class Function>
0035 class FCNGradAdapter : public FCNBase {
0036
0037 public:
0038 FCNGradAdapter(const Function &f, double up = 1.) : fFunc(f), fUp(up), fGrad(std::vector<double>(fFunc.NDim())) {}
0039
0040 bool HasGradient() const override { return true; }
0041
0042 double operator()(std::vector<double> const& v) const override { return fFunc.operator()(&v[0]); }
0043 double operator()(const double *v) const { return fFunc.operator()(v); }
0044
0045 double Up() const override { return fUp; }
0046
0047 std::vector<double> Gradient(std::vector<double> const& v) const override
0048 {
0049 fFunc.Gradient(&v[0], &fGrad[0]);
0050 return fGrad;
0051 }
0052 std::vector<double> GradientWithPrevResult(std::vector<double> const& v, double *previous_grad, double *previous_g2,
0053 double *previous_gstep) const override
0054 {
0055 fFunc.GradientWithPrevResult(&v[0], &fGrad[0], previous_grad, previous_g2, previous_gstep);
0056 return fGrad;
0057 }
0058
0059 GradientParameterSpace gradParameterSpace() const override {
0060 if (fFunc.returnsInMinuit2ParameterSpace()) {
0061 return GradientParameterSpace::Internal;
0062 } else {
0063 return GradientParameterSpace::External;
0064 }
0065 }
0066
0067
0068 std::vector<double> G2(std::vector<double> const& x) const override {
0069 if (fG2Func)
0070 return fG2Func(x);
0071 if (fHessianFunc) {
0072 unsigned int n = fFunc.NDim();
0073 if (fG2Vec.empty() ) fG2Vec.resize(n);
0074 if (fHessian.empty() ) fHessian.resize(n*n);
0075 fHessianFunc(x,fHessian.data());
0076 if (!fHessian.empty()) {
0077
0078 for (unsigned int i = 0; i < n; i++)
0079 fG2Vec[i] = fHessian[i*n+i];
0080 }
0081 else fG2Vec.clear();
0082 }
0083 else
0084 if (!fG2Vec.empty()) fG2Vec.clear();
0085 return fG2Vec;
0086 }
0087
0088
0089 std::vector<double> Hessian(std::vector<double> const& x ) const override {
0090 unsigned int n = fFunc.NDim();
0091 if (fHessianFunc) {
0092 if (fHessian.empty() ) fHessian.resize(n * n);
0093 bool ret = fHessianFunc(x,fHessian.data());
0094 if (!ret) {
0095 fHessian.clear();
0096 fHessianFunc = nullptr;
0097 }
0098 } else {
0099 fHessian.clear();
0100 }
0101
0102 return fHessian;
0103 }
0104
0105 bool HasG2() const override {
0106 return bool(fG2Func);
0107 }
0108 bool HasHessian() const override {
0109 return bool(fHessianFunc);
0110 }
0111
0112 template<class Func>
0113 void SetG2Function(Func f) { fG2Func = f;}
0114
0115 template<class Func>
0116 void SetHessianFunction(Func f) { fHessianFunc = f;}
0117
0118 void SetErrorDef(double up) override { fUp = up; }
0119
0120 private:
0121 const Function &fFunc;
0122 double fUp;
0123 mutable std::vector<double> fGrad;
0124 mutable std::vector<double> fHessian;
0125 mutable std::vector<double> fG2Vec;
0126
0127 std::function<std::vector<double>(std::vector<double> const& )> fG2Func;
0128 mutable std::function<bool(std::vector<double> const& , double *)> fHessianFunc;
0129 };
0130
0131 }
0132
0133 }
0134
0135 #endif