13 #ifndef ROOT_Fit_FitUtil
14 #define ROOT_Fit_FitUtil
20 #include "ROOT/TThreadExecutor.hxx"
27 #include "Fit/FitExecutionPolicy.h"
29 #include "Math/Integrator.h"
30 #include "Math/IntegratorMultiDim.h"
36 #define USE_PARAMCACHE
43 vecCore::Mask<T> Int2Mask(
unsigned i)
46 for (
unsigned j = 0; j < vecCore::VectorSize<T>(); j++)
47 vecCore::Set<T>(x, j, j);
48 return vecCore::Mask<T>(x < T(i));
128 template <
class ParamFunc = ROOT::Math::IParamMultiFunctionTempl<
double>>
156 fIg1Dim =
new ROOT::Math::IntegratorOneDim();
159 }
else if (
fDim > 1) {
163 fIgNDim =
new ROOT::Math::IntegratorMultiDim();
189 double F1(
double x)
const
197 double Integral(
const double *x1,
const double *x2)
207 double dV = *x2 - *x1;
208 return fIg1Dim->Integral(*x1, *x2) / dV;
211 for (
unsigned int i = 0; i <
fDim; ++i)
212 dV *= (x2[i] - x1[i]);
213 return fIgNDim->Integral(x1, x2) / dV;
223 inline double ExecFunc(T *f,
const double *x,
const double *p)
const
228 #ifdef R__HAS_VECCORE
233 vecCore::Load<ROOT::Double_v>(xx, x);
234 const double *p0 = p;
235 auto res = (*f)(&xx, (
const double *)p0);
236 return vecCore::Get<ROOT::Double_v>(res, 0);
238 std::vector<ROOT::Double_v> xx(
fDim);
239 for (
unsigned int i = 0; i <
fDim; ++i) {
240 vecCore::Load<ROOT::Double_v>(xx[i], x + i);
242 auto res = (*f)(xx.data(), p);
243 return vecCore::Get<ROOT::Double_v>(res, 0);
270 ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0);
284 unsigned int &nPoints,
285 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
286 unsigned nChunks = 0);
293 unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0);
300 unsigned int &nPoints,
301 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
302 unsigned nChunks = 0);
316 bool extended,
unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy,
317 unsigned nChunks = 0);
324 unsigned int &nPoints,
325 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
326 unsigned nChunks = 0);
348 #ifdef R__HAS_VECCORE
349 template <
class NotCompileIfScalarBackend = std::enable_if<!(std::is_same<
double, ROOT::Double_v>::value)>>
354 const auto x = vecCore::FromPtr<ROOT::Double_v>(data.GetCoordComponent(i, 0));
355 auto fval = func(&x, p);
357 return vecCore::Get<ROOT::Double_v>(logPdf, 0);
373 #ifdef R__HAS_VECCORE
375 unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0)
384 unsigned int n = data.Size();
388 #ifdef USE_PARAMCACHE
398 Error(
"FitUtil::EvaluateChi2",
"The vectorized implementation doesn't support Integrals, BinVolume or ExpErrors\n. Aborting operation.");
402 double maxResValue = std::numeric_limits<double>::max() / n;
403 std::vector<double> ones{1, 1, 1, 1};
404 auto vecSize = vecCore::VectorSize<T>();
406 auto mapFunction = [&](
unsigned int i) {
408 T x1, y, invErrorVec;
409 vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
410 vecCore::Load<T>(y, data.
ValuePtr(i * vecSize));
411 const auto invError = data.
ErrorPtr(i * vecSize);
412 auto invErrorptr = (invError !=
nullptr) ? invError : &ones.front();
413 vecCore::Load<T>(invErrorVec, invErrorptr);
417 if(data.NDim() > 1) {
418 xc.resize(data.NDim());
420 for (
unsigned int j = 1; j < data.NDim(); ++j)
421 vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
429 #ifdef USE_PARAMCACHE
436 T tmp = (y - fval) * invErrorVec;
441 auto m = vecCore::Mask_v<T>(chi2 > maxResValue);
443 vecCore::MaskedAssign<T>(chi2, m, maxResValue);
449 auto redFunction = [](
const std::vector<T> &objs) {
450 return std::accumulate(objs.begin(), objs.end(), T{});
456 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
457 Warning(
"FitUtil::EvaluateChi2",
"Multithread execution policy requires IMT, which is disabled. Changing "
458 "to ROOT::Fit::ExecutionPolicy::kSerial.");
459 executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
464 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
465 for (
unsigned int i = 0; i < (data.Size() / vecSize); i++) {
466 res += mapFunction(i);
470 }
else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
472 ROOT::TThreadExecutor pool;
473 res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size() / vecSize), redFunction, chunks);
479 Error(
"FitUtil::EvaluateChi2",
"Execution policy unknown. Avalaible choices:\n ROOT::Fit::ExecutionPolicy::kSerial (default)\n ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
484 if (data.Size() % vecSize != 0)
485 vecCore::MaskedAssign(res, vecCore::Int2Mask<T>(data.Size() % vecSize),
486 res + mapFunction(data.Size() / vecSize));
488 return vecCore::ReduceAdd(res);
492 int iWeight,
bool extended,
unsigned int &nPoints,
493 ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0)
496 unsigned int n = data.Size();
499 bool normalizeFunc =
false;
502 #ifdef USE_PARAMCACHE
509 if (!normalizeFunc) {
510 if (data.NDim() == 1) {
512 vecCore::Load<T>(x, data.GetCoordComponent(0, 0));
516 std::vector<T> x(data.NDim());
517 for (
unsigned int j = 0; j < data.NDim(); ++j)
518 vecCore::Load<T>(x[j], data.GetCoordComponent(0, j));
528 std::vector<double> xmin(data.NDim());
529 std::vector<double> xmax(data.NDim());
532 if (data.Range().Size() > 0) {
534 for (
unsigned int ir = 0; ir < data.Range().Size(); ++ir) {
535 data.Range().GetRange(&xmin[0], &xmax[0], ir);
536 norm += igEval.
Integral(xmin.data(), xmax.data());
540 data.Range().GetRange(&xmin[0], &xmax[0]);
543 vecCore::Load<T>(xmin_v, xmin.data());
544 vecCore::Load<T>(xmax_v, xmax.data());
545 if (vecCore::ReduceAdd(func(&xmin_v, p)) != 0 || vecCore::ReduceAdd(func(&xmax_v, p)) != 0) {
546 MATH_ERROR_MSG(
"FitUtil::EvaluateLogLikelihood",
"A range has not been set and the function is not zero at +/- inf");
549 norm = igEval.
Integral(&xmin[0], &xmax[0]);
555 auto vecSize = vecCore::VectorSize<T>();
556 unsigned int numVectors = n / vecSize;
558 auto mapFunction = [ &, p](
const unsigned i) {
566 vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
567 const T *x =
nullptr;
568 unsigned int ndim = data.NDim();
573 for (
unsigned int j = 1; j < ndim; ++j)
574 vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
580 #ifdef USE_PARAMCACHE
587 if (i < 5 || (i > numVectors-5) ) {
588 if (ndim == 1) std::cout << i <<
" x " << x[0] <<
" fval = " << fval;
589 else std::cout << i <<
" x " << x[0] <<
" y " << x[1] <<
" fval = " << fval;
593 if (normalizeFunc) fval = fval * (1 / norm);
599 if (data.WeightsPtr(i) ==
nullptr)
602 vecCore::Load<T>(weight, data.WeightsPtr(i*vecSize));
609 W2 = weight * weight;
614 if (i < 5 || (i > numVectors-5) ) {
615 std::cout <<
" " << fval <<
" logfval " << logval << std::endl;
624 auto redFunction = [](
const std::vector<LikelihoodAux<T>> &objs) {
634 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
635 Warning(
"FitUtil::EvaluateLogL",
"Multithread execution policy requires IMT, which is disabled. Changing "
636 "to ROOT::Fit::ExecutionPolicy::kSerial.");
637 executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
644 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
645 for (
unsigned int i = 0; i < numVectors; ++i) {
646 auto resArray = mapFunction(i);
647 logl_v += resArray.logvalue;
648 sumW_v += resArray.weight;
649 sumW2_v += resArray.weight2;
652 }
else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
654 ROOT::TThreadExecutor pool;
655 auto resArray = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size() / vecSize), redFunction, chunks);
656 logl_v = resArray.logvalue;
657 sumW_v = resArray.weight;
658 sumW2_v = resArray.weight2;
664 Error(
"FitUtil::EvaluateLogL",
"Execution policy unknown. Avalaible choices:\n ROOT::Fit::ExecutionPolicy::kSerial (default)\n ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
668 unsigned int remainingPoints = n % vecSize;
669 if (remainingPoints > 0) {
670 auto remainingPointsContribution = mapFunction(numVectors);
672 auto remainingMask = vecCore::Int2Mask<T>(remainingPoints);
673 vecCore::MaskedAssign(logl_v, remainingMask, logl_v + remainingPointsContribution.logvalue);
674 vecCore::MaskedAssign(sumW_v, remainingMask, sumW_v + remainingPointsContribution.weight);
675 vecCore::MaskedAssign(sumW2_v, remainingMask, sumW2_v + remainingPointsContribution.weight2);
684 for (
unsigned vIt = 0; vIt < vecSize; vIt++) {
687 sumW2 += sumW2_v[vIt];
692 double extendedTerm = 0;
696 if (!normalizeFunc) {
698 std::vector<double> xmin(data.NDim());
699 std::vector<double> xmax(data.NDim());
702 if (data.Range().Size() > 0) {
704 for (
unsigned int ir = 0; ir < data.Range().Size(); ++ir) {
705 data.Range().GetRange(&xmin[0], &xmax[0], ir);
706 nuTot += igEval.
Integral(xmin.data(), xmax.data());
710 data.Range().GetRange(&xmin[0], &xmax[0]);
713 vecCore::Load<T>(xmin_v, xmin.data());
714 vecCore::Load<T>(xmax_v, xmax.data());
715 if (vecCore::ReduceAdd(func(&xmin_v, p)) != 0 || vecCore::ReduceAdd(func(&xmax_v, p)) != 0) {
716 MATH_ERROR_MSG(
"FitUtil::EvaluateLogLikelihood",
"A range has not been set and the function is not zero at +/- inf");
719 nuTot = igEval.
Integral(&xmin[0], &xmax[0]);
725 extendedTerm = - nuTot;
729 extendedTerm = - (sumW2 / sumW) * nuTot;
738 logl += extendedTerm;
742 std::cout <<
"Evaluated log L for parameters (";
743 for (
unsigned int ip = 0; ip < func.
NPar(); ++ip)
744 std::cout <<
" " << p[ip];
745 std::cout <<
") nll = " << -logl << std::endl;
757 int iWeight,
bool extended,
unsigned int,
758 ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0)
775 #ifdef USE_PARAMCACHE
778 auto vecSize = vecCore::VectorSize<T>();
782 Error(
"FitUtil::EvaluateChi2",
783 "The vectorized implementation doesn't support Integrals or BinVolume\n. Aborting operation.");
784 bool useW2 = (iWeight == 2);
786 auto mapFunction = [&](
unsigned int i) {
788 vecCore::Load<T>(y, data.
ValuePtr(i * vecSize));
791 if (data.NDim() > 1) {
792 std::vector<T> x(data.NDim());
793 for (
unsigned int j = 0; j < data.NDim(); ++j)
794 vecCore::Load<T>(x[j], data.GetCoordComponent(i * vecSize, j));
795 #ifdef USE_PARAMCACHE
796 fval = func(x.data());
798 fval = func(x.data(), p);
803 vecCore::Load<T>(x, data.GetCoordComponent(i * vecSize, 0));
804 #ifdef USE_PARAMCACHE
813 vecCore::MaskedAssign<T>(fval, fval < 0.0, 0.0);
823 assert (data.
GetErrorType() != ROOT::Fit::BinData::ErrorType::kNoError);
825 vecCore::Load<T>(error, data.
ErrorPtr(i * vecSize));
827 auto m = vecCore::Mask_v<T>(y != 0.0);
830 nloglike = weight * ( fval - y);
839 if (extended) nloglike = fval - y;
841 vecCore::MaskedAssign<T>(
849 auto redFunction = [](
const std::vector<T> &objs) {
return std::accumulate(objs.begin(), objs.end(), T{}); };
854 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
855 Warning(
"FitUtil::Evaluate<T>::EvalPoissonLogL",
856 "Multithread execution policy requires IMT, which is disabled. Changing "
857 "to ROOT::Fit::ExecutionPolicy::kSerial.");
858 executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
863 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
864 for (
unsigned int i = 0; i < (data.Size() / vecSize); i++) {
865 res += mapFunction(i);
868 }
else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
870 ROOT::TThreadExecutor pool;
871 res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size() / vecSize), redFunction, chunks);
878 "FitUtil::Evaluate<T>::EvalPoissonLogL",
879 "Execution policy unknown. Avalaible choices:\n ROOT::Fit::ExecutionPolicy::kSerial (default)\n ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
883 if (data.Size() % vecSize != 0)
884 vecCore::MaskedAssign(res, vecCore::Int2Mask<T>(data.Size() % vecSize),
885 res + mapFunction(data.Size() / vecSize));
887 return vecCore::ReduceAdd(res);
892 Error(
"FitUtil::Evaluate<T>::EvalChi2Effective",
"The vectorized evaluation of the Chi2 with coordinate errors is still not supported");
899 static vecCore::Mask<T> CheckInfNaNValues(T &rval)
913 unsigned int &nPoints,
914 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
915 unsigned nChunks = 0)
925 "Error on the coordinates are not used in calculating Chi2 gradient");
930 assert(fg !=
nullptr);
936 Error(
"FitUtil::EvaluateChi2Gradient",
"The vectorized implementation doesn't support Integrals,"
937 "BinVolume or ExpErrors\n. Aborting operation.");
939 unsigned int npar = func.
NPar();
940 auto vecSize = vecCore::VectorSize<T>();
941 unsigned initialNPoints = data.Size();
942 unsigned numVectors = initialNPoints / vecSize;
945 std::vector<vecCore::Mask<T>> validPointsMasks(numVectors + 1);
947 auto mapFunction = [&](
const unsigned int i) {
949 std::vector<T> gradFunc(npar);
950 std::vector<T> pointContributionVec(npar);
954 vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
955 vecCore::Load<T>(y, data.
ValuePtr(i * vecSize));
956 const auto invErrorPtr = data.
ErrorPtr(i * vecSize);
958 if (invErrorPtr ==
nullptr)
961 vecCore::Load<T>(invError, invErrorPtr);
967 const T *x =
nullptr;
969 unsigned int ndim = data.NDim();
976 for (
unsigned int j = 1; j < ndim; ++j)
977 vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
993 validPointsMasks[i] = CheckInfNaNValues(fval);
994 if (vecCore::MaskEmpty(validPointsMasks[i])) {
996 return pointContributionVec;
1000 for (
unsigned int ipar = 0; ipar < npar; ++ipar) {
1003 validPointsMasks[i] = CheckInfNaNValues(gradFunc[ipar]);
1005 if (vecCore::MaskEmpty(validPointsMasks[i])) {
1010 vecCore::MaskedAssign(pointContributionVec[ipar], validPointsMasks[i],
1011 -2.0 * (y - fval) * invError * invError * gradFunc[ipar]);
1014 return pointContributionVec;
1018 auto redFunction = [&](
const std::vector<std::vector<T>> &partialResults) {
1019 std::vector<T> result(npar);
1021 for (
auto const &pointContributionVec : partialResults) {
1022 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1023 result[parameterIndex] += pointContributionVec[parameterIndex];
1029 std::vector<T> gVec(npar);
1030 std::vector<double> g(npar);
1037 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1038 Warning(
"FitUtil::EvaluateChi2Gradient",
1039 "Multithread execution policy requires IMT, which is disabled. Changing "
1040 "to ROOT::Fit::ExecutionPolicy::kSerial.");
1041 executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
1045 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
1046 std::vector<std::vector<T>> allGradients(numVectors);
1047 for (
unsigned int i = 0; i < numVectors; ++i) {
1048 allGradients[i] = mapFunction(i);
1051 gVec = redFunction(allGradients);
1054 else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1056 ROOT::TThreadExecutor pool;
1057 gVec = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, numVectors), redFunction, chunks);
1066 "FitUtil::EvaluateChi2Gradient",
1067 "Execution policy unknown. Avalaible choices:\n 0: Serial (default)\n 1: MultiThread (requires IMT)\n");
1071 unsigned int remainingPoints = initialNPoints % vecSize;
1072 if (remainingPoints > 0) {
1073 auto remainingPointsContribution = mapFunction(numVectors);
1075 auto remainingMask = vecCore::Int2Mask<T>(remainingPoints);
1076 for (
unsigned int param = 0; param < npar; param++) {
1077 vecCore::MaskedAssign(gVec[param], remainingMask, gVec[param] + remainingPointsContribution[param]);
1081 for (
unsigned int param = 0; param < npar; param++) {
1082 grad[param] = vecCore::ReduceAdd(gVec[param]);
1086 nPoints = initialNPoints;
1088 if (std::any_of(validPointsMasks.begin(), validPointsMasks.end(),
1089 [](vecCore::Mask<T> validPoints) { return !vecCore::MaskFull(validPoints); })) {
1090 unsigned nRejected = 0;
1092 for (
const auto &mask : validPointsMasks) {
1093 for (
unsigned int i = 0; i < vecSize; i++) {
1094 nRejected += !vecCore::Get(mask, i);
1098 assert(nRejected <= initialNPoints);
1099 nPoints = initialNPoints - nRejected;
1101 if (nPoints < npar) {
1103 "Too many points rejected for overflow in gradient calculation");
1110 Error(
"FitUtil::Evaluate<T>::EvalChi2Residual",
"The vectorized evaluation of the Chi2 with the ith residual is still not supported");
1117 Error(
"FitUtil::Evaluate<T>::EvaluatePoissonBinPdf",
"The vectorized evaluation of the BinnedLikelihood fit evaluated point by point is still not supported");
1124 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
1125 unsigned nChunks = 0)
1130 assert(fg !=
nullptr);
1139 Error(
"FitUtil::EvaluatePoissonLogLGradient",
"The vectorized implementation doesn't support Integrals,"
1140 "BinVolume or ExpErrors\n. Aborting operation.");
1142 unsigned int npar = func.
NPar();
1143 auto vecSize = vecCore::VectorSize<T>();
1144 unsigned initialNPoints = data.Size();
1145 unsigned numVectors = initialNPoints / vecSize;
1147 auto mapFunction = [&](
const unsigned int i) {
1149 std::vector<T> gradFunc(npar);
1150 std::vector<T> pointContributionVec(npar);
1154 vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
1155 vecCore::Load<T>(y, data.
ValuePtr(i * vecSize));
1159 const T *x =
nullptr;
1161 unsigned ndim = data.NDim();
1166 for (
unsigned int j = 1; j < ndim; ++j)
1167 vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
1177 for (
unsigned int ipar = 0; ipar < npar; ++ipar) {
1178 vecCore::Mask<T> positiveValuesMask = fval > 0;
1181 vecCore::MaskedAssign(pointContributionVec[ipar], positiveValuesMask, gradFunc[ipar] * (1. - y / fval));
1183 vecCore::Mask<T> validNegativeValuesMask = !positiveValuesMask && gradFunc[ipar] != 0;
1185 if (!vecCore::MaskEmpty(validNegativeValuesMask)) {
1188 T gg = kdmax1 * gradFunc[ipar];
1193 #ifdef DEBUG_FITUTIL
1195 R__LOCKGUARD(gROOTMutex);
1196 if (i < 5 || (i > data.Size()-5) ) {
1197 if (data.NDim() > 1) std::cout << i <<
" x " << x[0] <<
" y " << x[1];
1198 else std::cout << i <<
" x " << x[0];
1199 std::cout <<
" func " << fval <<
" gradient ";
1200 for (
unsigned int ii = 0; ii < npar; ++ii) std::cout <<
" " << pointContributionVec[ii];
1206 return pointContributionVec;
1210 auto redFunction = [&](
const std::vector<std::vector<T>> &partialResults) {
1211 std::vector<T> result(npar);
1213 for (
auto const &pointContributionVec : partialResults) {
1214 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1215 result[parameterIndex] += pointContributionVec[parameterIndex];
1221 std::vector<T> gVec(npar);
1228 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1229 Warning(
"FitUtil::EvaluatePoissonLogLGradient",
1230 "Multithread execution policy requires IMT, which is disabled. Changing "
1231 "to ROOT::Fit::ExecutionPolicy::kSerial.");
1232 executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
1236 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
1237 std::vector<std::vector<T>> allGradients(numVectors);
1238 for (
unsigned int i = 0; i < numVectors; ++i) {
1239 allGradients[i] = mapFunction(i);
1242 gVec = redFunction(allGradients);
1245 else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1247 ROOT::TThreadExecutor pool;
1248 gVec = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, numVectors), redFunction, chunks);
1256 Error(
"FitUtil::EvaluatePoissonLogLGradient",
"Execution policy unknown. Avalaible choices:\n "
1257 "ROOT::Fit::ExecutionPolicy::kSerial (default)\n "
1258 "ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
1263 unsigned int remainingPoints = initialNPoints % vecSize;
1264 if (remainingPoints > 0) {
1265 auto remainingPointsContribution = mapFunction(numVectors);
1267 auto remainingMask = vecCore::Int2Mask<T>(remainingPoints);
1268 for (
unsigned int param = 0; param < npar; param++) {
1269 vecCore::MaskedAssign(gVec[param], remainingMask, gVec[param] + remainingPointsContribution[param]);
1273 for (
unsigned int param = 0; param < npar; param++) {
1274 grad[param] = vecCore::ReduceAdd(gVec[param]);
1277 #ifdef DEBUG_FITUTIL
1278 std::cout <<
"***** Final gradient : ";
1279 for (
unsigned int ii = 0; ii< npar; ++ii) std::cout << grad[ii] <<
" ";
1286 double *grad,
unsigned int &,
1287 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
1288 unsigned nChunks = 0)
1293 assert(fg !=
nullptr);
1298 unsigned int npar = func.
NPar();
1299 auto vecSize = vecCore::VectorSize<T>();
1300 unsigned initialNPoints = data.Size();
1301 unsigned numVectors = initialNPoints / vecSize;
1303 #ifdef DEBUG_FITUTIL
1304 std::cout <<
"\n===> Evaluate Gradient for parameters ";
1305 for (
unsigned int ip = 0; ip < npar; ++ip)
1306 std::cout <<
" " << p[ip];
1315 auto mapFunction = [&](
const unsigned int i) {
1316 std::vector<T> gradFunc(npar);
1317 std::vector<T> pointContributionVec(npar);
1320 vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
1322 const T *x =
nullptr;
1324 unsigned int ndim = data.NDim();
1325 std::vector<T> xc(ndim);
1329 for (
unsigned int j = 1; j < ndim; ++j)
1330 vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
1337 T fval = func(x, p);
1340 #ifdef DEBUG_FITUTIL
1341 if (i < 5 || (i > numVectors-5) ) {
1342 if (ndim > 1) std::cout << i <<
" x " << x[0] <<
" y " << x[1] <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1343 else std::cout << i <<
" x " << x[0] <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1347 vecCore::Mask<T> positiveValues = fval > 0;
1349 for (
unsigned int kpar = 0; kpar < npar; ++kpar) {
1350 if (!vecCore::MaskEmpty(positiveValues))
1351 vecCore::MaskedAssign<T>(pointContributionVec[kpar], positiveValues, -1. / fval * gradFunc[kpar]);
1353 vecCore::Mask<T> nonZeroGradientValues = !positiveValues && gradFunc[kpar] != 0;
1354 if (!vecCore::MaskEmpty(nonZeroGradientValues)) {
1355 T gg = kdmax1 * gradFunc[kpar];
1356 pointContributionVec[kpar] =
1363 return pointContributionVec;
1367 auto redFunction = [&](
const std::vector<std::vector<T>> &pointContributions) {
1368 std::vector<T> result(npar);
1370 for (
auto const &pointContributionVec : pointContributions) {
1371 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1372 result[parameterIndex] += pointContributionVec[parameterIndex];
1378 std::vector<T> gVec(npar);
1379 std::vector<double> g(npar);
1386 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1387 Warning(
"FitUtil::EvaluateLogLGradient",
1388 "Multithread execution policy requires IMT, which is disabled. Changing "
1389 "to ROOT::Fit::ExecutionPolicy::kSerial.");
1390 executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
1394 if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
1395 std::vector<std::vector<T>> allGradients(numVectors);
1396 for (
unsigned int i = 0; i < numVectors; ++i) {
1397 allGradients[i] = mapFunction(i);
1399 gVec = redFunction(allGradients);
1402 else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1404 ROOT::TThreadExecutor pool;
1405 gVec = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, numVectors), redFunction, chunks);
1413 Error(
"FitUtil::EvaluateLogLGradient",
"Execution policy unknown. Avalaible choices:\n "
1414 "ROOT::Fit::ExecutionPolicy::kSerial (default)\n "
1415 "ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
1419 unsigned int remainingPoints = initialNPoints % vecSize;
1420 if (remainingPoints > 0) {
1421 auto remainingPointsContribution = mapFunction(numVectors);
1423 auto remainingMask = vecCore::Int2Mask<T>(initialNPoints % vecSize);
1424 for (
unsigned int param = 0; param < npar; param++) {
1425 vecCore::MaskedAssign(gVec[param], remainingMask, gVec[param] + remainingPointsContribution[param]);
1429 for (
unsigned int param = 0; param < npar; param++) {
1430 grad[param] = vecCore::ReduceAdd(gVec[param]);
1433 #ifdef DEBUG_FITUTIL
1434 std::cout <<
"Final gradient ";
1435 for (
unsigned int param = 0; param < npar; param++) {
1436 std::cout <<
" " << grad[param];
1448 ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0)
1462 int iWeight,
bool extended,
unsigned int &nPoints,
1463 ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0)
1469 int iWeight,
bool extended,
unsigned int &nPoints,
1470 ROOT::Fit::ExecutionPolicy executionPolicy,
unsigned nChunks = 0)
1480 double *g,
unsigned int &nPoints,
1481 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
1482 unsigned nChunks = 0)
1499 unsigned int &nPoints,
1500 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
1501 unsigned nChunks = 0)
1507 double *g,
unsigned int &nPoints,
1508 ROOT::Fit::ExecutionPolicy executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial,
1509 unsigned nChunks = 0)
1521 #if defined (R__HAS_VECCORE) && defined(R__HAS_VC)
#define MATH_ERROR_MSG(loc, str)
void Warning(Ts &&... args)
void Error(Ts &&... args)
double SumOfContent() const
const double * ErrorPtr(unsigned int ipoint) const
const double * ValuePtr(unsigned int ipoint) const
ErrorType GetErrorType() const
bool HaveCoordErrors() const
double SumOfError2() const
double Integral(const double *x1, const double *x2)
void SetFunction(const ParamFunc &func, const double *p=0)
IntegralEvaluator & operator=(const IntegralEvaluator &rhs)
ROOT::Math::IGenFunction * fFunc1Dim
ROOT::Math::IntegratorMultiDim * fIgNDim
IntegralEvaluator(const IntegralEvaluator &rhs)
IntegralEvaluator(const ParamFunc &func, const double *p, bool useIntegral=true)
double F1(double x) const
ROOT::Math::IntegratorOneDim * fIg1Dim
double FN(const double *x) const
ROOT::Math::IMultiGenFunction * fFuncNDim
void SetParameters(const double *p)
double ExecFunc(T *f, const double *x, const double *p) const
double operator()(const double *x1, const double *x2)
LikelihoodAux & operator+=(const LikelihoodAux &l)
LikelihoodAux(double logv=0.0, double w=0.0, double w2=0.0)
LikelihoodAux operator+(const LikelihoodAux &l) const
LikelihoodAux operator+(const LikelihoodAux &l) const
LikelihoodAux(T logv={}, T w={}, T w2={})
LikelihoodAux & operator+=(const LikelihoodAux &l)
virtual void SetParameters(const double *p)=0
virtual unsigned int NPar() const =0
virtual void ParameterGradient(const T *x, const double *p, T *grad) const
ROOT::Math::IParamMultiGradFunction IGradModelFunction
double EvaluateChi2(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
ROOT::Math::IParamMultiFunction IModelFunction
double EvaluateChi2Residual(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint, double *g=0)
void EvaluateLogLGradient(const IModelFunction &func, const UnBinData &data, const double *x, double *grad, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
double EvaluatePoissonLogL(const IModelFunction &func, const BinData &data, const double *x, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
double EvaluateChi2Effective(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints)
double EvaluatePoissonBinPdf(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint, double *g=0)
unsigned setAutomaticChunking(unsigned nEvents)
double EvaluateLogL(const IModelFunction &func, const UnBinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
void EvaluatePoissonLogLGradient(const IModelFunction &func, const BinData &data, const double *x, double *grad, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
double EvaluatePdf(const IModelFunction &func, const UnBinData &data, const double *x, unsigned int ipoint, double *g=0)
void EvaluateChi2Gradient(const IModelFunction &func, const BinData &data, const double *x, double *grad, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
T EvalLog(T x)
safe evaluation of log(x) with a protections against negative or zero argument to the log smooth line...
Short_t Max(Short_t a, Short_t b)
Double_t Sqrt(Double_t x)
Short_t Min(Short_t a, Short_t b)
static double EvalLogL(const IModelFunctionTempl< double > &func, const UnBinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
static double EvalPoissonBinPdf(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, unsigned int i, double *g)
evaluate the pdf (Poisson) contribution to the logl (return actually log of pdf) and its gradient
static void EvalLogLGradient(const IModelFunctionTempl< double > &func, const UnBinData &data, const double *p, double *g, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
static double EvalPoissonLogL(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
static double EvalChi2Effective(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, unsigned int &nPoints)
static void EvalChi2Gradient(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, double *g, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
static double EvalChi2(const IModelFunction &func, const BinData &data, const double *p, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
static double EvalChi2Residual(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, unsigned int i, double *g=0)
static void EvalPoissonLogLGradient(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, double *g, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)