54 RooArgSet RooNLLVar::_emptySet ;
72 RooNLLVar::RooNLLVar(const
char *name, const
char* title, RooAbsPdf& pdf, RooAbsData& indata,
73 const RooCmdArg& arg1, const RooCmdArg& arg2,const RooCmdArg& arg3,
74 const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6,
75 const RooCmdArg& arg7, const RooCmdArg& arg8,const RooCmdArg& arg9) :
76 RooAbsOptTestStatistic(name,title,pdf,indata,
77 *(const RooArgSet*)RooCmdConfig::decodeObjOnTheFly("RooNLLVar::RooNLLVar","ProjectedObservables",0,&_emptySet
78 ,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9),
79 RooCmdConfig::decodeStringOnTheFly("RooNLLVar::RooNLLVar","RangeWithName",0,"",arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9).c_str(),
80 RooCmdConfig::decodeStringOnTheFly("RooNLLVar::RooNLLVar","AddCoefRange",0,"",arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9).c_str(),
81 RooCmdConfig::decodeIntOnTheFly("RooNLLVar::RooNLLVar","NumCPU",0,1,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9),
82 RooFit::BulkPartition,
83 RooCmdConfig::decodeIntOnTheFly("RooNLLVar::RooNLLVar","Verbose",0,1,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9),
84 RooCmdConfig::decodeIntOnTheFly("RooNLLVar::RooNLLVar","SplitRange",0,0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9),
85 RooCmdConfig::decodeIntOnTheFly("RooNLLVar::RooNLLVar","CloneData",0,1,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9))
87 RooCmdConfig pc(
"RooNLLVar::RooNLLVar") ;
89 pc.defineInt(
"extended",
"Extended",0,kFALSE) ;
90 pc.defineInt(
"BatchMode",
"BatchMode", 0,
false);
92 pc.process(arg1) ; pc.process(arg2) ; pc.process(arg3) ;
93 pc.process(arg4) ; pc.process(arg5) ; pc.process(arg6) ;
94 pc.process(arg7) ; pc.process(arg8) ; pc.process(arg9) ;
96 _extended = pc.getInt(
"extended") ;
97 _batchEvaluations = pc.getInt(
"BatchMode");
103 _offsetCarrySaveW2 = 0.;
114 RooNLLVar::RooNLLVar(
const char *name,
const char *title, RooAbsPdf& pdf, RooAbsData& indata,
115 Bool_t extended,
const char* rangeName,
const char* addCoefRangeName,
116 Int_t nCPU, RooFit::MPSplit interleave, Bool_t verbose, Bool_t splitRange, Bool_t cloneData, Bool_t binnedL) :
117 RooAbsOptTestStatistic(name,title,pdf,indata,RooArgSet(),rangeName,addCoefRangeName,nCPU,interleave,verbose,splitRange,cloneData),
120 _first(kTRUE), _offsetSaveW2(0.), _offsetCarrySaveW2(0.)
124 _binnedPdf = binnedL ? (RooRealSumPdf*)_funcClone : 0 ;
130 _binnedPdf->setAttribute(
"BinnedLikelihoodActive") ;
132 RooArgSet* obs = _funcClone->getObservables(_dataClone) ;
133 if (obs->getSize()!=1) {
136 RooRealVar* var = (RooRealVar*) obs->first() ;
137 std::list<Double_t>* boundaries = _binnedPdf->binBoundaries(*var,var->getMin(),var->getMax()) ;
138 std::list<Double_t>::iterator biter = boundaries->begin() ;
139 _binw.resize(boundaries->size()-1) ;
140 Double_t lastBound = (*biter) ;
143 while (biter!=boundaries->end()) {
144 _binw[ibin] = (*biter) - lastBound ;
145 lastBound = (*biter) ;
159 RooNLLVar::RooNLLVar(
const char *name,
const char *title, RooAbsPdf& pdf, RooAbsData& indata,
160 const RooArgSet& projDeps, Bool_t extended,
const char* rangeName,
const char* addCoefRangeName,
161 Int_t nCPU,RooFit::MPSplit interleave,Bool_t verbose, Bool_t splitRange, Bool_t cloneData, Bool_t binnedL) :
162 RooAbsOptTestStatistic(name,title,pdf,indata,projDeps,rangeName,addCoefRangeName,nCPU,interleave,verbose,splitRange,cloneData),
165 _first(kTRUE), _offsetSaveW2(0.), _offsetCarrySaveW2(0.)
169 _binnedPdf = binnedL ? (RooRealSumPdf*)_funcClone : 0 ;
174 RooArgSet* obs = _funcClone->getObservables(_dataClone) ;
175 if (obs->getSize()!=1) {
178 RooRealVar* var = (RooRealVar*) obs->first() ;
179 std::list<Double_t>* boundaries = _binnedPdf->binBoundaries(*var,var->getMin(),var->getMax()) ;
180 std::list<Double_t>::iterator biter = boundaries->begin() ;
181 _binw.resize(boundaries->size()-1) ;
182 Double_t lastBound = (*biter) ;
185 while (biter!=boundaries->end()) {
186 _binw[ibin] = (*biter) - lastBound ;
187 lastBound = (*biter) ;
200 RooNLLVar::RooNLLVar(
const RooNLLVar& other,
const char* name) :
201 RooAbsOptTestStatistic(other,name),
202 _extended(other._extended),
203 _batchEvaluations(other._batchEvaluations),
204 _weightSq(other._weightSq),
205 _first(kTRUE), _offsetSaveW2(other._offsetSaveW2),
206 _offsetCarrySaveW2(other._offsetCarrySaveW2),
208 _binnedPdf = other._binnedPdf ? (RooRealSumPdf*)_funcClone : 0 ;
217 RooNLLVar::~RooNLLVar()
226 void RooNLLVar::applyWeightSquared(Bool_t flag)
228 if (_gofOpMode==Slave) {
229 if (flag != _weightSq) {
231 std::swap(_offset, _offsetSaveW2);
232 std::swap(_offsetCarry, _offsetCarrySaveW2);
235 }
else if ( _gofOpMode==MPMaster) {
236 for (Int_t i=0 ; i<_nCPU ; i++)
237 _mpfeArray[i]->applyNLLWeightSquared(flag);
238 }
else if ( _gofOpMode==SimMaster) {
239 for (Int_t i=0 ; i<_nGof ; i++)
240 ((RooNLLVar*)_gofArray[i])->applyWeightSquared(flag);
255 Double_t RooNLLVar::evaluatePartition(std::size_t firstEvent, std::size_t lastEvent, std::size_t stepSize)
const
261 double result(0), carry(0), sumWeight(0);
263 RooAbsPdf* pdfClone = (RooAbsPdf*) _funcClone ;
267 _dataClone->store()->recalculateCache( _projDeps, firstEvent, lastEvent, stepSize, (_binnedPdf?kFALSE:kTRUE) ) ;
273 double sumWeightCarry = 0.;
274 for (
auto i=firstEvent ; i<lastEvent ; i+=stepSize) {
278 if (!_dataClone->valid())
continue;
280 Double_t eventWeight = _dataClone->weight();
284 Double_t N = eventWeight ;
285 Double_t mu = _binnedPdf->getVal()*_binw[i] ;
291 logEvalError(Form(
"Observed %f events in bin %lu with zero event yield",N,(
unsigned long)i)) ;
293 }
else if (fabs(mu)<1e-10 && fabs(N)<1e-10) {
300 Double_t term = -1*(-mu + N*log(mu) - TMath::LnGamma(N+1)) ;
304 Double_t y = eventWeight - sumWeightCarry;
305 Double_t t = sumWeight + y;
306 sumWeightCarry = (t - sumWeight) - y;
312 carry = (t - result) - y;
320 if (_batchEvaluations) {
321 std::tie(result, carry, sumWeight) = computeBatched(stepSize, firstEvent, lastEvent);
322 #ifdef ROOFIT_CHECK_CACHED_VALUES
324 double resultScalar, carryScalar, sumWeightScalar;
325 std::tie(resultScalar, carryScalar, sumWeightScalar) =
326 computeScalar(stepSize, firstEvent, lastEvent);
328 constexpr
bool alwaysPrint =
false;
330 if (alwaysPrint || fabs(result - resultScalar)/resultScalar > 1.E-15) {
331 std::cerr <<
"RooNLLVar: result is off\n\t" << std::setprecision(15) << result
332 <<
"\n\t" << resultScalar << std::endl;
335 if (alwaysPrint || fabs(carry - carryScalar)/carryScalar > 10.) {
336 std::cerr <<
"RooNLLVar: carry is far off\n\t" << std::setprecision(15) << carry
337 <<
"\n\t" << carryScalar << std::endl;
340 if (alwaysPrint || fabs(sumWeight - sumWeightScalar)/sumWeightScalar > 1.E-15) {
341 std::cerr <<
"RooNLLVar: sumWeight is off\n\t" << std::setprecision(15) << sumWeight
342 <<
"\n\t" << sumWeightScalar << std::endl;
347 std::tie(result, carry, sumWeight) = computeScalar(stepSize, firstEvent, lastEvent);
351 if(_extended && _setNum==_extSet) {
356 Double_t sumW2(0), sumW2carry(0);
357 for (decltype(_dataClone->numEntries()) i = 0; i < _dataClone->numEntries() ; i++) {
359 Double_t y = _dataClone->weightSquared() - sumW2carry;
360 Double_t t = sumW2 + y;
361 sumW2carry = (t - sumW2) - y;
365 Double_t expected= pdfClone->expectedEvents(_dataClone->get());
383 Double_t expectedW2 = expected * sumW2 / _dataClone->sumEntries() ;
384 Double_t extra= expectedW2 - sumW2*log(expected );
388 Double_t y = extra - carry ;
390 Double_t t = result + y;
391 carry = (t - result) - y;
394 Double_t y = pdfClone->extendedTerm(_dataClone->sumEntries(), _dataClone->get()) - carry;
395 Double_t t = result + y;
396 carry = (t - result) - y;
406 Double_t y = sumWeight*log(1.0*_simCount) - carry;
407 Double_t t = result + y;
408 carry = (t - result) - y;
416 _funcClone->wireAllCaches() ;
424 if (_offset==0 && result !=0 ) {
425 coutI(Minimization) <<
"RooNLLVar::evaluatePartition(" << GetName() <<
") first = "<< firstEvent <<
" last = " << lastEvent <<
" Likelihood offset now set to " << result << std::endl ;
427 _offsetCarry = carry;
431 Double_t y = -_offset - (carry + _offsetCarry);
432 Double_t t = result + y;
433 carry = (t - result) - y;
443 std::tuple<double, double, double> RooNLLVar::computeBatched(std::size_t stepSize, std::size_t firstEvent, std::size_t lastEvent)
const
446 throw std::invalid_argument(std::string(
"Error in ") + __FILE__ +
": Step size for batch computations can only be 1.");
449 auto pdfClone =
static_cast<const RooAbsPdf*
>(_funcClone);
451 auto results = pdfClone->getLogValBatch(firstEvent, lastEvent-firstEvent, _normSet);
454 #ifdef ROOFIT_CHECK_CACHED_VALUES
455 for (std::size_t evtNo = firstEvent; evtNo < lastEvent; ++evtNo) {
456 _dataClone->get(evtNo);
457 assert(_dataClone->valid());
458 pdfClone->getValV(_normSet);
460 RooHelpers::BatchInterfaceAccessor::checkBatchComputation(*pdfClone, evtNo, _normSet);
461 }
catch (std::exception& e) {
462 std::cerr <<
"ERROR when checking batch computation for event " << evtNo <<
":\n"
463 << e.what() << std::endl;
470 const RooSpan<const double> eventWeights = _dataClone->getWeightBatch(firstEvent, lastEvent);
472 const bool retrieveSquaredWeights = _weightSq;
473 auto retrieveWeight = [&eventWeights, retrieveSquaredWeights](std::size_t i) {
474 if (retrieveSquaredWeights)
475 return eventWeights[i] * eventWeights[i];
477 return eventWeights[i];
481 ROOT::Math::KahanSum<double, 4u> kahanWeight;
482 if (eventWeights.size() == 1) {
483 kahanWeight.Add( (lastEvent - firstEvent) * retrieveWeight(0));
485 for (std::size_t i = 0; i < eventWeights.size(); ++i) {
486 kahanWeight.AddIndexed(retrieveWeight(i), i);
492 ROOT::Math::KahanSum<double, 4u> kahanProb;
493 if (eventWeights.size() == 1) {
494 const double weight = retrieveWeight(0);
495 for (std::size_t i = 0; i < results.size(); ++i) {
496 kahanProb.AddIndexed(-weight * results[i], i);
499 for (std::size_t i = 0; i < results.size(); ++i) {
500 kahanProb.AddIndexed(-retrieveWeight(i) * results[i], i);
505 return std::tuple<double, double, double>{kahanProb.Sum(), kahanProb.Carry(), kahanWeight.Sum()};
509 std::tuple<double, double, double> RooNLLVar::computeScalar(std::size_t stepSize, std::size_t firstEvent, std::size_t lastEvent)
const {
510 auto pdfClone =
static_cast<const RooAbsPdf*
>(_funcClone);
512 ROOT::Math::KahanSum<double> kahanWeight;
513 ROOT::Math::KahanSum<double> kahanProb;
515 for (
auto i=firstEvent; i<lastEvent; i+=stepSize) {
518 if (!_dataClone->valid())
continue;
520 Double_t eventWeight = _dataClone->weight();
521 if (0. == eventWeight * eventWeight) continue ;
522 if (_weightSq) eventWeight = _dataClone->weightSquared() ;
524 const double term = -eventWeight * pdfClone->getLogVal(_normSet);
526 kahanWeight.Add(eventWeight);
530 return std::tuple<double, double, double>{kahanProb.Sum(), kahanProb.Carry(), kahanWeight.Sum()};