Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TUnuranSampler.cxx
Go to the documentation of this file.
1// @(#)root/unuran:$Id$
2// Authors: L. Moneta, J. Leydold Wed Feb 28 2007
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2010 LCG ROOT Math Team, CERN/PH-SFT *
7 * *
8 * *
9 **********************************************************************/
10
11// Implementation file for class TUnuranSampler
12#include "TUnuranSampler.h"
13
14#include "TUnuranContDist.h"
15#include "TUnuranDiscrDist.h"
17#include "TUnuran.h"
20#include "Math/GenAlgoOptions.h"
21#include "Fit/DataRange.h"
22//#include "Math/WrappedTF1.h"
23
24#include "TRandom.h"
25#include "TError.h"
26
27#include "TF1.h"
28#include <cassert>
29#include <cmath>
30
31
33 fOneDim(false),
34 fDiscrete(false),
35 fHasMode(false), fHasArea(false),
36 fMode(0), fArea(0),
37 fUnuran(new TUnuran() )
38{
40}
41
43 assert(fUnuran != nullptr);
44 delete fUnuran;
45}
46
47bool TUnuranSampler::Init(const char * algo) {
48 // initialize unuran classes using the given algorithm
49 assert (fUnuran != nullptr );
50 bool ret = false;
51 //case distribution has not been set
52 // Maybe we are using the Unuran string API which contains also distribution string
53 // try to initialize Unuran
54 if (NDim() == 0) {
55 ret = fUnuran->Init(algo,"");
56 if (!ret) {
57 Error("TUnuranSampler::Init",
58 "Unuran initialization string is invalid or the Distribution function has not been set and one needs to call SetFunction first.");
59 return false;
60 }
61 int ndim = fUnuran->GetDimension();
62 assert(ndim > 0);
63 fOneDim = (ndim == 1);
65 DoSetDimension(ndim);
66 return true;
67 }
68
70
72 if (method.IsNull() ) {
75 }
76 method.ToUpper();
77
78 if (NDim() == 1) {
79 // check if distribution is discrete by
80 // using first string in the method name is "D"
81 if (method.First("D") == 0) {
82 if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim discrete distribution with method %s",method.Data());
84 }
85 else {
86 if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim continuous distribution with method %s",method.Data());
88 }
89 }
90 else {
91 if (fLevel>1) Info("TUnuranSampler::Init","Initialize multi-dim continuous distribution with method %s",method.Data());
93 }
94 // set print level in UNURAN (must be done after having initialized) -
95 if (fLevel>0) {
96 //fUnuran->SetLogLevel(fLevel); ( seems not to work disable for the time being)
97 if (ret) Info("TUnuranSampler::Init","Successfully initialize Unuran with method %s",method.Data() );
98 else Error("TUnuranSampler::Init","Failed to initialize Unuran with method %s",method.Data() );
99 // seems not to work in UNURAN (call only when level > 0 )
100 }
101 return ret;
102}
103
104
106 // default initialization with algorithm name
108 // check if there are extra options
109 std::string optionStr = opt.Algorithm();
110 auto extraOpts = opt.ExtraOptions();
111 if (extraOpts) {
113 auto appendOption = [&](const std::string & key, const std::string & val) {
114 optionStr += "; ";
115 optionStr += key;
116 if (!val.empty()) {
117 optionStr += "=";
118 optionStr += val;
119 }
120 };
121 auto names = opts->GetAllNamedKeys();
122 for ( auto & name : names) {
123 std::string value = opts->NamedValue(name.c_str());
125 }
126 names = opts->GetAllIntKeys();
127 for ( auto & name : names) {
128 std::string value = ROOT::Math::Util::ToString(opts->IValue(name.c_str()));
130 }
131 names = opts->GetAllRealKeys();
132 for ( auto & name : names) {
133 std::string value = ROOT::Math::Util::ToString(opts->RValue(name.c_str()));
135 }
136 }
137 Info("Init","Initialize UNU.RAN with Method option string: %s",optionStr.c_str());
138 return Init(optionStr.c_str() );
139}
140
141
143 // initialize for 1D sampling
144 // need to create 1D interface from Multidim one
145 // (to do: use directly 1D functions ??)
146 // to do : add possibility for String API of UNURAN
147 fOneDim = true;
148 TUnuranContDist * dist = nullptr;
149 if (fFunc1D == nullptr) {
150 if (HasParentPdf()) {
152 dist = new TUnuranContDist(&function,fDPDF,fCDF,fUseLogPdf,true);
153 }
154 else {
155 if (!fDPDF && !fCDF) {
156 Error("DoInit1D", "No PDF, CDF or DPDF function has been set");
157 return false;
158 }
159 dist = new TUnuranContDist(nullptr, fDPDF, fCDF, fUseLogPdf, true);
160 }
161 }
162 else {
163 dist = new TUnuranContDist(fFunc1D, fDPDF, fCDF, fUseLogPdf, true); // no need to copy the function
164 }
165 // set range in distribution (support only one range)
167 if (range.Size(0) > 0) {
168 double xmin, xmax;
169 range.GetRange(0,xmin,xmax);
170 dist->SetDomain(xmin,xmax);
171 }
172 if (fHasMode) dist->SetMode(fMode);
173 if (fHasArea) dist->SetPdfArea(fArea);
174
175 bool ret = false;
176 if (method) ret = fUnuran->Init(*dist, method);
177 else ret = fUnuran->Init(*dist);
178 delete dist;
179 return ret;
180}
181
183 // initialize for 1D sampling of discrete distributions
184 fOneDim = true;
185 fDiscrete = true;
186 TUnuranDiscrDist * dist = nullptr;
187 if (fFunc1D == nullptr) {
188 if (!HasParentPdf()) {
189 Error("DoInitDiscrete1D", "No PMF has been defined");
190 return false;
191 }
192 // need to copy the passed function pointer in this case
194 dist = new TUnuranDiscrDist(function,true);
195 }
196 else {
197 // no need to copy the function since fFunc1D is managed outside
198 dist = new TUnuranDiscrDist(*fFunc1D, false);
199 }
200 // set CDF if available
201 if (fCDF) dist->SetCdf(*fCDF);
202 // set range in distribution (support only one range)
203 // otherwise 0, inf is assumed
205 if (range.Size(0) > 0) {
206 double xmin, xmax;
207 range.GetRange(0,xmin,xmax);
208 if (xmin < 0) {
209 Warning("DoInitDiscrete1D","range starts from negative values - set minimum to zero");
210 xmin = 0;
211 }
212 dist->SetDomain(int(xmin+0.1),int(xmax+0.1));
213 }
214 if (fHasMode) dist->SetMode(int(fMode+0.1));
215 if (fHasArea) dist->SetProbSum(fArea);
216
217 bool ret = fUnuran->Init(*dist, method);
218 delete dist;
219 return ret;
220}
221
222
224 // initialize for ND sampling
225 if (!HasParentPdf()) {
226 Error("DoInitND", "No PDF has been defined");
227 return false;
228 }
230 // set range in distribution (support only one range)
232 if (range.IsSet()) {
233 std::vector<double> xmin(range.NDim() );
234 std::vector<double> xmax(range.NDim() );
235 range.GetRange(&xmin[0],&xmax[0]);
236 dist.SetDomain(&xmin.front(),&xmax.front());
237 }
238 fOneDim = false;
239 if (fHasMode && fNDMode.size() == dist.NDim())
240 dist.SetMode(fNDMode.data());
241
242 if (method) return fUnuran->Init(dist, method);
243 return fUnuran->Init(dist);
244}
245
247 // set function from a TF1 pointer
248 SetFunction<TF1>(*pdf, pdf->GetNdim());
249}
250
252 // set random generator (must be called before Init to have effect)
254}
255
256void TUnuranSampler::SetSeed(unsigned int seed) {
257 // set random generator seed (must be called before Init to have effect)
258 fUnuran->SetSeed(seed);
259}
260
262 // get random generator used
263 return fUnuran->GetRandom();
264}
265
267 // sample 1D distributions
268 return (fDiscrete) ? (double) fUnuran->SampleDiscr() : fUnuran->Sample();
269}
270
271bool TUnuranSampler::Sample(double * x) {
272 // sample multi-dim distributions
273 if (!fOneDim) return fUnuran->SampleMulti(x);
274 x[0] = Sample1D();
275 return true;
276}
277
278
279bool TUnuranSampler::SampleBin(double prob, double & value, double *error) {
280 // sample a bin according to Poisson statistics
281 TRandom * r = fUnuran->GetRandom();
282 if (!r) return false;
283 value = r->Poisson(prob);
284 if (error) *error = std::sqrt(prob);
285 return true;
286}
287
288void TUnuranSampler::SetMode(const std::vector<double> &mode)
289{
290 // set modes for multidim distribution
291 if (mode.size() == ParentPdf().NDim()) {
292 if (mode.size() == 1)
293 fMode = mode[0];
294 else
295 fNDMode = mode;
296
297 fHasMode = true;
298 }
299 else {
300 Error("SetMode", "modes vector is not compatible with function dimension of %d", (int)ParentPdf().NDim());
301 fHasMode = false;
302 fNDMode.clear();
303 }
304}
305
307 fCDF = &cdf;
308 // in case dimension has not been defined ( a pdf is not provided)
309 if (NDim() == 0) DoSetDimension(1);
310}
311
313 fDPDF = &dpdf;
314 // in case dimension has not been defined ( a pdf is not provided)
315 if (NDim() == 0) DoSetDimension(1);
316}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char mode
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition DataRange.h:35
DistSampler options class.
int PrintLevel() const
non-static methods for retrieving options
const std::string & Algorithm() const
type of algorithm (method)
IOptions * ExtraOptions() const
return extra options (NULL pointer if they are not present)
static const std::string & DefaultAlgorithmND()
static const std::string & DefaultAlgorithm1D()
const double * Sample()
Sample one event and return an array x with sample coordinates values.
const ROOT::Math::IMultiGenFunction & ParentPdf() const
Get the parent distribution function (must be called after setting the function).
unsigned int NDim() const
return the dimension of the parent distribution (and the data)
Definition DistSampler.h:92
const ROOT::Fit::DataRange & PdfRange() const
return the data range of the Pdf . Must be called after setting the function
virtual void DoSetDimension(unsigned int ndim)
bool HasParentPdf() const
Check if there is a parent distribution defined.
class implementing generic options for a numerical algorithm Just store the options in a map of strin...
Interface (abstract class) for generic functions objects of one-dimension Provides a method to evalua...
Definition IFunction.h:157
OneDimMultiFunctionAdapter class to wrap a multidimensional function in one dimensional one.
1-Dim function class
Definition TF1.h:182
virtual Int_t GetNdim() const
Definition TF1.h:465
This is the base class for the ROOT Random number generators.
Definition TRandom.h:27
Basic string class.
Definition TString.h:138
TUnuranContDist class describing one dimensional continuous distribution.
TUnuranDiscrDist class for one dimensional discrete distribution.
TUnuranMultiContDist class describing multi dimensional continuous distributions.
const ROOT::Math::IGenFunction * fDPDF
1D Derivative function pointer
double fArea
area of dist
bool Init(const char *algo="") override
initialize the generators with the given algorithm If no algorithm is passed used the default one for...
const ROOT::Math::IGenFunction * fCDF
CDF function pointer.
void SetRandom(TRandom *r) override
Set the random engine to be used Needs to be called before Init to have effect.
void SetFunction(const ROOT::Math::IGenFunction &func) override
Set the parent function distribution to use for random sampling (one dim case).
TRandom * GetRandom() override
Get the random engine used by the sampler.
bool fHasMode
flag to indicate if a mode is set
bool fHasArea
flag to indicate if a area is set
void SetSeed(unsigned int seed) override
Set the random seed for the TRandom instances used by the sampler classes Needs to be called before I...
void SetPrintLevel(int level)
Set the print level (if level=-1 use default)
bool DoInitND(const char *algo)
Initialization for multi-dim distributions.
TUnuran * fUnuran
unuran engine class
const ROOT::Math::IGenFunction * fFunc1D
1D function pointer (pdf)
bool DoInit1D(const char *algo)
Initialization for 1D distributions.
void SetMode(double mode) override
Set the mode of the distribution (1D case).
bool fUseLogPdf
flag to indicate if we use the log of the PDF
double Sample1D() override
sample one event in one dimension better implementation could be provided by the derived classes
void SetDPdf(const ROOT::Math::IGenFunction &dpdf) override
set the Derivative of the PDF used for random sampling (one dim continuous case)
TUnuranSampler()
default constructor
bool fDiscrete
flag to indicate if the function is discrete
bool fOneDim
flag to indicate if the function is 1 dimension
void SetCdf(const ROOT::Math::IGenFunction &cdf) override
set the cumulative distribution function of the PDF used for random sampling (one dim case)
double fMode
mode of dist (1D)
std::vector< double > fNDMode
mode of the multi-dim distribution
int fLevel
debug level
~TUnuranSampler() override
virtual destructor
bool SampleBin(double prob, double &value, double *error=nullptr) override
sample one bin given an estimated of the pdf in the bin (this can be function value at the center or ...
bool DoInitDiscrete1D(const char *algo)
Initialization for 1D discrete distributions.
TUnuran class.
Definition TUnuran.h:79
int SampleDiscr()
Sample discrete distributions.
Definition TUnuran.cxx:407
bool SampleMulti(double *x)
Sample multidimensional distributions.
Definition TUnuran.cxx:421
bool Init(const std::string &distr, const std::string &method)
Initialize with Unuran string API interface.
Definition TUnuran.cxx:62
double Sample()
Sample 1D distribution.
Definition TUnuran.cxx:414
TRandom * GetRandom()
Return instance of the random engine used.
Definition TUnuran.h:223
int GetDimension() const
Return the dimension of unuran generator method.
Definition TUnuran.cxx:376
void SetSeed(unsigned int seed)
set the seed for the random number generator
Definition TUnuran.cxx:429
void SetRandom(TRandom *r)
Set the random engine.
Definition TUnuran.h:216
bool IsDistDiscrete() const
Return true for a discrete distribution.
Definition TUnuran.cxx:398
Double_t x[n]
Definition legend1.C:17
std::string ToString(const T &val)
Utility function for conversion to strings.
Definition Util.h:65