00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "RooFit.h"
00030 #include "Riostream.h"
00031
00032 #include "RooAcceptReject.h"
00033 #include "RooAcceptReject.h"
00034 #include "RooAbsReal.h"
00035 #include "RooCategory.h"
00036 #include "RooRealVar.h"
00037 #include "RooDataSet.h"
00038 #include "RooRandom.h"
00039 #include "RooErrorHandler.h"
00040
00041 #include "TString.h"
00042 #include "TIterator.h"
00043 #include "RooMsgService.h"
00044 #include "TClass.h"
00045 #include "TFoam.h"
00046 #include "RooRealBinding.h"
00047 #include "RooNumGenFactory.h"
00048 #include "RooNumGenConfig.h"
00049
00050 #include <assert.h>
00051
00052 ClassImp(RooAcceptReject)
00053 ;
00054
00055
00056
00057 void RooAcceptReject::registerSampler(RooNumGenFactory& fact)
00058 {
00059
00060 RooRealVar nTrial0D("nTrial0D","Number of trial samples for cat-only generation",100,0,1e9) ;
00061 RooRealVar nTrial1D("nTrial1D","Number of trial samples for 1-dim generation",1000,0,1e9) ;
00062 RooRealVar nTrial2D("nTrial2D","Number of trial samples for 2-dim generation",100000,0,1e9) ;
00063 RooRealVar nTrial3D("nTrial3D","Number of trial samples for N-dim generation",10000000,0,1e9) ;
00064
00065 RooAcceptReject* proto = new RooAcceptReject ;
00066 fact.storeProtoSampler(proto,RooArgSet(nTrial0D,nTrial1D,nTrial2D,nTrial3D)) ;
00067 }
00068
00069
00070
00071
00072 RooAcceptReject::RooAcceptReject(const RooAbsReal &func, const RooArgSet &genVars, const RooNumGenConfig& config, Bool_t verbose, const RooAbsReal* maxFuncVal) :
00073 RooAbsNumGenerator(func,genVars,verbose,maxFuncVal), _nextCatVar(0), _nextRealVar(0)
00074 {
00075
00076
00077
00078
00079
00080 _minTrialsArray[0] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial0D")) ;
00081 _minTrialsArray[1] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial1D")) ;
00082 _minTrialsArray[2] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial2D")) ;
00083 _minTrialsArray[3] = static_cast<Int_t>(config.getConfigSection("RooAcceptReject").getRealValue("nTrial3D")) ;
00084
00085 _realSampleDim = _realVars.getSize() ;
00086 TIterator* iter = _catVars.createIterator() ;
00087 RooAbsCategory* cat ;
00088 _catSampleMult = 1 ;
00089 while((cat=(RooAbsCategory*)iter->Next())) {
00090 _catSampleMult *= cat->numTypes() ;
00091 }
00092 delete iter ;
00093
00094
00095
00096 if (!_funcMaxVal) {
00097
00098 if(_realSampleDim > 3) {
00099 _minTrials= _minTrialsArray[3]*_catSampleMult;
00100 coutW(Generation) << fName << "::" << ClassName() << ": WARNING: generating " << _realSampleDim
00101 << " variables with accept-reject may not be accurate" << endl;
00102 }
00103 else {
00104 _minTrials= _minTrialsArray[_realSampleDim]*_catSampleMult;
00105 }
00106 } else {
00107
00108 _minTrials=0 ;
00109 }
00110
00111
00112 if (_realSampleDim > 1) {
00113 coutW(Generation) << "RooAcceptReject::ctor(" << fName
00114 << ") WARNING: performing accept/reject sampling on a p.d.f in " << _realSampleDim << " dimensions "
00115 << "without prior knowledge on maximum value of p.d.f. Determining maximum value by taking " << _minTrials
00116 << " trial samples. If p.d.f contains sharp peaks smaller than average distance between trial sampling points"
00117 << " these may be missed and p.d.f. may be sampled incorrectly." << endl ;
00118 }
00119 if (_minTrials>10000) {
00120 coutW(Generation) << "RooAcceptReject::ctor(" << fName << "): WARNING: " << _minTrials << " trial samples requested by p.d.f for "
00121 << _realSampleDim << "-dimensional accept/reject sampling, this may take some time" << endl ;
00122 }
00123
00124
00125 if(_verbose) {
00126 coutI(Generation) << fName << "::" << ClassName() << ":" << endl
00127 << " Initializing accept-reject generator for" << endl << " ";
00128 _funcClone->printStream(ccoutI(Generation),kName,kSingleLine);
00129 if (_funcMaxVal) {
00130 ccoutI(Generation) << " Function maximum provided, no trial sampling performed" << endl ;
00131 } else {
00132 ccoutI(Generation) << " Real sampling dimension is " << _realSampleDim << endl;
00133 ccoutI(Generation) << " Category sampling multiplier is " << _catSampleMult << endl ;
00134 ccoutI(Generation) << " Min sampling trials is " << _minTrials << endl;
00135 }
00136 if (_catVars.getSize()>0) {
00137 ccoutI(Generation) << " Will generate category vars "<< _catVars << endl ;
00138 }
00139 if (_realVars.getSize()>0) {
00140 ccoutI(Generation) << " Will generate real vars " << _realVars << endl ;
00141 }
00142 }
00143
00144 _nextCatVar= _catVars.createIterator();
00145 _nextRealVar= _realVars.createIterator();
00146 assert(0 != _nextCatVar && 0 != _nextRealVar);
00147
00148
00149 _maxFuncVal= 0;
00150 _funcSum= 0;
00151 _totalEvents= 0;
00152 _eventsUsed= 0;
00153 }
00154
00155
00156
00157
00158 RooAcceptReject::~RooAcceptReject()
00159 {
00160
00161 delete _nextCatVar;
00162 delete _nextRealVar;
00163 }
00164
00165
00166
00167
00168 const RooArgSet *RooAcceptReject::generateEvent(UInt_t remaining, Double_t& resampleRatio)
00169 {
00170
00171
00172
00173
00174
00175 const RooArgSet *event= _cache->get();
00176 if(event->getSize() == 1) return event;
00177
00178 if (!_funcMaxVal) {
00179
00180
00181
00182
00183
00184 while(_totalEvents < _minTrials) {
00185 addEventToCache();
00186
00187
00188 if (_cache->numEntries()>1000000) {
00189 coutI(Generation) << "RooAcceptReject::generateEvent: resetting event cache" << endl ;
00190 _cache->reset() ;
00191 _eventsUsed = 0 ;
00192 }
00193 }
00194
00195 event= 0;
00196 Double_t oldMax2(_maxFuncVal);
00197 while(0 == event) {
00198
00199 if (_maxFuncVal>oldMax2) {
00200 cxcoutD(Generation) << "RooAcceptReject::generateEvent maxFuncVal has changed, need to resample already accepted events by factor"
00201 << oldMax2 << "/" << _maxFuncVal << "=" << oldMax2/_maxFuncVal << endl ;
00202 resampleRatio=oldMax2/_maxFuncVal ;
00203 }
00204 event= nextAcceptedEvent();
00205 if(event) break;
00206
00207
00208 _cache->reset();
00209 _eventsUsed= 0;
00210
00211
00212 if(_totalEvents*_maxFuncVal <= 0) {
00213 coutE(Generation) << "RooAcceptReject::generateEvent: cannot estimate efficiency...giving up" << endl;
00214 return 0;
00215 }
00216
00217 Double_t eff= _funcSum/(_totalEvents*_maxFuncVal);
00218 Long64_t extra= 1 + (Long64_t)(1.05*remaining/eff);
00219 cxcoutD(Generation) << "RooAcceptReject::generateEvent: adding " << extra << " events to the cache, eff = " << eff << endl;
00220 Double_t oldMax(_maxFuncVal);
00221 while(extra--) {
00222 addEventToCache();
00223 if((_maxFuncVal > oldMax)) {
00224 cxcoutD(Generation) << "RooAcceptReject::generateEvent: estimated function maximum increased from "
00225 << oldMax << " to " << _maxFuncVal << endl;
00226 oldMax = _maxFuncVal ;
00227
00228 }
00229 }
00230 }
00231
00232
00233 if (_eventsUsed>1000000) {
00234 _cache->reset() ;
00235 _eventsUsed = 0 ;
00236 }
00237
00238 } else {
00239
00240 _maxFuncVal = _funcMaxVal->getVal() ;
00241
00242
00243 event = 0 ;
00244 while(0==event) {
00245 addEventToCache() ;
00246 event = nextAcceptedEvent() ;
00247 }
00248
00249 }
00250 return event;
00251 }
00252
00253
00254
00255
00256 const RooArgSet *RooAcceptReject::nextAcceptedEvent()
00257 {
00258
00259
00260
00261
00262
00263
00264 const RooArgSet *event = 0;
00265 while((event= _cache->get(_eventsUsed))) {
00266 _eventsUsed++ ;
00267
00268 Double_t r= RooRandom::uniform();
00269 if(r*_maxFuncVal > _funcValPtr->getVal()) {
00270
00271 continue;
00272 }
00273
00274
00275 if(_verbose && (_eventsUsed%1000==0)) {
00276 cerr << "RooAcceptReject: accepted event (used " << _eventsUsed << " of "
00277 << _cache->numEntries() << " so far)" << endl;
00278 }
00279 break;
00280 }
00281
00282 return event;
00283 }
00284
00285
00286
00287
00288 void RooAcceptReject::addEventToCache()
00289 {
00290
00291
00292
00293
00294 _nextCatVar->Reset();
00295 RooCategory *cat = 0;
00296 while((cat= (RooCategory*)_nextCatVar->Next())) cat->randomize();
00297
00298
00299 _nextRealVar->Reset();
00300 RooRealVar *real = 0;
00301 while((real= (RooRealVar*)_nextRealVar->Next())) real->randomize();
00302
00303
00304 Double_t val= _funcClone->getVal();
00305 _funcValPtr->setVal(val);
00306
00307
00308
00309
00310 if(val > _maxFuncVal) _maxFuncVal= 1.05*val;
00311 _funcSum+= val;
00312
00313
00314 _cache->fill();
00315 _totalEvents++;
00316
00317 if (_verbose &&_totalEvents%10000==0) {
00318 cerr << "RooAcceptReject: generated " << _totalEvents << " events so far." << endl ;
00319 }
00320
00321 }
00322
00323 Double_t RooAcceptReject::getFuncMax()
00324 {
00325
00326
00327
00328
00329
00330 while(_totalEvents < _minTrials) {
00331 addEventToCache();
00332
00333
00334 if (_cache->numEntries()>1000000) {
00335 coutI(Generation) << "RooAcceptReject::getFuncMax: resetting event cache" << endl ;
00336 _cache->reset() ;
00337 _eventsUsed = 0 ;
00338 }
00339 }
00340
00341 return _maxFuncVal ;
00342 }
00343