Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooAcceptReject.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooAcceptReject.cxx
19\class RooAcceptReject
20\ingroup Roofitcore
21
22Generic Monte Carlo toy generator implement
23the accept/reject sampling technique on any positively valued function.
24The RooAcceptReject generator is used by the various generator context
25classes to take care of generation of observables for which p.d.fs
26do not define internal methods
27**/
28
29#include "Riostream.h"
30
31#include "RooAcceptReject.h"
32#include "RooAbsReal.h"
33#include "RooCategory.h"
34#include "RooRealVar.h"
35#include "RooDataSet.h"
36#include "RooRandom.h"
37#include "RooErrorHandler.h"
38#include "RooPrintable.h"
39#include "RooMsgService.h"
40#include "RooRealBinding.h"
41#include "RooNumGenFactory.h"
42#include "RooNumGenConfig.h"
43
44#include "TFoam.h"
45#include "TNamed.h"
46
47#include <cassert>
48
49
50////////////////////////////////////////////////////////////////////////////////
51/// Register RooIntegrator1D, is parameters and capabilities with RooNumIntFactory
52
54{
55 RooRealVar nTrial0D("nTrial0D","Number of trial samples for cat-only generation",100,0,1e9) ;
56 RooRealVar nTrial1D("nTrial1D","Number of trial samples for 1-dim generation",1000,0,1e9) ;
57 RooRealVar nTrial2D("nTrial2D","Number of trial samples for 2-dim generation",100000,0,1e9) ;
58 RooRealVar nTrial3D("nTrial3D","Number of trial samples for N-dim generation",10000000,0,1e9) ;
59
62}
63
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Initialize an accept-reject generator for the specified distribution function,
68/// which must be non-negative but does not need to be normalized over the
69/// variables to be generated, genVars. The function and its dependents are
70/// cloned and so will not be disturbed during the generation process.
71
73 bool verbose, const RooAbsReal *maxFuncVal)
74 : RooAbsNumGenerator(func, genVars, verbose, maxFuncVal), _realSampleDim(_realVars.size()), _catSampleMult(1)
75{
76 _minTrialsArray[0] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial0D")) ;
77 _minTrialsArray[1] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial1D")) ;
78 _minTrialsArray[2] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial2D")) ;
79 _minTrialsArray[3] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial3D")) ;
80
82 _catSampleMult *= cat->numTypes() ;
83 }
84
85
86 // calculate the minimum number of trials needed to estimate our integral and max value
87 if (!_funcMaxVal) {
88
89 if(_realSampleDim > 3) {
91 oocoutW(nullptr, Generation) << _funcClone->GetName() << "::RooAcceptReject" << ": WARNING: generating " << _realSampleDim
92 << " variables with accept-reject may not be accurate" << std::endl;
93 }
94 else {
96 }
97 if (_realSampleDim > 1) {
98 oocoutW(nullptr, Generation) << "RooAcceptReject::ctor(" << _funcClone->GetName()
99 << ") WARNING: performing accept/reject sampling on a p.d.f in "
100 << _realSampleDim << " dimensions without prior knowledge on maximum value "
101 << "of p.d.f. Determining maximum value by taking " << _minTrials
102 << " trial samples. If p.d.f contains sharp peaks smaller than average "
103 << "distance between trial sampling points these may be missed and p.d.f. "
104 << "may be sampled incorrectly." << std::endl ;
105 }
106 } else {
107 // No trials needed if we know the maximum a priori
108 _minTrials=0 ;
109 }
110
111 // Need to fix some things here
112 if (_minTrials>10000) {
113 oocoutW(nullptr, Generation) << "RooAcceptReject::ctor(" << func.GetName() << "): WARNING: " << _minTrials << " trial samples requested by p.d.f for "
114 << _realSampleDim << "-dimensional accept/reject sampling, this may take some time" << std::endl ;
115 }
116
117 // print a verbose summary of our configuration, if requested
118 if(_verbose) {
119 oocoutI(nullptr, Generation) << func.GetName() << "::RooAcceptReject" << ":" << std::endl
120 << " Initializing accept-reject generator for" << std::endl << " ";
122 if (_funcMaxVal) {
123 ooccoutI(nullptr, Generation) << " Function maximum provided, no trial sampling performed" << std::endl ;
124 } else {
125 ooccoutI(nullptr, Generation) << " Real sampling dimension is " << _realSampleDim << std::endl;
126 ooccoutI(nullptr, Generation) << " Category sampling multiplier is " << _catSampleMult << std::endl ;
127 ooccoutI(nullptr, Generation) << " Min sampling trials is " << _minTrials << std::endl;
128 }
129 if (!_catVars.empty()) {
130 ooccoutI(nullptr, Generation) << " Will generate category vars "<< _catVars << std::endl ;
131 }
132 if (!_realVars.empty()) {
133 ooccoutI(nullptr, Generation) << " Will generate real vars " << _realVars << std::endl ;
134 }
135 }
136
137 // initialize our statistics
138 _maxFuncVal= 0;
139 _funcSum= 0;
140 _totalEvents= 0;
141 _eventsUsed= 0;
142}
143
144
145////////////////////////////////////////////////////////////////////////////////
146/// Return a pointer to a generated event. The caller does not own the event and it
147/// will be overwritten by a subsequent call. The input parameter 'remaining' should
148/// contain your best guess at the total number of subsequent events you will request.
149
151{
152 // are we actually generating anything? (the cache always contains at least our function value)
153 const RooArgSet *event= _cache->get();
154 if(event->size() == 1) return event;
155
156 if (!_funcMaxVal) {
157 // Generation with empirical maximum determination
158
159 // first generate enough events to get reasonable estimates for the integral and
160 // maximum function value
161
162 while(_totalEvents < _minTrials) {
164
165 // Limit cache size to 1M events
166 if (_cache->numEntries()>1000000) {
167 oocoutI(nullptr, Generation) << "RooAcceptReject::generateEvent: resetting event cache" << std::endl;
168 _cache->reset() ;
169 _eventsUsed = 0 ;
170 }
171 }
172
173 event= nullptr;
174 double oldMax2(_maxFuncVal);
175 while(nullptr == event) {
176 // Use any cached events first
177 if (_maxFuncVal>oldMax2) {
178 oocxcoutD(nullptr, Generation) << "RooAcceptReject::generateEvent maxFuncVal has changed, need to resample already accepted events by factor"
179 << oldMax2 << "/" << _maxFuncVal << "=" << oldMax2/_maxFuncVal << std::endl ;
181 }
182 event= nextAcceptedEvent();
183 if(event) break;
184 // When we have used up the cache, start a new cache and add
185 // some more events to it.
186 _cache->reset();
187 _eventsUsed= 0;
188 // Calculate how many more events to generate using our best estimate of our efficiency.
189 // Always generate at least one more event so we don't get stuck.
190 if(_totalEvents*_maxFuncVal <= 0) {
191 oocoutE(nullptr, Generation) << "RooAcceptReject::generateEvent: cannot estimate efficiency...giving up" << std::endl;
192 return nullptr;
193 }
194
195 double eff= _funcSum/(_totalEvents*_maxFuncVal);
196 Long64_t extra= 1 + (Long64_t)(1.05*remaining/eff);
197 oocxcoutD(nullptr, Generation) << "RooAcceptReject::generateEvent: adding " << extra << " events to the cache, eff = " << eff << std::endl;
198 double oldMax(_maxFuncVal);
199 while(extra--) {
201 if((_maxFuncVal > oldMax)) {
202 oocxcoutD(nullptr, Generation) << "RooAcceptReject::generateEvent: estimated function maximum increased from "
203 << oldMax << " to " << _maxFuncVal << std::endl;
205 // Trim cache here
206 }
207 }
208 }
209
210 // Limit cache size to 1M events
211 if (_eventsUsed>1000000) {
212 _cache->reset() ;
213 _eventsUsed = 0 ;
214 }
215
216 } else {
217 // Generation with a priori maximum knowledge
218 _maxFuncVal = _funcMaxVal->getVal() ;
219
220 // Generate enough trials to produce a single accepted event
221 event = nullptr ;
222 while(nullptr==event) {
224 event = nextAcceptedEvent() ;
225 }
226
227 }
228 return event;
229}
230
231
232
233////////////////////////////////////////////////////////////////////////////////
234/// Scan through events in the cache which have not been used yet,
235/// looking for the first accepted one which is added to the specified
236/// container. Return a pointer to the accepted event, or else zero
237/// if we use up the cache before we accept an event. The caller does
238/// not own the event and it will be overwritten by a subsequent call.
239
241{
242 const RooArgSet *event = nullptr;
243 while((event= _cache->get(_eventsUsed))) {
244 _eventsUsed++ ;
245 // accept this cached event?
246 double r= RooRandom::uniform();
248 //cout << " event number " << _eventsUsed << " has been rejected" << std::endl ;
249 continue;
250 }
251 //cout << " event number " << _eventsUsed << " has been accepted" << std::endl ;
252 // copy this event into the output container
253 if(_verbose && (_eventsUsed%1000==0)) {
254 std::cerr << "RooAcceptReject: accepted event (used " << _eventsUsed << " of "
255 << _cache->numEntries() << " so far)" << std::endl;
256 }
257 break;
258 }
259 //cout << "accepted event " << _eventsUsed << " of " << _cache->numEntries() << std::endl ;
260 return event;
261}
262
263
264
265////////////////////////////////////////////////////////////////////////////////
266/// Add a trial event to our cache and update our estimates
267/// of the function maximum value and integral.
268
270{
271 // randomize each discrete argument
272 for(auto * cat : static_range_cast<RooCategory*>(_catVars)) cat->randomize();
273
274 // randomize each real argument
275 for(auto * real : static_range_cast<RooRealVar*>(_realVars)) real->randomize();
276
277 // calculate and store our function value at this new point
278 double val= _funcClone->getVal();
279 _funcValPtr->setVal(val);
280
281 // Update the estimated integral and maximum value. Increase our
282 // maximum estimate slightly to give a safety margin with a
283 // corresponding loss of efficiency.
284 if(val > _maxFuncVal) _maxFuncVal= 1.05*val;
285 _funcSum+= val;
286
287 // fill a new entry in our cache dataset for this point
288 _cache->fill();
289 _totalEvents++;
290
291 if (_verbose &&_totalEvents%10000==0) {
292 std::cerr << "RooAcceptReject: generated " << _totalEvents << " events so far." << std::endl ;
293 }
294
295}
296
298{
299 // Empirically determine maximum value of function by taking a large number
300 // of samples. The actual number depends on the number of dimensions in which
301 // the sampling occurs
302
303 // Generate the minimum required number of samples for a reliable maximum estimate
304 while(_totalEvents < _minTrials) {
306
307 // Limit cache size to 1M events
308 if (_cache->numEntries()>1000000) {
309 oocoutI(nullptr, Generation) << "RooAcceptReject::getFuncMax: resetting event cache" << std::endl ;
310 _cache->reset() ;
311 _eventsUsed = 0 ;
312 }
313 }
314
315 return _maxFuncVal ;
316}
317
318std::string const& RooAcceptReject::generatorName() const {
319 static const std::string name = "RooAcceptReject";
320 return name;
321}
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define oocoutW(o, a)
#define oocxcoutD(o, a)
#define oocoutE(o, a)
#define oocoutI(o, a)
#define ooccoutI(o, a)
long long Long64_t
Definition RtypesCore.h:69
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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 r
char name[80]
Definition TGX11.cxx:110
const char * proto
Definition civetweb.c:17535
Abstract base class for MC event generator implementations like RooAcceptReject and RooFoam.
RooArgSet _catVars
Set of discrete observabeles.
RooArgSet _realVars
Set of real valued observabeles.
const RooAbsReal * _funcMaxVal
Container for maximum function value.
RooAbsReal * _funcClone
Pointer to top level node of cloned function.
bool _verbose
Verbose flag.
RooRealVar * _funcValPtr
RRV storing function value in output dataset.
std::unique_ptr< RooDataSet > _cache
Dataset holding generared values of observables.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
Generic Monte Carlo toy generator implement the accept/reject sampling technique on any positively va...
UInt_t _minTrialsArray[4]
Minimum number of trials samples for 1,2,3 dimensional problems.
UInt_t _minTrials
Minimum number of max.finding trials, total number of samples.
static void registerSampler(RooNumGenFactory &fact)
Register RooIntegrator1D, is parameters and capabilities with RooNumIntFactory.
double getFuncMax() override
const RooArgSet * nextAcceptedEvent()
Scan through events in the cache which have not been used yet, looking for the first accepted one whi...
void addEventToCache()
Add a trial event to our cache and update our estimates of the function maximum value and integral.
double _funcSum
Maximum function value found, and sum of all samples made.
UInt_t _realSampleDim
Number of real dimensions to be sampled.
std::string const & generatorName() const override
Return unique name of generator implementation.
UInt_t _totalEvents
Total number of function samples.
UInt_t _catSampleMult
Number of discrete dimensions to be sampled.
const RooArgSet * generateEvent(UInt_t remaining, double &resampleRatio) override
Return a pointer to a generated event.
UInt_t _eventsUsed
Accepted number of function samples.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Holds the configuration parameters of the various numeric integrators used by RooRealIntegral.
const RooArgSet & getConfigSection(const char *name) const
Retrieve configuration information specific to integrator with given name.
Factory to instantiate numeric integrators from a given function binding and a given configuration.
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
static double uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1)
Definition RooRandom.cxx:77
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setVal(double value) override
Set value of variable to 'value'.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47