Warning, file /include/root/Fit/FitUtil.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef ROOT_Fit_FitUtil
0014 #define ROOT_Fit_FitUtil
0015
0016 #include "Math/IParamFunctionfwd.h"
0017 #include "Math/IParamFunction.h"
0018
0019 #include "Fit/BinData.h"
0020 #include "Fit/UnBinData.h"
0021 #include "ROOT/EExecutionPolicy.hxx"
0022
0023 #include "Math/Integrator.h"
0024 #include "Math/IntegratorMultiDim.h"
0025
0026 #include "TError.h"
0027 #include <vector>
0028
0029
0030 #define USE_PARAMCACHE
0031
0032
0033
0034 namespace ROOT {
0035
0036 namespace Fit {
0037
0038
0039
0040
0041
0042
0043
0044 namespace FitUtil {
0045
0046 typedef ROOT::Math::IParamMultiFunction IModelFunction;
0047 typedef ROOT::Math::IParamMultiGradFunction IGradModelFunction;
0048
0049 template <class T>
0050 using IGradModelFunctionTempl = ROOT::Math::IParamMultiGradFunctionTempl<T>;
0051
0052 template <class T>
0053 using IModelFunctionTempl = ROOT::Math::IParamMultiFunctionTempl<T>;
0054
0055
0056 template <class T>
0057 class LikelihoodAux {
0058 public:
0059 LikelihoodAux(T logv = {}, T w = {}, T w2 = {}) : logvalue(logv), weight(w), weight2(w2) {}
0060
0061 LikelihoodAux operator+(const LikelihoodAux &l) const
0062 {
0063 return LikelihoodAux<T>(logvalue + l.logvalue, weight + l.weight, weight2 + l.weight2);
0064 }
0065
0066 LikelihoodAux &operator+=(const LikelihoodAux &l)
0067 {
0068 logvalue += l.logvalue;
0069 weight += l.weight;
0070 weight2 += l.weight2;
0071 return *this;
0072 }
0073
0074 T logvalue;
0075 T weight;
0076 T weight2;
0077 };
0078
0079 template <>
0080 class LikelihoodAux<double> {
0081 public:
0082 LikelihoodAux(double logv = 0.0, double w = 0.0, double w2 = 0.0) : logvalue(logv), weight(w), weight2(w2){};
0083
0084 LikelihoodAux operator+(const LikelihoodAux &l) const
0085 {
0086 return LikelihoodAux<double>(logvalue + l.logvalue, weight + l.weight, weight2 + l.weight2);
0087 }
0088
0089 LikelihoodAux &operator+=(const LikelihoodAux &l)
0090 {
0091 logvalue += l.logvalue;
0092 weight += l.weight;
0093 weight2 += l.weight2;
0094 return *this;
0095 }
0096
0097 double logvalue;
0098 double weight;
0099 double weight2;
0100 };
0101
0102
0103
0104
0105
0106
0107
0108
0109 template <class ParamFunc = ROOT::Math::IParamMultiFunctionTempl<double>>
0110 class IntegralEvaluator {
0111
0112 public:
0113 IntegralEvaluator(const ParamFunc &func, const double *p, bool useIntegral = true,
0114 ROOT::Math::IntegrationOneDim::Type igType = ROOT::Math::IntegrationOneDim::kDEFAULT)
0115 : fDim(0), fParams(nullptr), fFunc(nullptr), fIg1Dim(nullptr), fIgNDim(nullptr), fFunc1Dim(nullptr), fFuncNDim(nullptr)
0116 {
0117 if (useIntegral) {
0118 SetFunction(func, p, igType);
0119 }
0120 }
0121
0122 void SetFunction(const ParamFunc &func, const double *p = nullptr,
0123 ROOT::Math::IntegrationOneDim::Type igType = ROOT::Math::IntegrationOneDim::kDEFAULT)
0124 {
0125
0126
0127 fParams = p;
0128 fDim = func.NDim();
0129
0130
0131 fFunc = &func;
0132 assert(fFunc != nullptr);
0133
0134
0135 if (fDim == 1) {
0136 fFunc1Dim =
0137 new ROOT::Math::WrappedMemFunction<IntegralEvaluator, double (IntegralEvaluator::*)(double) const>(
0138 *this, &IntegralEvaluator::F1);
0139 fIg1Dim = new ROOT::Math::IntegratorOneDim(igType);
0140
0141 fIg1Dim->SetFunction(static_cast<const ROOT::Math::IGenFunction &>(*fFunc1Dim));
0142 } else if (fDim > 1) {
0143 fFuncNDim =
0144 new ROOT::Math::WrappedMemMultiFunction<IntegralEvaluator, double (IntegralEvaluator::*)(const double *)
0145 const>(*this, &IntegralEvaluator::FN, fDim);
0146 fIgNDim = new ROOT::Math::IntegratorMultiDim();
0147 fIgNDim->SetFunction(*fFuncNDim);
0148 } else
0149 assert(fDim > 0);
0150 }
0151
0152 void SetParameters(const double *p)
0153 {
0154
0155 fParams = p;
0156 }
0157
0158 ~IntegralEvaluator()
0159 {
0160 if (fIg1Dim)
0161 delete fIg1Dim;
0162 if (fIgNDim)
0163 delete fIgNDim;
0164 if (fFunc1Dim)
0165 delete fFunc1Dim;
0166 if (fFuncNDim)
0167 delete fFuncNDim;
0168
0169 }
0170
0171
0172 double F1(double x) const
0173 {
0174 double xx = x;
0175 return ExecFunc(fFunc, &xx, fParams);
0176 }
0177
0178 double FN(const double *x) const { return ExecFunc(fFunc, x, fParams); }
0179
0180 double Integral(const double *x1, const double *x2)
0181 {
0182
0183 return (fIg1Dim) ? fIg1Dim->Integral(*x1, *x2) : fIgNDim->Integral(x1, x2);
0184 }
0185
0186 double operator()(const double *x1, const double *x2)
0187 {
0188
0189 if (fIg1Dim) {
0190 double dV = *x2 - *x1;
0191 return fIg1Dim->Integral(*x1, *x2) / dV;
0192 } else if (fIgNDim) {
0193 double dV = 1;
0194 for (unsigned int i = 0; i < fDim; ++i)
0195 dV *= (x2[i] - x1[i]);
0196 return fIgNDim->Integral(x1, x2) / dV;
0197
0198
0199 } else
0200 assert(1.);
0201 return 0;
0202 }
0203
0204 private:
0205 template <class T>
0206 inline double ExecFunc(T *f, const double *x, const double *p) const
0207 {
0208 return (*f)(x, p);
0209 }
0210
0211 #ifdef R__HAS_STD_EXPERIMENTAL_SIMD
0212
0213 #if __clang_major__ > 16
0214 #pragma clang diagnostic push
0215 #pragma clang diagnostic ignored "-Wvla-cxx-extension"
0216 #endif
0217
0218 inline double ExecFunc(const IModelFunctionTempl<ROOT::Double_v> *f, const double *x, const double *p) const
0219 {
0220 ROOT::Double_v xx[fDim];
0221 for (unsigned int i = 0; i < fDim; ++i) {
0222 xx[i][0] = x[i];
0223 for (std::size_t j = 1; j < ROOT::Double_v::size(); ++j) {
0224 xx[i][j] = 0.0;
0225 }
0226 }
0227 auto res = (*f)(xx, p);
0228 return res[0];
0229 }
0230
0231 #if __clang_major__ > 16
0232 #pragma clang diagnostic pop
0233 #endif
0234
0235 #endif
0236
0237
0238 IntegralEvaluator(const IntegralEvaluator &rhs) = delete;
0239 IntegralEvaluator &operator=(const IntegralEvaluator &rhs) = delete;
0240
0241 unsigned int fDim;
0242 const double *fParams;
0243
0244
0245 const ParamFunc *fFunc;
0246 ROOT::Math::IntegratorOneDim *fIg1Dim;
0247 ROOT::Math::IntegratorMultiDim *fIgNDim;
0248 ROOT::Math::IGenFunction *fFunc1Dim;
0249 ROOT::Math::IMultiGenFunction *fFuncNDim;
0250 };
0251
0252
0253
0254
0255
0256
0257
0258 double EvaluateChi2(const IModelFunction &func, const BinData &data, const double *p, unsigned int &nPoints,
0259 ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0);
0260
0261
0262
0263
0264
0265
0266 double EvaluateChi2Effective(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints);
0267
0268
0269
0270
0271
0272 void EvaluateChi2Gradient(const IModelFunction &func, const BinData &data, const double *p, double *grad,
0273 unsigned int &nPoints,
0274 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0275 unsigned nChunks = 0);
0276
0277
0278
0279
0280
0281 double EvaluateLogL(const IModelFunction &func, const UnBinData &data, const double *p, int iWeight, bool extended,
0282 unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0);
0283
0284
0285
0286
0287
0288 void EvaluateLogLGradient(const IModelFunction &func, const UnBinData &data, const double *p, double *grad,
0289 unsigned int &nPoints,
0290 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0291 unsigned nChunks = 0);
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 double EvaluatePoissonLogL(const IModelFunction &func, const BinData &data, const double *p, int iWeight,
0305 bool extended, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy,
0306 unsigned nChunks = 0);
0307
0308
0309
0310
0311
0312 void EvaluatePoissonLogLGradient(const IModelFunction &func, const BinData &data, const double *p, double *grad,
0313 unsigned int &nPoints,
0314 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0315 unsigned nChunks = 0);
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 double EvaluateChi2Residual(const IModelFunction &func, const BinData &data, const double *p, unsigned int ipoint,
0326 double *g = nullptr, double * h = nullptr, bool hasGrad = false, bool fullHessian = false);
0327
0328
0329
0330
0331
0332
0333
0334 double
0335 EvaluatePdf(const IModelFunction &func, const UnBinData &data, const double *p, unsigned int ipoint, double *g = nullptr, double * h = nullptr, bool hasGrad = false, bool fullHessian = false);
0336
0337
0338
0339
0340
0341
0342
0343
0344 double EvaluatePoissonBinPdf(const IModelFunction & func, const BinData & data, const double * x, unsigned int ipoint, double * g = nullptr, double * h = nullptr, bool hasGrad = false, bool fullHessian = false);
0345
0346 unsigned setAutomaticChunking(unsigned nEvents);
0347
0348 template <class T>
0349 struct Evaluate {};
0350
0351 #ifdef R__HAS_STD_EXPERIMENTAL_SIMD
0352 template <>
0353 struct Evaluate<Double_v> {
0354 static double EvalChi2(const IModelFunctionTempl<Double_v> &func, const BinData &data, const double *p,
0355 unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0);
0356
0357 static double EvalLogL(const IModelFunctionTempl<Double_v> &func, const UnBinData &data, const double *const p,
0358 int iWeight, bool extended, unsigned int &nPoints,
0359 ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0);
0360
0361 static double EvalPoissonLogL(const IModelFunctionTempl<Double_v> &func, const BinData &data, const double *p,
0362 int iWeight, bool extended, unsigned int, ::ROOT::EExecutionPolicy executionPolicy,
0363 unsigned nChunks = 0);
0364
0365 static double
0366 EvalChi2Effective(const IModelFunctionTempl<Double_v> &, const BinData &, const double *, unsigned int &)
0367 {
0368 Error("FitUtil::Evaluate<T>::EvalChi2Effective", "The vectorized evaluation of the Chi2 with coordinate errors is still not supported");
0369 return -1.;
0370 }
0371
0372 static void EvalChi2Gradient(const IModelFunctionTempl<Double_v> &f, const BinData &data, const double *p,
0373 double *grad, unsigned int &nPoints,
0374 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0375 unsigned nChunks = 0);
0376
0377 static double EvalChi2Residual(const IModelFunctionTempl<Double_v> &, const BinData &, const double *,
0378 unsigned int, double *, double *, bool, bool)
0379 {
0380 Error("FitUtil::Evaluate<T>::EvalChi2Residual", "The vectorized evaluation of the Chi2 with the ith residual is still not supported");
0381 return -1.;
0382 }
0383
0384
0385
0386 static double EvalPoissonBinPdf(const IModelFunctionTempl<Double_v> &, const BinData &, const double *,
0387 unsigned int, double *, double *, bool, bool)
0388 {
0389 Error("FitUtil::Evaluate<T>::EvaluatePoissonBinPdf", "The vectorized evaluation of the BinnedLikelihood fit evaluated point by point is still not supported");
0390 return -1.;
0391 }
0392
0393 static double EvalPdf(const IModelFunctionTempl<Double_v> &, const UnBinData &, const double *, unsigned int,
0394 double *, double *, bool, bool)
0395 {
0396 Error("FitUtil::Evaluate<T>::EvalPdf", "The vectorized evaluation of the LogLikelihood fit evaluated point by point is still not supported");
0397 return -1.;
0398 }
0399
0400 static void
0401 EvalPoissonLogLGradient(const IModelFunctionTempl<Double_v> &f, const BinData &data, const double *p,
0402 double *grad, unsigned int &,
0403 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0404 unsigned nChunks = 0);
0405
0406 static void EvalLogLGradient(const IModelFunctionTempl<Double_v> &f, const UnBinData &data, const double *p,
0407 double *grad, unsigned int &,
0408 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0409 unsigned nChunks = 0);
0410 };
0411 #endif
0412
0413 template <>
0414 struct Evaluate<double> {
0415
0416 static double EvalChi2(const IModelFunction &func, const BinData &data, const double *p, unsigned int &nPoints,
0417 ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0)
0418 {
0419
0420
0421
0422
0423
0424
0425
0426
0427 return FitUtil::EvaluateChi2(func, data, p, nPoints, executionPolicy, nChunks);
0428 }
0429
0430 static double EvalLogL(const IModelFunctionTempl<double> &func, const UnBinData &data, const double *p,
0431 int iWeight, bool extended, unsigned int &nPoints,
0432 ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0)
0433 {
0434 return FitUtil::EvaluateLogL(func, data, p, iWeight, extended, nPoints, executionPolicy, nChunks);
0435 }
0436
0437 static double EvalPoissonLogL(const IModelFunctionTempl<double> &func, const BinData &data, const double *p,
0438 int iWeight, bool extended, unsigned int &nPoints,
0439 ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks = 0)
0440 {
0441 return FitUtil::EvaluatePoissonLogL(func, data, p, iWeight, extended, nPoints, executionPolicy, nChunks);
0442 }
0443
0444 static double EvalChi2Effective(const IModelFunctionTempl<double> &func, const BinData & data, const double * p, unsigned int &nPoints)
0445 {
0446 return FitUtil::EvaluateChi2Effective(func, data, p, nPoints);
0447 }
0448 static void EvalChi2Gradient(const IModelFunctionTempl<double> &func, const BinData &data, const double *p,
0449 double *g, unsigned int &nPoints,
0450 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0451 unsigned nChunks = 0)
0452 {
0453 FitUtil::EvaluateChi2Gradient(func, data, p, g, nPoints, executionPolicy, nChunks);
0454 }
0455
0456 static double EvalChi2Residual(const IModelFunctionTempl<double> &func, const BinData & data, const double * p, unsigned int i, double *g, double * h,
0457 bool hasGrad, bool fullHessian)
0458 {
0459 return FitUtil::EvaluateChi2Residual(func, data, p, i, g, h, hasGrad, fullHessian);
0460 }
0461
0462
0463
0464 static double EvalPoissonBinPdf(const IModelFunctionTempl<double> &func, const BinData & data, const double *p, unsigned int i, double *g, double * h, bool hasGrad, bool fullHessian) {
0465 return FitUtil::EvaluatePoissonBinPdf(func, data, p, i, g, h, hasGrad, fullHessian);
0466 }
0467
0468 static double EvalPdf(const IModelFunctionTempl<double> &func, const UnBinData & data, const double *p, unsigned int i, double *g, double * h, bool hasGrad, bool fullHessian) {
0469 return FitUtil::EvaluatePdf(func, data, p, i, g, h, hasGrad, fullHessian);
0470 }
0471
0472 static void
0473 EvalPoissonLogLGradient(const IModelFunctionTempl<double> &func, const BinData &data, const double *p, double *g,
0474 unsigned int &nPoints,
0475 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0476 unsigned nChunks = 0)
0477 {
0478 FitUtil::EvaluatePoissonLogLGradient(func, data, p, g, nPoints, executionPolicy, nChunks);
0479 }
0480
0481 static void EvalLogLGradient(const IModelFunctionTempl<double> &func, const UnBinData &data, const double *p,
0482 double *g, unsigned int &nPoints,
0483 ::ROOT::EExecutionPolicy executionPolicy = ::ROOT::EExecutionPolicy::kSequential,
0484 unsigned nChunks = 0)
0485 {
0486 FitUtil::EvaluateLogLGradient(func, data, p, g, nPoints, executionPolicy, nChunks);
0487 }
0488 };
0489
0490 }
0491
0492 }
0493
0494 }
0495
0496 #endif