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 #include "RooFit.h"
00029
00030 #include "Riostream.h"
00031 #include "Riostream.h"
00032 #include <math.h>
00033 #include <vector>
00034 #include <utility>
00035 #include <memory>
00036
00037 #include "RooProduct.h"
00038 #include "RooNameReg.h"
00039 #include "RooAbsReal.h"
00040 #include "RooAbsCategory.h"
00041 #include "RooErrorHandler.h"
00042 #include "RooMsgService.h"
00043
00044 using namespace std ;
00045
00046 ClassImp(RooProduct)
00047 ;
00048
00049 class RooProduct::ProdMap : public std::vector<std::pair<RooArgSet*,RooArgSet*> > {} ;
00050
00051
00052 namespace {
00053 typedef RooProduct::ProdMap::iterator RPPMIter ;
00054 std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end) ;
00055 void dump_map(ostream& os, RPPMIter i, RPPMIter end) ;
00056 }
00057
00058
00059
00060
00061 RooProduct::RooProduct() :
00062 _compRIter( _compRSet.createIterator() ),
00063 _compCIter( _compCSet.createIterator() )
00064 {
00065
00066 }
00067
00068
00069
00070
00071 RooProduct::~RooProduct()
00072 {
00073
00074
00075 if (_compRIter) {
00076 delete _compRIter ;
00077 }
00078
00079 if (_compCIter) {
00080 delete _compCIter ;
00081 }
00082 }
00083
00084
00085
00086
00087 RooProduct::RooProduct(const char* name, const char* title, const RooArgSet& prodSet) :
00088 RooAbsReal(name, title),
00089 _compRSet("!compRSet","Set of real product components",this),
00090 _compCSet("!compCSet","Set of category product components",this),
00091 _compRIter( _compRSet.createIterator() ),
00092 _compCIter( _compCSet.createIterator() ),
00093 _cacheMgr(this,10)
00094 {
00095
00096
00097 TIterator* compIter = prodSet.createIterator() ;
00098 RooAbsArg* comp ;
00099 while((comp = (RooAbsArg*)compIter->Next())) {
00100 if (dynamic_cast<RooAbsReal*>(comp)) {
00101 _compRSet.add(*comp) ;
00102 } else if (dynamic_cast<RooAbsCategory*>(comp)) {
00103 _compCSet.add(*comp) ;
00104 } else {
00105 coutE(InputArguments) << "RooProduct::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
00106 << " is not of type RooAbsReal or RooAbsCategory" << endl ;
00107 RooErrorHandler::softAbort() ;
00108 }
00109 }
00110 delete compIter ;
00111 }
00112
00113
00114
00115
00116 RooProduct::RooProduct(const RooProduct& other, const char* name) :
00117 RooAbsReal(other, name),
00118 _compRSet("!compRSet",this,other._compRSet),
00119 _compCSet("!compCSet",this,other._compCSet),
00120 _compRIter(_compRSet.createIterator()),
00121 _compCIter(_compCSet.createIterator()),
00122 _cacheMgr(other._cacheMgr,this)
00123 {
00124
00125 }
00126
00127
00128
00129
00130 Bool_t RooProduct::forceAnalyticalInt(const RooAbsArg& dep) const
00131 {
00132
00133
00134
00135 _compRIter->Reset() ;
00136 RooAbsReal* rcomp ;
00137 Bool_t depends(kFALSE);
00138 while((rcomp=(RooAbsReal*)_compRIter->Next())&&!depends) {
00139 depends = rcomp->dependsOn(dep);
00140 }
00141 return depends ;
00142 }
00143
00144
00145
00146
00147 RooProduct::ProdMap* RooProduct::groupProductTerms(const RooArgSet& allVars) const
00148 {
00149
00150
00151
00152 ProdMap* map = new ProdMap ;
00153
00154
00155
00156 RooAbsReal* rcomp ; _compRIter->Reset() ;
00157 RooArgSet *indep = new RooArgSet();
00158 while((rcomp=(RooAbsReal*)_compRIter->Next())) {
00159 if( !rcomp->dependsOn(allVars) ) indep->add(*rcomp);
00160 }
00161 if (indep->getSize()!=0) {
00162 map->push_back( std::make_pair(new RooArgSet(),indep) );
00163 }
00164
00165
00166 TIterator *allVarsIter = allVars.createIterator() ;
00167 RooAbsReal* var ;
00168 while((var=(RooAbsReal*)allVarsIter->Next())) {
00169 RooArgSet *vars = new RooArgSet(); vars->add(*var);
00170 RooArgSet *comps = new RooArgSet();
00171 RooAbsReal* rcomp2 ;
00172
00173 _compRIter->Reset() ;
00174 while((rcomp2=(RooAbsReal*)_compRIter->Next())) {
00175 if( rcomp2->dependsOn(*var) ) comps->add(*rcomp2);
00176 }
00177 map->push_back( std::make_pair(vars,comps) );
00178 }
00179 delete allVarsIter ;
00180
00181
00182 Bool_t overlap;
00183 do {
00184 std::pair<ProdMap::iterator,ProdMap::iterator> i = findOverlap2nd(map->begin(),map->end());
00185 overlap = (i.first!=i.second);
00186 if (overlap) {
00187 i.first->first->add(*i.second->first);
00188 i.first->second->add(*i.second->second);
00189 delete i.second->first;
00190 delete i.second->second;
00191 map->erase(i.second);
00192 }
00193 } while (overlap);
00194
00195
00196
00197 int nVar=0; int nFunc=0;
00198 for (ProdMap::iterator i = map->begin();i!=map->end();++i) {
00199 nVar+=i->first->getSize();
00200 nFunc+=i->second->getSize();
00201 }
00202 assert(nVar==allVars.getSize());
00203 assert(nFunc==_compRSet.getSize());
00204 return map;
00205 }
00206
00207
00208
00209
00210 Int_t RooProduct::getPartIntList(const RooArgSet* iset, const char *isetRange) const
00211 {
00212
00213
00214
00215
00216
00217
00218 Int_t sterileIndex(-1);
00219 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(iset,iset,&sterileIndex,RooNameReg::ptr(isetRange));
00220 if (cache!=0) {
00221 Int_t code = _cacheMgr.lastIndex();
00222 return code;
00223 }
00224
00225 ProdMap* map = groupProductTerms(*iset);
00226
00227 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") groupProductTerms returned map" ;
00228 if (dologD(Integration)) {
00229 dump_map(ccoutD(Integration),map->begin(),map->end());
00230 ccoutD(Integration) << endl;
00231 }
00232
00233
00234 if (map->size()<2) {
00235
00236 for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
00237 delete iter->first ;
00238 delete iter->second ;
00239 }
00240
00241 delete map ;
00242 return -1;
00243 }
00244 cache = new CacheElem();
00245
00246 for (ProdMap::const_iterator i = map->begin();i!=map->end();++i) {
00247 RooAbsReal *term(0);
00248 if (i->second->getSize()>1) {
00249 const char *name = makeFPName("SUBPROD_",*i->second);
00250 term = new RooProduct(name,name,*i->second);
00251 cache->_ownedList.addOwned(*term);
00252 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") created subexpression " << term->GetName() << endl;
00253 } else {
00254 assert(i->second->getSize()==1);
00255 auto_ptr<TIterator> j( i->second->createIterator() );
00256 term = (RooAbsReal*)j->Next();
00257 }
00258 assert(term!=0);
00259 if (i->first->getSize()==0) {
00260 cache->_prodList.add(*term);
00261 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") adding simple factor " << term->GetName() << endl;
00262 } else {
00263 RooAbsReal *integral = term->createIntegral(*i->first,isetRange);
00264 cache->_prodList.add(*integral);
00265 cache->_ownedList.addOwned(*integral);
00266 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") adding integral for " << term->GetName() << " : " << integral->GetName() << endl;
00267 }
00268 }
00269
00270 Int_t code = _cacheMgr.setObj(iset,iset,(RooAbsCacheElement*)cache,RooNameReg::ptr(isetRange));
00271
00272 cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") created list " << cache->_prodList << " with code " << code+1 << endl
00273 << " for iset=" << *iset << " @" << iset << " range: " << (isetRange?isetRange:"<none>") << endl ;
00274
00275 for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
00276 delete iter->first ;
00277 delete iter->second ;
00278 }
00279 delete map ;
00280 return code;
00281 }
00282
00283
00284
00285 Int_t RooProduct::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
00286 const RooArgSet* ,
00287 const char* rangeName) const
00288 {
00289
00290
00291 if (_forceNumInt) return 0 ;
00292
00293
00294
00295
00296 assert(analVars.getSize()==0);
00297 analVars.add(allVars) ;
00298 Int_t code = getPartIntList(&analVars,rangeName)+1;
00299 return code ;
00300 }
00301
00302
00303
00304 Double_t RooProduct::analyticalIntegral(Int_t code, const char* rangeName) const
00305 {
00306
00307
00308
00309 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
00310 if (cache==0) {
00311
00312 std::auto_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
00313 std::auto_ptr<RooArgSet> iset( _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
00314 Int_t code2 = getPartIntList(iset.get(),rangeName)+1;
00315 assert(code==code2);
00316 return analyticalIntegral(code2,rangeName);
00317 }
00318 assert(cache!=0);
00319
00320 return calculate(cache->_prodList);
00321 }
00322
00323
00324
00325 Double_t RooProduct::calculate(const RooArgList& partIntList) const
00326 {
00327
00328
00329 RooAbsReal *term(0);
00330 Double_t val=1;
00331 std::auto_ptr<TIterator> i( partIntList.createIterator() );
00332 while((term=(RooAbsReal*)i->Next())) {
00333 double x = term->getVal();
00334 val*= x;
00335 }
00336 return val;
00337 }
00338
00339
00340
00341 const char* RooProduct::makeFPName(const char *pfx,const RooArgSet& terms) const
00342 {
00343
00344
00345 static TString pname;
00346 pname = pfx;
00347 std::auto_ptr<TIterator> i( terms.createIterator() );
00348 RooAbsArg *arg;
00349 Bool_t first(kTRUE);
00350 while((arg=(RooAbsArg*)i->Next())) {
00351 if (first) { first=kFALSE;}
00352 else pname.Append("_X_");
00353 pname.Append(arg->GetName());
00354 }
00355 return pname.Data();
00356 }
00357
00358
00359
00360
00361 Double_t RooProduct::evaluate() const
00362 {
00363
00364
00365 Double_t prod(1) ;
00366
00367 _compRIter->Reset() ;
00368 RooAbsReal* rcomp ;
00369 const RooArgSet* nset = _compRSet.nset() ;
00370 while((rcomp=(RooAbsReal*)_compRIter->Next())) {
00371 prod *= rcomp->getVal(nset) ;
00372 }
00373
00374 _compCIter->Reset() ;
00375 RooAbsCategory* ccomp ;
00376 while((ccomp=(RooAbsCategory*)_compCIter->Next())) {
00377 prod *= ccomp->getIndex() ;
00378 }
00379
00380 return prod ;
00381 }
00382
00383
00384
00385 RooProduct::CacheElem::~CacheElem()
00386 {
00387
00388 }
00389
00390
00391
00392 RooArgList RooProduct::CacheElem::containedArgs(Action)
00393 {
00394
00395 RooArgList ret(_ownedList) ;
00396 return ret ;
00397 }
00398
00399
00400
00401
00402
00403 void RooProduct::printMetaArgs(ostream& os) const
00404 {
00405
00406
00407
00408 Bool_t first(kTRUE) ;
00409
00410 _compRIter->Reset() ;
00411 RooAbsReal* rcomp ;
00412 while((rcomp=(RooAbsReal*)_compRIter->Next())) {
00413 if (!first) { os << " * " ; } else { first = kFALSE ; }
00414 os << rcomp->GetName() ;
00415 }
00416
00417 _compCIter->Reset() ;
00418 RooAbsCategory* ccomp ;
00419 while((ccomp=(RooAbsCategory*)_compCIter->Next())) {
00420 if (!first) { os << " * " ; } else { first = kFALSE ; }
00421 os << ccomp->GetName() ;
00422 }
00423
00424 os << " " ;
00425 }
00426
00427
00428
00429
00430
00431 namespace {
00432
00433 std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end)
00434 {
00435
00436 for (; i!=end; ++i) for ( RPPMIter j(i+1); j!=end; ++j) {
00437 if (i->second->overlaps(*j->second)) {
00438 return std::make_pair(i,j);
00439 }
00440 }
00441 return std::make_pair(end,end);
00442 }
00443
00444
00445 void dump_map(ostream& os, RPPMIter i, RPPMIter end)
00446 {
00447
00448 Bool_t first(kTRUE);
00449 os << " [ " ;
00450 for(; i!=end;++i) {
00451 if (first) { first=kFALSE; }
00452 else { os << " , " ; }
00453 os << *(i->first) << " -> " << *(i->second) ;
00454 }
00455 os << " ] " ;
00456 }
00457
00458 }
00459
00460
00461
00462