00001 // @(#)root/mathcore:$Id: DistSampler.h 37371 2010-12-07 16:26:39Z moneta $ 00002 // Author: L. Moneta Fri Sep 22 15:06:47 2006 00003 00004 /********************************************************************** 00005 * * 00006 * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT * 00007 * * 00008 * * 00009 **********************************************************************/ 00010 00011 // Header file for class DistSampler 00012 00013 #ifndef ROOT_Math_DistSampler 00014 #define ROOT_Math_DistSampler 00015 00016 #ifndef ROOT_Math_IFunctionfwd 00017 #include "Math/IFunctionfwd.h" 00018 #endif 00019 00020 #ifndef ROOT_Math_WrappedFunction 00021 #include "Math/WrappedFunction.h" 00022 #endif 00023 00024 #include <vector> 00025 #include <cassert> 00026 00027 class TRandom; 00028 00029 namespace ROOT { 00030 00031 namespace Fit { 00032 00033 class DataRange; 00034 class BinData; 00035 class UnBinData; 00036 } 00037 00038 namespace Math { 00039 00040 class DistSamplerOptions; 00041 00042 /** 00043 @defgroup Random Random number generators and generation of random number distributions 00044 @ingroup Random 00045 00046 Classes implementing random number generators and classes implementing generation of random numbers 00047 according to arbitrary distributions 00048 */ 00049 00050 //_______________________________________________________________________________ 00051 /** 00052 Interface class for generic sampling of a distribution, 00053 i.e. generating random numbers according to arbitrary distributions 00054 00055 @ingroup Random 00056 */ 00057 00058 00059 class DistSampler { 00060 00061 public: 00062 00063 /// default constructor 00064 DistSampler() : fOwnFunc(false), fRange(0), fFunc(0) {} 00065 00066 00067 /// virtual destructor 00068 virtual ~DistSampler(); 00069 00070 00071 00072 /// set the parent function distribution to use for sampling (generic case) 00073 template<class Function> 00074 void SetFunction(Function & func, unsigned int dim) { 00075 WrappedMultiFunction<Function &> wf(func, dim); 00076 fData.resize(dim); 00077 // need to clone to avoid temporary 00078 DoSetFunction(wf,true); 00079 } 00080 00081 /// set the parent function distribution to use for random sampling (one dim case) 00082 virtual void SetFunction(const ROOT::Math::IGenFunction & func) { 00083 SetFunction<const ROOT::Math::IGenFunction>(func, 1); 00084 } 00085 00086 00087 /// set the parent function distribution to use for random sampling (multi-dim case) 00088 virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func) { 00089 DoSetFunction(func,false); 00090 } 00091 00092 /// return the dimension of the parent distribution (and the data) 00093 unsigned int NDim() const { return fData.size(); } 00094 00095 00096 /** 00097 initialize the generators with the given algorithm 00098 Implemented by derived classes who needs it 00099 (like UnuranSampler) 00100 If nothing is specified use default algorithm 00101 from DistSamplerOptions::SetDefaultAlgorithm 00102 */ 00103 virtual bool Init(const char * =""/* algorithm */) { return true;} 00104 00105 /** 00106 initialize the generators with the given option 00107 which my include the algorithm but also more if 00108 the method is re-impelmented by derived class 00109 The default implementation calls the above method 00110 passing just the algorithm name 00111 */ 00112 virtual bool Init(const DistSamplerOptions & opt ); 00113 00114 00115 /** 00116 Set the random engine to be used 00117 To be implemented by the derived classes who provides 00118 random sampling 00119 */ 00120 virtual void SetRandom(TRandom * ) {} 00121 00122 /** 00123 Set the random seed for the TRandom instances used by the sampler 00124 classes 00125 To be implemented by the derived classes who provides random sampling 00126 */ 00127 virtual void SetSeed(unsigned int /*seed*/ ) {} 00128 00129 /** 00130 Get the random engine used by the sampler 00131 To be implemented by the derived classes who needs it 00132 Returns zero by default 00133 */ 00134 virtual TRandom * GetRandom() { return 0; } 00135 00136 /// set range in a given dimension 00137 void SetRange(double xmin, double xmax, int icoord = 0); 00138 00139 /// set range for all dimensions 00140 void SetRange(const double * xmin, const double * xmax); 00141 00142 /// set range using DataRange class 00143 void SetRange(const ROOT::Fit::DataRange & range); 00144 00145 /// set the mode of the distribution (could be useful to some methods) 00146 /// implemented by derived classes if needed 00147 virtual void SetMode(double ) {} 00148 00149 /// set the normalization area of distribution 00150 /// implemented by derived classes if needed 00151 virtual void SetArea(double) {} 00152 00153 /// get the parent distribution function (must be called after setting the function) 00154 const ROOT::Math::IMultiGenFunction & ParentPdf() const { 00155 return *fFunc; 00156 } 00157 00158 00159 /** 00160 sample one event in one dimension 00161 better implementation could be provided by the derived classes 00162 */ 00163 virtual double Sample1D() { 00164 Sample(&fData[0]); 00165 return fData[0]; 00166 } 00167 00168 /** 00169 sample one event and rerturning array x with coordinates 00170 */ 00171 const double * Sample() { 00172 Sample(&fData[0]); 00173 return &fData.front(); 00174 } 00175 00176 /** 00177 sample one event in multi-dimension by filling the given array 00178 return false if sampling failed 00179 */ 00180 virtual bool Sample(double * x) = 0; 00181 00182 /** 00183 sample one bin given an estimated of the pdf in the bin 00184 (this can be function value at the center or its integral in the bin 00185 divided by the bin width) 00186 By default do not do random sample, just return the function values 00187 Typically Poisson statistics will be used 00188 */ 00189 virtual bool SampleBin(double prob, double & value, double * error = 0) { 00190 value = prob; 00191 if (error) *error = 0; 00192 return true; 00193 } 00194 /** 00195 sample a set of bins given a vector of probabilities 00196 Typically multinomial statistics will be used and the sum of the probabilities 00197 will be equal to the total number of events to be generated 00198 For sampling the bins indipendently, SampleBin should be used 00199 */ 00200 virtual bool SampleBins(unsigned int n, const double * prob, double * values, double * errors = 0) { 00201 std::copy(prob,prob+n, values); 00202 if (errors) std::fill(errors,errors+n,0); 00203 return true; 00204 } 00205 00206 00207 /** 00208 generate a un-binned data sets (fill the given data set) 00209 if dataset has already data append to it 00210 */ 00211 virtual bool Generate(unsigned int nevt, ROOT::Fit::UnBinData & data); 00212 00213 00214 /** 00215 generate a bin data set . 00216 A range must have been set before (otherwise inf is returned) 00217 and the bins are equidinstant in the previously defined range 00218 bin center values must be present in given data set 00219 If the sampler is implemented by a random one, the entries 00220 will be binned according to the Poisson distribution 00221 It is assumed the distribution is normalized, otherwise the nevt must be scaled 00222 accordingly. The expected value/bin nexp = f(x_i) * binArea/ nevt 00223 Extend control if use a fixed (i.e. multinomial statistics) or floating total number of events 00224 */ 00225 virtual bool Generate(unsigned int nevt, const int * nbins, ROOT::Fit::BinData & data, bool extend = true); 00226 /** 00227 same as before but passing the range in case of 1 dim data 00228 */ 00229 bool Generate(unsigned int nevt, int nbins, double xmin, double xmax, ROOT::Fit::BinData & data, bool extend = true) { 00230 SetRange(xmin,xmax); 00231 int nbs[1]; nbs[0] = nbins; 00232 return Generate(nevt, nbs, data, extend); 00233 } 00234 00235 00236 protected: 00237 00238 // internal method to set the function 00239 virtual void DoSetFunction(const ROOT::Math::IMultiGenFunction & func, bool copy); 00240 // check if generator have been initialized correctly and one can start generating 00241 bool IsInitialized() ; 00242 /// return the data range of the Pdf . Must be called after setting the function 00243 const ROOT::Fit::DataRange & PdfRange() const { 00244 assert(fRange); 00245 return *fRange; 00246 } 00247 00248 00249 00250 00251 private: 00252 00253 // private methods 00254 00255 bool fOwnFunc; // flag to indicate if the function is owned 00256 mutable std::vector<double> fData; // internal array used to cached the sample data 00257 ROOT::Fit::DataRange * fRange; // data range 00258 const ROOT::Math::IMultiGenFunction * fFunc; // internal function (ND) 00259 00260 00261 }; 00262 00263 } // end namespace Math 00264 00265 } // end namespace ROOT 00266 00267 00268 #endif /* ROOT_Math_DistSampler */