53 template<
class GradFunc = IGradModelFunction>
99 deriv = 0.5 * ( f2 -
f1 )/
h;
102 deriv = (
f1 - f0 )/
h;
127 for (
unsigned int k = 0; k <
fN; ++k) {
133 void Gradient(
const double *
x,
const double *
p,
double f0,
double *
g) {
136 for (
unsigned int k = 0; k <
fN; ++k) {
146 g[k] = 0.5 * ( f2 -
f1 )/
h;
149 g[k] = (
f1 - f0 )/
h;
162 mutable std::vector<double>
fVec;
169 if (rval > - std::numeric_limits<double>::max() && rval < std::numeric_limits<double>::max() )
173 return -std::numeric_limits<double>::max();
176 return + std::numeric_limits<double>::max();
183 if (rval > - std::numeric_limits<double>::max() && rval < std::numeric_limits<double>::max() )
187 rval = -std::numeric_limits<double>::max();
192 rval = + std::numeric_limits<double>::max();
201 template <
class GFunc>
203 const double *
x1,
const double *
x2,
const double *
p,
double *
g) {
209 unsigned int npar = gfunc.NPar();
210 for (
unsigned int k = 0; k < npar; ++k ) {
212 g[k] = igDerEval(
x1,
x2 );
234 unsigned int n =
data.Size();
246 bool useBinIntegral = fitOpt.
fIntegral &&
data.HasBinEdges();
251 std::cout <<
"\n\nFit data size = " <<
n << std::endl;
252 std::cout <<
"evaluate chi2 using function " << &func <<
" " <<
p << std::endl;
253 std::cout <<
"use empty bins " << fitOpt.
fUseEmpty << std::endl;
254 std::cout <<
"use integral " << useBinIntegral << std::endl;
255 std::cout <<
"use binvolume " << useBinVolume << std::endl;
256 std::cout <<
"use Exp Errors " << useExpErrors << std::endl;
257 std::cout <<
"use all error=1 " << fitOpt.
fErrors1 << std::endl;
258 if (isWeighted) std::cout <<
"Weighted data set - sumw = " <<
data.SumOfContent() <<
" sumw2 = " <<
data.SumOfError2() << std::endl;
271 double maxResValue = std::numeric_limits<double>::max() /
n;
272 double wrefVolume = 1.0;
279 auto mapFunction = [&](
const unsigned i){
284 const auto x1 =
data.GetCoordComponent(i, 0);
285 const auto y =
data.Value(i);
286 auto invError =
data.InvError(i);
290 const double *
x =
nullptr;
291 std::vector<double> xc;
292 double binVolume = 1.0;
294 unsigned int ndim =
data.NDim();
295 xc.resize(
data.NDim());
296 for (
unsigned int j = 0; j < ndim; ++j) {
297 double xx = *
data.GetCoordComponent(i, j);
298 double x2 =
data.GetBinUpEdgeComponent(i, j);
299 binVolume *= std::abs(
x2 - xx);
300 xc[j] = (useBinIntegral) ? xx : 0.5*(
x2 + xx);
304 binVolume *= wrefVolume;
305 }
else if(
data.NDim() > 1) {
308 xc.resize(
data.NDim());
310 for (
unsigned int j = 1; j <
data.NDim(); ++j)
311 xc[j] = *
data.GetCoordComponent(i, j);
319 if (!useBinIntegral) {
323 fval = func (
x,
p );
329 std::vector<double>
x2(
data.NDim());
330 data.GetBinUpEdgeCoordinates(i,
x2.data());
331 fval = igEval(
x,
x2.data());
335 if (useBinVolume) fval *= binVolume;
339 double invWeight = 1.0;
345 invWeight =
y * invError * invError;
349 invWeight =
data.SumOfContent()/
data.SumOfError2();
352 double invError2 = (fval > 0) ? invWeight / fval : 0.0;
353 invError = std::sqrt(invError2);
358 std::cout <<
x[0] <<
" " <<
y <<
" " << 1./invError <<
" params : ";
359 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
360 std::cout <<
p[ipar] <<
"\t";
361 std::cout <<
"\tfval = " << fval <<
" bin volume " << binVolume <<
" ref " << wrefVolume << std::endl;
366 double tmp = (
y -fval )* invError;
367 double resval = tmp * tmp;
371 if ( resval < maxResValue )
382 auto redFunction = [](
const std::vector<double> & objs){
383 return std::accumulate(objs.begin(), objs.end(),
double{});
390 Warning(
"FitUtil::EvaluateChi2",
"Multithread execution policy requires IMT, which is disabled. Changing "
391 "to ROOT::EExecutionPolicy::kSequential.");
398 for (
unsigned int i=0; i<
n; ++i) {
399 res += mapFunction(i);
411 Error(
"FitUtil::EvaluateChi2",
"Execution policy unknown. Available choices:\n ROOT::EExecutionPolicy::kSequential (default)\n ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
430 unsigned int n =
data.Size();
433 std::cout <<
"\n\nFit data size = " <<
n << std::endl;
434 std::cout <<
"evaluate effective chi2 using function " << &func <<
" " <<
p << std::endl;
437 assert(
data.HaveCoordErrors() ||
data.HaveAsymErrors());
445 unsigned int ndim = func.
NDim();
450 double maxResValue = std::numeric_limits<double>::max() /
n;
454 for (
unsigned int i = 0; i <
n; ++ i) {
458 const double *
x =
data.GetPoint(i,
y);
460 double fval = func(
x,
p );
462 double delta_y_func =
y - fval;
466 const double *
ex =
nullptr;
467 if (!
data.HaveAsymErrors() )
470 double eylow, eyhigh = 0;
471 ex =
data.GetPointError(i, eylow, eyhigh);
472 if ( delta_y_func < 0)
480 while ( j < ndim &&
ex[j] == 0.) { j++; }
487 double kPrecision = 1.E-8;
488 for (
unsigned int icoord = 0; icoord < ndim; ++icoord) {
490 if (
ex[icoord] > 0) {
494 double x0=
x[icoord];
495 double h = std::max( kEps* std::abs(
ex[icoord]), 8.0*kPrecision*(std::abs(x0) + kPrecision) );
497 double edx =
ex[icoord] * deriv;
500 std::cout <<
"error for coord " << icoord <<
" = " <<
ex[icoord] <<
" deriv " << deriv << std::endl;
505 double w2 = (e2 > 0) ? 1.0/e2 : 0;
506 double resval = w2 * (
y - fval ) * (
y - fval);
509 std::cout <<
x[0] <<
" " <<
y <<
" ex " <<
ex[0] <<
" ey " <<
ey <<
" params : ";
510 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
511 std::cout <<
p[ipar] <<
"\t";
512 std::cout <<
"\tfval = " << fval <<
"\tresval = " << resval << std::endl;
517 if ( resval < maxResValue )
530 std::cout <<
"chi2 = " << chi2 <<
" n = " << nPoints << std::endl;
547 MATH_ERROR_MSG(
"FitUtil::EvaluateChi2Residual",
"Error on the coordinates are not used in calculating Chi2 residual");
551 double y, invError = 0;
554 bool useBinIntegral = fitOpt.
fIntegral &&
data.HasBinEdges();
559 const double *
x1 =
data.GetPoint(i,
y, invError);
561 unsigned int ndim =
data.NDim();
562 double binVolume = 1.0;
563 const double *
x2 =
nullptr;
564 if (useBinVolume || useBinIntegral)
x2 =
data.BinUpEdge(i);
566 std::vector<double> xc;
569 if (!useBinIntegral) {
571 for (
unsigned int j = 0; j < ndim; ++j) {
572 binVolume *= std::abs(
x2[j]-
x1[j] );
573 xc[j] = 0.5*(
x2[j]+
x1[j]);
577 if (useNormBinVolume) binVolume /=
data.RefVolume();
580 const double *
x = (useBinVolume) ? xc.data() :
x1;
585 double fval0 = (useBinIntegral) ? igEval(
x1,
x2) : func (
x,
p );
589 if (useBinVolume) fval = fval0*binVolume;
595 double invWeight = 1.0;
597 invWeight =
y * invError * invError;
598 if (
y == 0) invWeight = (
data.SumOfError2() > 0) ?
data.SumOfContent()/
data.SumOfError2() : 1.0;
601 double invError2 = (fval > 0) ? invWeight / fval : 0.0;
602 invError = std::sqrt(invError2);
606 double resval = (
y -fval ) * invError;
614 unsigned int npar = func.
NPar();
620 if (!
h ) useFullHessian =
false;
622 if (useFullHessian && (!gfunc || useBinIntegral || (gfunc && !gfunc->
HasParameterHessian())))
623 return std::numeric_limits<double>::quiet_NaN();
627 if (!useBinIntegral ) {
629 if (useFullHessian) {
640 if (!useBinIntegral ) {
642 gc.ParameterGradient(
x,
p, fval0,
g);
649 for (
unsigned int k = 0; k < npar; ++k) {
651 if (useBinVolume)
g[k] *= binVolume;
653 for (
unsigned int l = 0;
l <= k;
l++) {
654 unsigned int idx =
l + k * (k + 1) / 2;
655 if (useFullHessian) {
656 h[idx] *= 2.* resval * (-invError);
657 if (useBinVolume)
h[idx] *= binVolume;
663 h[idx] += 2. *
g[k]*
g[
l];
683 if (
data.HaveCoordErrors()) {
685 "Error on the coordinates are not used in calculating Chi2 gradient");
689 const IGradModelFunction *fg =
dynamic_cast<const IGradModelFunction *
>(&
f);
690 assert(fg !=
nullptr);
692 const IGradModelFunction &func = *fg;
695 std::cout <<
"\n\nFit data size = " << nPoints << std::endl;
696 std::cout <<
"evaluate chi2 using function gradient " << &func <<
" " <<
p << std::endl;
699 const DataOptions &fitOpt =
data.Opt();
700 bool useBinIntegral = fitOpt.fIntegral &&
data.HasBinEdges();
701 bool useBinVolume = (fitOpt.fBinVolume &&
data.HasBinEdges());
703 double wrefVolume = 1.0;
705 if (fitOpt.fNormBinVolume) wrefVolume /=
data.RefVolume();
713 IntegralEvaluator<> igEval(func,
p, useBinIntegral,igType);
715 unsigned int npar = func.NPar();
716 unsigned initialNPoints =
data.Size();
718 std::vector<bool> isPointRejected(initialNPoints);
720 auto mapFunction = [&](
const unsigned int i) {
722 std::vector<double> gradFunc(npar);
723 std::vector<double> pointContribution(npar);
725 const auto x1 =
data.GetCoordComponent(i, 0);
726 const auto y =
data.Value(i);
727 auto invError =
data.Error(i);
729 invError = (invError != 0.0) ? 1.0 / invError : 1;
733 const double *
x =
nullptr;
734 std::vector<double> xc;
736 unsigned int ndim =
data.NDim();
737 double binVolume = 1;
740 for (
unsigned int j = 0; j < ndim; ++j) {
741 double x1_j = *
data.GetCoordComponent(i, j);
742 double x2_j =
data.GetBinUpEdgeComponent(i, j);
743 binVolume *= std::abs(x2_j - x1_j);
744 xc[j] = (useBinIntegral) ? x1_j : 0.5 * (x2_j + x1_j);
750 binVolume *= wrefVolume;
751 }
else if (ndim > 1) {
754 for (
unsigned int j = 1; j < ndim; ++j)
755 xc[j] = *
data.GetCoordComponent(i, j);
761 if (!useBinIntegral) {
763 func.ParameterGradient(
x,
p, &gradFunc[0]);
765 std::vector<double>
x2(
data.NDim());
766 data.GetBinUpEdgeCoordinates(i,
x2.data());
769 fval = igEval(
x,
x2.data());
776 std::cout <<
x[0] <<
" " <<
y <<
" " << 1. / invError <<
" params : ";
777 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
778 std::cout <<
p[ipar] <<
"\t";
779 std::cout <<
"\tfval = " << fval << std::endl;
782 isPointRejected[i] =
true;
784 return pointContribution;
788 unsigned int ipar = 0;
789 for (; ipar < npar; ++ipar) {
793 gradFunc[ipar] *= binVolume;
797 double dfval = gradFunc[ipar];
803 pointContribution[ipar] = -2.0 * (
y - fval) * invError * invError * gradFunc[ipar];
808 isPointRejected[i] =
true;
811 return pointContribution;
815 auto redFunction = [&](
const std::vector<std::vector<double>> &pointContributions) {
816 std::vector<double>
result(npar);
818 for (
auto const &pointContribution : pointContributions) {
819 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
820 result[parameterIndex] += pointContribution[parameterIndex];
826 std::vector<double>
g(npar);
831 Warning(
"FitUtil::EvaluateChi2Gradient",
"Multithread execution policy requires IMT, which is disabled. Changing "
832 "to ROOT::EExecutionPolicy::kSequential.");
838 std::vector<std::vector<double>> allGradients(initialNPoints);
839 for (
unsigned int i = 0; i < initialNPoints; ++i) {
840 allGradients[i] = mapFunction(i);
842 g = redFunction(allGradients);
856 Error(
"FitUtil::EvaluateChi2Gradient",
857 "Execution policy unknown. Available choices:\n 0: Serial (default)\n 1: MultiThread (requires IMT)\n");
866 nPoints = initialNPoints;
868 if (std::any_of(isPointRejected.begin(), isPointRejected.end(), [](
bool point) { return point; })) {
869 unsigned nRejected = std::accumulate(isPointRejected.begin(), isPointRejected.end(), 0);
870 assert(nRejected <= initialNPoints);
871 nPoints = initialNPoints - nRejected;
875 "Error - too many points rejected for overflow in gradient calculation");
879 std::copy(
g.begin(),
g.end(), grad);
898 const double *
x =
data.Coords(i);
899 double fval = func (
x,
p );
902 if (
g ==
nullptr)
return logPdf;
916 gc.ParameterGradient(
x,
p, fval,
g );
919 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar) {
924 std::cout <<
x[i] <<
"\t";
925 std::cout <<
"\tpar = [ " << func.
NPar() <<
" ] = ";
926 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
927 std::cout <<
p[ipar] <<
"\t";
928 std::cout <<
"\tfval = " << fval;
929 std::cout <<
"\tgrad = [ ";
930 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
931 std::cout <<
g[ipar] <<
"\t";
932 std::cout <<
" ] " << std::endl;
940 int iWeight,
bool extended,
unsigned int &nPoints,
945 unsigned int n =
data.Size();
949 bool normalizeFunc =
false;
953 (
const_cast<IModelFunctionTempl<double> &
>(func)).SetParameters(
p);
956 nPoints =
data.Size();
961 if (!normalizeFunc) {
962 if (
data.NDim() == 1) {
963 const double *
x =
data.GetCoordComponent(0,0);
967 std::vector<double>
x(
data.NDim());
968 for (
unsigned int j = 0; j <
data.NDim(); ++j)
969 x[j] = *
data.GetCoordComponent(0, j);
978 std::vector<double>
xmin(
data.NDim());
979 std::vector<double>
xmax(
data.NDim());
980 IntegralEvaluator<> igEval(func,
p,
true);
982 if (
data.Range().Size() > 0) {
984 for (
unsigned int ir = 0; ir <
data.Range().
Size(); ++ir) {
986 norm += igEval.Integral(
xmin.data(),
xmax.data());
992 if (func(
xmin.data(),
p) != 0 || func(
xmax.data(),
p) != 0) {
994 "A range has not been set and the function is not zero at +/- inf");
997 norm = igEval.Integral(&
xmin[0], &
xmax[0]);
1003 auto mapFunction = [&](
const unsigned i) {
1008 if (
data.NDim() > 1) {
1009 std::vector<double>
x(
data.NDim());
1010 for (
unsigned int j = 0; j <
data.NDim(); ++j)
1011 x[j] = *
data.GetCoordComponent(i, j);
1012#ifdef USE_PARAMCACHE
1013 fval = func(
x.data());
1015 fval = func(
x.data(),
p);
1020 const auto x =
data.GetCoordComponent(i, 0);
1021#ifdef USE_PARAMCACHE
1029 fval = fval * (1 / norm);
1034 double weight =
data.Weight(i);
1041 W2 = weight * weight;
1045 return LikelihoodAux<double>(logval, W, W2);
1056 auto redFunction = [](
const std::vector<LikelihoodAux<double>> & objs){
1057 auto l0 = LikelihoodAux<double>(0.0,0.0,0.0);
1058 for (
auto &
l : objs ) {
1068 Warning(
"FitUtil::EvaluateLogL",
"Multithread execution policy requires IMT, which is disabled. Changing "
1069 "to ROOT::EExecutionPolicy::kSequential.");
1078 for (
unsigned int i=0; i<
n; ++i) {
1079 auto resArray = mapFunction(i);
1080 logl+=resArray.logvalue;
1081 sumW+=resArray.weight;
1082 sumW2+=resArray.weight2;
1089 logl=resArray.logvalue;
1090 sumW=resArray.weight;
1091 sumW2=resArray.weight2;
1097 Error(
"FitUtil::EvaluateLogL",
"Execution policy unknown. Available choices:\n ROOT::EExecutionPolicy::kSequential (default)\n ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
1102 double extendedTerm = 0;
1106 if (!normalizeFunc) {
1107 IntegralEvaluator<> igEval( func,
p,
true);
1108 std::vector<double>
xmin(
data.NDim());
1109 std::vector<double>
xmax(
data.NDim());
1112 if (
data.Range().Size() > 0 ) {
1114 for (
unsigned int ir = 0; ir <
data.Range().
Size(); ++ir) {
1116 nuTot += igEval.Integral(
xmin.data(),
xmax.data());
1122 if (func(
xmin.data(),
p) != 0 || func(
xmax.data(),
p) != 0) {
1123 MATH_ERROR_MSG(
"FitUtil::EvaluateLogLikelihood",
"A range has not been set and the function is not zero at +/- inf");
1126 nuTot = igEval.Integral(&
xmin[0],&
xmax[0]);
1132 extendedTerm = - nuTot;
1136 extendedTerm = - (sumW2 / sumW) * nuTot;
1145 logl += extendedTerm;
1150 std::cout <<
"Evaluated log L for parameters (";
1151 for (
unsigned int ip = 0; ip < func.NPar(); ++ip)
1152 std::cout <<
" " <<
p[ip];
1153 std::cout <<
") fval = " << -logl << std::endl;
1165 assert(fg !=
nullptr);
1169 unsigned int npar = func.
NPar();
1170 unsigned initialNPoints =
data.Size();
1175 std::cout <<
"\n===> Evaluate Gradient for parameters ";
1176 for (
unsigned int ip = 0; ip < npar; ++ip)
1177 std::cout <<
" " <<
p[ip];
1181 const double kdmax1 = std::sqrt(std::numeric_limits<double>::max());
1182 const double kdmax2 = std::numeric_limits<double>::max() / (4 * initialNPoints);
1184 auto mapFunction = [&](
const unsigned int i) {
1185 std::vector<double> gradFunc(npar);
1186 std::vector<double> pointContribution(npar);
1189 const double *
x =
nullptr;
1190 std::vector<double> xc;
1191 if (
data.NDim() > 1) {
1192 xc.resize(
data.NDim() );
1193 for (
unsigned int j = 0; j <
data.NDim(); ++j)
1194 xc[j] = *
data.GetCoordComponent(i, j);
1197 x =
data.GetCoordComponent(i, 0);
1200 double fval = func(
x,
p);
1201 func.ParameterGradient(
x,
p, &gradFunc[0]);
1206 if (i < 5 || (i >
data.Size()-5) ) {
1207 if (
data.NDim() > 1) std::cout << i <<
" x " <<
x[0] <<
" y " <<
x[1] <<
" func " << fval
1208 <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1209 else std::cout << i <<
" x " <<
x[0] <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1214 for (
unsigned int kpar = 0; kpar < npar; ++kpar) {
1216 pointContribution[kpar] = -1. / fval * gradFunc[kpar];
1217 else if (gradFunc[kpar] != 0) {
1218 double gg = kdmax1 * gradFunc[kpar];
1220 gg = std::min(gg, kdmax2);
1222 gg = std::max(gg, -kdmax2);
1223 pointContribution[kpar] = -gg;
1228 return pointContribution;
1232 auto redFunction = [&](
const std::vector<std::vector<double>> &pointContributions) {
1233 std::vector<double>
result(npar);
1235 for (
auto const &pointContribution : pointContributions) {
1236 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1237 result[parameterIndex] += pointContribution[parameterIndex];
1243 std::vector<double>
g(npar);
1248 Warning(
"FitUtil::EvaluateLogLGradient",
"Multithread execution policy requires IMT, which is disabled. Changing "
1249 "to ROOT::EExecutionPolicy::kSequential.");
1255 std::vector<std::vector<double>> allGradients(initialNPoints);
1256 for (
unsigned int i = 0; i < initialNPoints; ++i) {
1257 allGradients[i] = mapFunction(i);
1259 g = redFunction(allGradients);
1269 Error(
"FitUtil::EvaluateLogLGradient",
"Execution policy unknown. Available choices:\n "
1270 "ROOT::EExecutionPolicy::kSequential (default)\n "
1271 "ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
1280 std::copy(
g.begin(),
g.end(), grad);
1281 nPoints =
data.Size();
1284 std::cout <<
"FitUtil.cxx : Final gradient ";
1285 for (
unsigned int param = 0; param < npar; param++) {
1286 std::cout <<
" " << grad[param];
1299 const double *
x1 =
data.GetPoint(i,
y);
1302 bool useBinIntegral = fitOpt.
fIntegral &&
data.HasBinEdges();
1306 const double *
x2 =
nullptr;
1308 double binVolume = 1;
1309 std::vector<double> xc;
1311 unsigned int ndim =
data.NDim();
1313 for (
unsigned int j = 0; j < ndim; ++j) {
1314 double x2j =
data.GetBinUpEdgeComponent(i, j);
1315 binVolume *= std::abs( x2j-
x1[j] );
1316 xc[j] = 0.5*(x2j+
x1[j]);
1319 binVolume /=
data.RefVolume();
1322 const double *
x = (useBinVolume) ? &xc.front() :
x1;
1325 if (!useBinIntegral ) {
1326 fval0 = func (
x,
p );
1330 std::vector<double> vx2(
data.NDim());
1331 data.GetBinUpEdgeCoordinates(i, vx2.data());
1332 fval0 = igEval(
x1, vx2.data() ) ;
1334 double fval = fval0;
1335 if (useBinVolume) fval = fval0*binVolume;
1338 fval = std::max(fval, 0.0);
1339 double nlogPdf = fval;
1345 if (
g ==
nullptr)
return nlogPdf;
1347 unsigned int npar = func.
NPar();
1352 if (useFullHessian && (!gfunc || useBinIntegral || (gfunc && !gfunc->
HasParameterHessian())))
1353 return std::numeric_limits<double>::quiet_NaN();
1358 if (!useBinIntegral ) {
1360 if (useFullHessian &&
h) {
1362 return std::numeric_limits<double>::quiet_NaN();
1364 if (!goodHessFunc) {
1365 return std::numeric_limits<double>::quiet_NaN();
1377 if (!useBinIntegral )
1378 gc.ParameterGradient(
x,
p, fval0,
g);
1385 double coeffGrad = (fval > 0) ? (1. -
y/fval) : ( (
y > 0) ? std::sqrt( std::numeric_limits<double>::max() ) : 1. );
1386 double coeffHess = (fval > 0) ?
y/(fval*fval) : ( (
y > 0) ? std::sqrt( std::numeric_limits<double>::max() ) : 0. );
1388 coeffGrad *= binVolume;
1389 coeffHess *= binVolume*binVolume;
1391 for (
unsigned int k = 0; k < npar; ++k) {
1394 for (
unsigned int l = k;
l < npar; ++
l) {
1395 unsigned int idx = k +
l * (
l + 1) / 2;
1396 if (useFullHessian) {
1397 h[idx] *= coeffGrad;
1403 h[idx] += coeffHess *
g[k]*
g[
l];
1414 std::cout <<
"x = " <<
x[0] <<
" y " <<
y <<
" fval " << fval <<
" logPdf = " << nlogPdf <<
" gradient : ";
1415 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
1416 std::cout <<
g[ipar] <<
"\t";
1418 std::cout <<
"\thessian : ";
1419 for (
unsigned int ipar = 0; ipar < npar; ++ipar) {
1421 for (
unsigned int jpar = 0; jpar <= ipar; ++jpar) {
1422 std::cout <<
h[ipar + jpar * (jpar + 1) / 2] <<
"\t";
1427 std::cout << std::endl;
1455 unsigned int n =
data.Size();
1457#ifdef USE_PARAMCACHE
1458 (
const_cast<IModelFunction &
>(func)).SetParameters(
p);
1461 nPoints =
data.Size();
1466 bool useBinIntegral = fitOpt.
fIntegral &&
data.HasBinEdges();
1468 bool useW2 = (iWeight == 2);
1471 double wrefVolume = 1.0;
1478 std::cout <<
"Evaluate PoissonLogL for params = [ ";
1479 for (
unsigned int j = 0; j < func.NPar(); ++j) std::cout <<
p[j] <<
" , ";
1480 std::cout <<
"] - data size = " <<
n <<
" useBinIntegral " << useBinIntegral <<
" useBinVolume "
1481 << useBinVolume <<
" useW2 " << useW2 <<
" wrefVolume = " << wrefVolume << std::endl;
1490#ifdef USE_PARAMCACHE
1491 IntegralEvaluator<> igEval(func,
nullptr, useBinIntegral, igType);
1493 IntegralEvaluator<> igEval(func,
p, useBinIntegral, igType);
1496 auto mapFunction = [&](
const unsigned i) {
1497 auto x1 =
data.GetCoordComponent(i, 0);
1498 auto y = *
data.ValuePtr(i);
1500 const double *
x =
nullptr;
1501 std::vector<double> xc;
1503 double binVolume = 1.0;
1506 unsigned int ndim =
data.NDim();
1507 xc.resize(
data.NDim());
1508 for (
unsigned int j = 0; j < ndim; ++j) {
1509 double xx = *
data.GetCoordComponent(i, j);
1510 double x2 =
data.GetBinUpEdgeComponent(i, j);
1511 binVolume *= std::abs(
x2 - xx);
1512 xc[j] = (useBinIntegral) ? xx : 0.5 * (
x2 + xx);
1516 binVolume *= wrefVolume;
1517 }
else if (
data.NDim() > 1) {
1518 xc.resize(
data.NDim());
1520 for (
unsigned int j = 1; j <
data.NDim(); ++j) {
1521 xc[j] = *
data.GetCoordComponent(i, j);
1528 if (!useBinIntegral) {
1529#ifdef USE_PARAMCACHE
1537 std::vector<double>
x2(
data.NDim());
1538 data.GetBinUpEdgeCoordinates(i,
x2.data());
1539 fval = igEval(
x,
x2.data());
1541 if (useBinVolume) fval *= binVolume;
1547 if (i % NSAMPLE == 0) {
1548 std::cout <<
"evt " << i <<
" x = [ ";
1549 for (
unsigned int j = 0; j < func.NDim(); ++j) std::cout <<
x[j] <<
" , ";
1552 std::cout <<
"x2 = [ ";
1553 for (
unsigned int j = 0; j < func.NDim(); ++j) std::cout <<
data.GetBinUpEdgeComponent(i, j) <<
" , ";
1556 std::cout <<
" y = " <<
y <<
" fval = " << fval << std::endl;
1563 fval = std::max(fval, 0.0);
1565 double nloglike = 0;
1574 double weight = 1.0;
1576 double error =
data.Error(i);
1577 weight = (error * error) /
y;
1582 weight =
data.SumOfError2()/
data.SumOfContent();
1585 nloglike += weight * ( fval -
y);
1593 if (extended) nloglike = fval -
y;
1602 std::cout <<
" nll = " << nloglike << std::endl;
1609 auto redFunction = [](
const std::vector<double> &objs) {
1610 return std::accumulate(objs.begin(), objs.end(),
double{});
1617 Warning(
"FitUtil::EvaluatePoissonLogL",
"Multithread execution policy requires IMT, which is disabled. Changing "
1618 "to ROOT::EExecutionPolicy::kSequential.");
1625 for (
unsigned int i = 0; i <
n; ++i) {
1626 res += mapFunction(i);
1638 Error(
"FitUtil::EvaluatePoissonLogL",
1639 "Execution policy unknown. Available choices:\n ROOT::EExecutionPolicy::kSequential (default)\n ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
1643 std::cout <<
"Loglikelihood = " << res << std::endl;
1655 assert(fg !=
nullptr);
1659#ifdef USE_PARAMCACHE
1663 const DataOptions &fitOpt =
data.Opt();
1664 bool useBinIntegral = fitOpt.fIntegral &&
data.HasBinEdges();
1665 bool useBinVolume = (fitOpt.fBinVolume &&
data.HasBinEdges());
1667 double wrefVolume = 1.0;
1668 if (useBinVolume && fitOpt.fNormBinVolume)
1669 wrefVolume /=
data.RefVolume();
1677 IntegralEvaluator<> igEval(func,
p, useBinIntegral, igType);
1679 unsigned int npar = func.NPar();
1680 unsigned initialNPoints =
data.Size();
1682 auto mapFunction = [&](
const unsigned int i) {
1684 std::vector<double> gradFunc(npar);
1685 std::vector<double> pointContribution(npar);
1687 const auto x1 =
data.GetCoordComponent(i, 0);
1688 const auto y =
data.Value(i);
1689 auto invError =
data.Error(i);
1691 invError = (invError != 0.0) ? 1.0 / invError : 1;
1695 const double *
x =
nullptr;
1696 std::vector<double> xc;
1698 unsigned ndim =
data.NDim();
1699 double binVolume = 1.0;
1704 for (
unsigned int j = 0; j < ndim; ++j) {
1705 double x1_j = *
data.GetCoordComponent(i, j);
1706 double x2_j =
data.GetBinUpEdgeComponent(i, j);
1707 binVolume *= std::abs(x2_j - x1_j);
1708 xc[j] = (useBinIntegral) ? x1_j : 0.5 * (x2_j + x1_j);
1714 binVolume *= wrefVolume;
1715 }
else if (ndim > 1) {
1718 for (
unsigned int j = 1; j < ndim; ++j)
1719 xc[j] = *
data.GetCoordComponent(i, j);
1725 if (!useBinIntegral) {
1727 func.ParameterGradient(
x,
p, &gradFunc[0]);
1731 std::vector<double>
x2(
data.NDim());
1732 data.GetBinUpEdgeCoordinates(i,
x2.data());
1733 fval = igEval(
x,
x2.data());
1742 if (i < 5 || (i >
data.Size()-5) ) {
1743 if (
data.NDim() > 1) std::cout << i <<
" x " <<
x[0] <<
" y " <<
x[1] <<
" func " << fval
1744 <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1745 else std::cout << i <<
" x " <<
x[0] <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1751 for (
unsigned int ipar = 0; ipar < npar; ++ipar) {
1755 gradFunc[ipar] *= binVolume;
1759 pointContribution[ipar] = gradFunc[ipar] * (1. -
y / fval);
1760 else if (gradFunc[ipar] != 0) {
1761 const double kdmax1 = std::sqrt(std::numeric_limits<double>::max());
1762 const double kdmax2 = std::numeric_limits<double>::max() / (4 * initialNPoints);
1763 double gg = kdmax1 * gradFunc[ipar];
1765 gg = std::min(gg, kdmax2);
1767 gg = std::max(gg, -kdmax2);
1768 pointContribution[ipar] = -gg;
1773 return pointContribution;
1777 auto redFunction = [&](
const std::vector<std::vector<double>> &pointContributions) {
1778 std::vector<double>
result(npar);
1780 for (
auto const &pointContribution : pointContributions) {
1781 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1782 result[parameterIndex] += pointContribution[parameterIndex];
1788 std::vector<double>
g(npar);
1793 Warning(
"FitUtil::EvaluatePoissonLogLGradient",
1794 "Multithread execution policy requires IMT, which is disabled. Changing "
1795 "to ROOT::EExecutionPolicy::kSequential.");
1801 std::vector<std::vector<double>> allGradients(initialNPoints);
1802 for (
unsigned int i = 0; i < initialNPoints; ++i) {
1803 allGradients[i] = mapFunction(i);
1805 g = redFunction(allGradients);
1820 Error(
"FitUtil::EvaluatePoissonLogLGradient",
1821 "Execution policy unknown. Available choices:\n 0: Serial (default)\n 1: MultiThread (requires IMT)\n");
1830 std::copy(
g.begin(),
g.end(), grad);
1833 std::cout <<
"***** Final gradient : ";
1834 for (
unsigned int ii = 0; ii< npar; ++ii) std::cout << grad[ii] <<
" ";
1843 if (nEvents/ncpu < 1000)
return ncpu;
1844 return nEvents/1000;
#define MATH_ERROR_MSG(loc, str)
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void gc
R__EXTERN TVirtualMutex * gROOTMutex
#define R__LOCKGUARD(mutex)
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
SimpleGradientCalculator(int gdim, const IModelFunction &func, double eps=2.E-8, int istrat=1)
const IModelFunction & fFunc
std::vector< double > fVec
double ParameterDerivative(const double *x, const double *p, int ipar) const
void Gradient(const double *x, const double *p, double f0, double *g)
unsigned int NDim() const
void ParameterGradient(const double *x, const double *p, double f0, double *g)
unsigned int NPar() const
double DoParameterDerivative(const double *x, const double *p, double f0, int k) const
Class describing the un-binned data sets (just x coordinates values) of any dimensions.
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
virtual void SetParameters(const double *p)=0
Set the parameter values.
virtual unsigned int NPar() const =0
Return the number of Parameters.
Interface (abstract class) for parametric gradient multi-dimensional functions providing in addition ...
virtual void ParameterGradient(const T *x, const double *p, T *grad) const
Evaluate the all the derivatives (gradient vector) of the function with respect to the parameters at ...
virtual bool HasParameterHessian() const
virtual bool ParameterHessian(const T *, const double *, T *) const
Evaluate the all the Hessian (second derivatives matrix) of the function with respect to the paramete...
OneDimMultiFunctionAdapter class to wrap a multidimensional function in one dimensional one.
void SetCoord(int icoord)
User class for calculating the derivatives of a function.
double Derivative1(double x)
Returns the first derivative of the function at point x, computed by Richardson's extrapolation metho...
A pseudo container class which is a generator of indices.
This class provides a simple interface to execute the same task multiple times in parallel threads,...
auto MapReduce(F func, unsigned nTimes, R redfunc) -> InvokeResult_t< F >
Execute a function nTimes in parallel (Map) and accumulate the results into a single value (Reduce).
Type
enumeration specifying the integration types.
@ kGAUSS
simple Gauss integration method with fixed rule
@ kDEFAULT
default type specified in the static options
TFitResultPtr Fit(FitObject *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
ROOT::Math::IParamMultiGradFunction IGradModelFunction
void CalculateGradientIntegral(const GFunc &gfunc, const double *x1, const double *x2, const double *p, double *g)
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)
evaluate the pdf contribution to the Poisson LogL given a model function and the BinPoint data.
double CorrectValue(double rval)
void EvaluatePoissonLogLGradient(const IModelFunction &func, const BinData &data, const double *p, double *grad, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy=::ROOT::EExecutionPolicy::kSequential, unsigned nChunks=0)
evaluate the Poisson LogL given a model function and the data at the point p.
double EvaluateChi2Residual(const IModelFunction &func, const BinData &data, const double *p, unsigned int ipoint, double *g=nullptr, double *h=nullptr, bool hasGrad=false, bool fullHessian=false)
evaluate the residual contribution to the Chi2 given a model function and the BinPoint data and if th...
double EvaluatePoissonLogL(const IModelFunction &func, const BinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks=0)
evaluate the Poisson LogL given a model function and the data at the point p.
double EvaluateChi2Effective(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints)
evaluate the effective Chi2 given a model function and the data at the point x.
void EvaluateLogLGradient(const IModelFunction &func, const UnBinData &data, const double *p, double *grad, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy=::ROOT::EExecutionPolicy::kSequential, unsigned nChunks=0)
evaluate the LogL gradient given a model function and the data at the point p.
double 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)
evaluate the pdf contribution to the LogL given a model function and the BinPoint data.
bool CheckInfNaNValue(double &rval)
unsigned setAutomaticChunking(unsigned nEvents)
double EvaluateLogL(const IModelFunction &func, const UnBinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks=0)
evaluate the LogL given a model function and the data at the point x.
double EvaluateChi2(const IModelFunction &func, const BinData &data, const double *p, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks=0)
Chi2 Functions.
void EvaluateChi2Gradient(const IModelFunction &func, const BinData &data, const double *p, double *grad, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy=::ROOT::EExecutionPolicy::kSequential, unsigned nChunks=0)
evaluate the Chi2 gradient given a model function and the data at the point p.
void(off) SmallVectorTemplateBase< T
T EvalLog(T x)
safe evaluation of log(x) with a protections against negative or zero argument to the log smooth line...
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
UInt_t GetThreadPoolSize()
Returns the size of ROOT's thread pool.
DataOptions : simple structure holding the options on how the data are filled.
bool fErrors1
use all errors equal to 1, i.e. fit without errors (default is false)
bool fNormBinVolume
normalize data by a normalized the bin volume (bin volume divided by a reference value)
bool fUseEmpty
use empty bins (default is false) with a fixed error of 1
bool fIntegral
use integral of bin content instead of bin center (default is false)
bool fExpErrors
use expected errors from the function and not from the data
bool fBinVolume
normalize data by the bin volume (it is used in the Poisson likelihood fits)
double operator()(const double *x, const double *p) const
void SetDerivComponent(unsigned int ipar)
unsigned int NDim() const
ParamDerivFunc(const GradFunc &f)