RooProduct.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooProduct.cxx 36222 2010-10-09 18:27:06Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   GR, Gerhard Raven,   VU Amsterdan,     graven@nikhef.nl                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2007, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 //
00021 // RooProduct a RooAbsReal implementation that represent the product
00022 // of a given set of other RooAbsReal objects
00023 //
00024 // END_HTML
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 // Namespace with helper functions that have STL stuff that we don't want to expose to CINT
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   // Default constructor
00066 }
00067 
00068 
00069 
00070 //_____________________________________________________________________________
00071 RooProduct::~RooProduct()
00072 {
00073   // Destructor
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   // Construct function representing the product of functions in prodSet
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   // Copy constructor
00125 }
00126 
00127 
00128 
00129 //_____________________________________________________________________________
00130 Bool_t RooProduct::forceAnalyticalInt(const RooAbsArg& dep) const
00131 {
00132   // Force internal handling of integration of given observable if any
00133   // of the product terms depend on it.
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   // Group observables into subsets in which the product factorizes
00150   // and that can thus be integrated separately
00151 
00152   ProdMap* map = new ProdMap ;
00153 
00154   // Do we have any terms which do not depend on the
00155   // on the variables we integrate over?
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   // Map observables -> functions ; start with individual observables
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   // Merge groups with overlapping dependents
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   // check that we have all variables to be integrated over on the LHS
00196   // of the map, and all terms in the product do appear on the RHS
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   // Return list of (partial) integrals whose product defines the integral of this
00213   // RooProduct over the observables in iset in range isetRange. If no such list
00214   // exists, create it now and store it in the cache for future use.
00215 
00216 
00217   // check if we already have integrals for this combination of factors
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   // did we find any factorizable terms?
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; // RRI caller will zero analVars if return code = 0....
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) { // create a RooProd for this subexpression
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) { // check whether we need to integrate over this term or not...
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   // add current set-up to cache, and return index..
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* /*normSet*/,
00287                                           const char* rangeName) const
00288 {
00289   // Declare that we handle all integrations internally
00290 
00291   if (_forceNumInt) return 0 ;
00292 
00293   // Declare that we can analytically integrate all requested observables
00294   // (basically, we will take care of the problem, and delegate where required)
00295   //assert(normSet==0);
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   // Calculate integral internally from appropriate partial integral cache
00307 
00308   // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
00309   CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
00310   if (cache==0) { 
00311     // cache got sterilized, trigger repopulation of this slot, then try again...
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); // must have revived the right (sterilized) slot...
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   // Calculate and return product of partial terms in partIntList
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   // Construct automatic name for internal product terms
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   // Evaluate product of input functions
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   // Destructor
00388 }
00389 
00390 
00391 //_____________________________________________________________________________
00392 RooArgList RooProduct::CacheElem::containedArgs(Action) 
00393 {
00394   // Return list of all RooAbsArgs in cache element
00395   RooArgList ret(_ownedList) ;
00396   return ret ;
00397 }
00398 
00399 
00400 
00401 
00402 //_____________________________________________________________________________
00403 void RooProduct::printMetaArgs(ostream& os) const 
00404 {
00405   // Customized printing of arguments of a RooProduct to more intuitively reflect the contents of the
00406   // product operator construction
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   // Utility function finding pairs of overlapping input functions
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   // Utility dump function for debugging
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 

Generated on Tue Jul 5 15:07:07 2011 for ROOT_528-00b_version by  doxygen 1.5.1