Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TUnuran.cxx
Go to the documentation of this file.
1// @(#)root/unuran:$Id$
2// Authors: L. Moneta, J. Leydold Tue Sep 26 16:25:09 2006
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7 * *
8 * *
9 **********************************************************************/
10
11// Implementation file for class TUnuran
12
13#include "TUnuran.h"
14
15#include "TUnuranContDist.h"
17#include "TUnuranDiscrDist.h"
18#include "TUnuranEmpDist.h"
19
20#include "UnuranRng.h"
21#include "UnuranDistrAdapter.h"
22
23#include "TRandom.h"
24
25#include <cassert>
26
27#include <unuran.h>
28
29#include "TError.h"
30
31
32TUnuran::TUnuran(TRandom * r, unsigned int debugLevel) :
33 fGen(nullptr),
34 fUdistr(nullptr),
35 fUrng(nullptr),
36 fRng(r)
37{
38 // constructor implementation with a ROOT random generator
39 // if no generator is given the ROOT default is used
40 if (fRng == nullptr) fRng = gRandom;
41 // set debug level at global level
42 // (should be in a static initialization function of the library ? )
43 if ( debugLevel > 1)
44 unur_set_default_debug(UNUR_DEBUG_ALL);
45 else if (debugLevel == 1)
46 unur_set_default_debug(UNUR_DEBUG_INIT);
47 else
48 unur_set_default_debug(UNUR_DEBUG_OFF);
49
50}
51
52
54{
55 // Destructor implementation
56 if (fGen != nullptr) unur_free(fGen);
57 if (fUrng != nullptr) unur_urng_free(fUrng);
58 // we can delete now the distribution object
59 if (fUdistr != nullptr) unur_distr_free(fUdistr);
60}
61
62bool TUnuran::Init(const std::string & dist, const std::string & method)
63{
64 // initialize with a string
65 std::string s = dist + " & " + method;
66 fGen = unur_str2gen(s.c_str() );
67 if (fGen == nullptr) {
68 Error("Init","Cannot create generator object");
69 return false;
70 }
71 if (! SetRandomGenerator() ) return false;
72
73 return true;
74}
75
76bool TUnuran::Init(const TUnuranContDist & distr, const std::string & method)
77{
78 // initialization with a distribution and and generator
79 // the distribution object is copied in and managed by this class
80 // use std::unique_ptr to manage previously existing distribution objects
81 TUnuranContDist * distNew = distr.Clone();
82 fDist.reset(distNew);
83
84 fMethod = method;
85 if (! SetContDistribution(*distNew) ) return false;
86 if (! SetMethodAndInit() ) return false;
87 if (! SetRandomGenerator() ) return false;
88 return true;
89}
90
91
92bool TUnuran::Init(const TUnuranMultiContDist & distr, const std::string & method)
93{
94 // initialization with a distribution and method
95 // the distribution object is copied in and managed by this class
96 // use std::unique_ptr to manage previously existing distribution objects
97 TUnuranMultiContDist * distNew = distr.Clone();
98 fDist.reset(distNew);
99
100 fMethod = method;
101 if (! SetMultiDistribution(*distNew) ) return false;
102 if (! SetMethodAndInit() ) return false;
103 if (! SetRandomGenerator() ) return false;
104 return true;
105}
106
107
108bool TUnuran::Init(const TUnuranDiscrDist & distr, const std::string & method ) {
109 // initialization with a distribution and and generator
110 // the distribution object is copied in and managed by this class
111 // use std::unique_ptr to manage previously existing distribution objects
112 TUnuranDiscrDist * distNew = distr.Clone();
113 fDist.reset(distNew);
114
115 fMethod = method;
116 if (! SetDiscreteDistribution(*distNew) ) return false;
117 if (! SetMethodAndInit() ) return false;
118 if (! SetRandomGenerator() ) return false;
119 return true;
120}
121
122bool TUnuran::Init(const TUnuranEmpDist & distr, const std::string & method ) {
123 // initialization with a distribution and and generator
124 // the distribution object is copied in and managed by this class
125 // use std::unique_ptr to manage previously existing distribution objects
126 TUnuranEmpDist * distNew = distr.Clone();
127 fDist.reset(distNew);
128
129 fMethod = method;
130 if (distr.IsBinned()) fMethod = "hist";
131 else if (distr.NDim() > 1) fMethod = "vempk";
132 if (! SetEmpiricalDistribution(*distNew) ) return false;
133 if (! SetMethodAndInit() ) return false;
134 if (! SetRandomGenerator() ) return false;
135 return true;
136}
137
138
140{
141 // set an external random generator
142 if (fRng == nullptr) return false;
143 if (fGen == nullptr) return false;
144
145 fUrng = unur_urng_new(&UnuranRng<TRandom>::Rndm, fRng );
146 if (fUrng == nullptr) return false;
147 unsigned int ret = 0;
148 ret |= unur_urng_set_delete(fUrng, &UnuranRng<TRandom>::Delete);
149 ret |= unur_urng_set_seed(fUrng, &UnuranRng<TRandom>::Seed);
150 if (ret != 0) return false;
151
152 unur_chg_urng( fGen, fUrng);
153 return true;
154}
155
157{
158 // internal method to set in unuran the function pointer for a continuous univariate distribution
159 if (fUdistr != nullptr) unur_distr_free(fUdistr);
160 fUdistr = unur_distr_cont_new();
161 if (fUdistr == nullptr) return false;
162 unsigned int ret = 0;
163 ret = unur_distr_set_extobj(fUdistr, &dist);
164 if ( ! dist.IsLogPdf() ) {
165 ret |= unur_distr_cont_set_pdf(fUdistr, &ContDist::Pdf);
166 ret |= unur_distr_cont_set_dpdf(fUdistr, &ContDist::Dpdf);
167 if (dist.HasCdf() ) ret |= unur_distr_cont_set_cdf(fUdistr, &ContDist::Cdf);
168 }
169 else {
170 // case user provides log of pdf
171 ret |= unur_distr_cont_set_logpdf(fUdistr, &ContDist::Pdf);
172 ret |= unur_distr_cont_set_dlogpdf(fUdistr, &ContDist::Dpdf);
173 }
174
175 double xmin, xmax = 0;
176 if (dist.GetDomain(xmin,xmax) ) {
177 ret = unur_distr_cont_set_domain(fUdistr,xmin,xmax);
178 if (ret != 0) {
179 Error("SetContDistribution","invalid domain xmin = %g xmax = %g ",xmin,xmax);
180 return false;
181 }
182 }
183 if (dist.HasMode() ) {
184 ret = unur_distr_cont_set_mode(fUdistr, dist.Mode());
185 if (ret != 0) {
186 Error("SetContDistribution","invalid mode given, mode = %g ",dist.Mode());
187 return false;
188 }
189 }
190 if (dist.HasPdfArea() ) {
191 ret = unur_distr_cont_set_pdfarea(fUdistr, dist.PdfArea());
192 if (ret != 0) {
193 Error("SetContDistribution","invalid area given, area = %g ",dist.PdfArea());
194 return false;
195 }
196 }
197
198 return (ret ==0) ? true : false;
199}
200
201
203{
204 // internal method to set in unuran the function pointer for a multivariate distribution
205 if (fUdistr != nullptr) unur_distr_free(fUdistr);
206 fUdistr = unur_distr_cvec_new(dist.NDim() );
207 if (fUdistr == nullptr) return false;
208 unsigned int ret = 0;
209 ret |= unur_distr_set_extobj(fUdistr, &dist );
210 if ( ! dist.IsLogPdf() ) {
211 ret |= unur_distr_cvec_set_pdf(fUdistr, &MultiDist::Pdf);
212 ret |= unur_distr_cvec_set_dpdf(fUdistr, &MultiDist::Dpdf);
213 ret |= unur_distr_cvec_set_pdpdf(fUdistr, &MultiDist::Pdpdf);
214 }
215 else {
216 ret |= unur_distr_cvec_set_logpdf(fUdistr, &MultiDist::Pdf);
217 ret |= unur_distr_cvec_set_dlogpdf(fUdistr, &MultiDist::Dpdf);
218 ret |= unur_distr_cvec_set_pdlogpdf(fUdistr, &MultiDist::Pdpdf);
219 }
220
221 const double * xmin = dist.GetLowerDomain();
222 const double * xmax = dist.GetUpperDomain();
223 if ( xmin != nullptr || xmax != nullptr ) {
224 ret = unur_distr_cvec_set_domain_rect(fUdistr,xmin,xmax);
225 if (ret != 0) {
226 Error("SetMultiDistribution","invalid domain");
227 return false;
228 }
229#ifdef OLDVERS
230 Error("SetMultiDistribution","domain setting not available in UNURAN 0.8.1");
231#endif
232
233 }
234
235 const double * xmode = dist.GetMode();
236 if (xmode != nullptr) {
237 ret = unur_distr_cvec_set_mode(fUdistr, xmode);
238 if (ret != 0) {
239 Error("SetMultiDistribution","invalid mode");
240 return false;
241 }
242 }
243 return (ret ==0) ? true : false;
244}
245
247
248 // internal method to set in unuran the function pointer for am empiral distribution (from histogram)
249 if (fUdistr != nullptr) unur_distr_free(fUdistr);
250 if (dist.NDim() == 1)
251 fUdistr = unur_distr_cemp_new();
252 else
253 fUdistr = unur_distr_cvemp_new(dist.NDim() );
254
255 if (fUdistr == nullptr) return false;
256 unsigned int ret = 0;
257
258
259 // get info from histogram
260 if (dist.IsBinned() ) {
261 int nbins = dist.Data().size();
262 double min = dist.LowerBin();
263 double max = dist.UpperBin();
264 const double * pv = &(dist.Data().front());
265 ret |= unur_distr_cemp_set_hist(fUdistr, pv, nbins, min, max);
266#ifdef OLDVERS
267 Error("SetEmpiricalDistribution","hist method not available in UNURAN 0.8.1");
268#endif
269 }
270 else {
271 const double * pv = &dist.Data().front();
272 // n is number of points (size/ndim)
273 int n = dist.Data().size()/dist.NDim();
274 if (dist.NDim() == 1)
275 ret |= unur_distr_cemp_set_data(fUdistr, pv, n);
276 else
277 ret |= unur_distr_cvemp_set_data(fUdistr, pv, n);
278 }
279 if (ret != 0) {
280 Error("SetEmpiricalDistribution","invalid distribution object");
281 return false;
282 }
283 return true;
284}
285
286
288{
289 // internal method to set in unuran the function pointer for a discrete univariate distribution
290 if (fUdistr != nullptr) unur_distr_free(fUdistr);
291 fUdistr = unur_distr_discr_new();
292 if (fUdistr == nullptr) return false;
293 unsigned int ret = 0;
294 // if a probability mesh function is provided
295 if (dist.ProbVec().empty()) {
296 ret = unur_distr_set_extobj(fUdistr, &dist );
297 ret |= unur_distr_discr_set_pmf(fUdistr, &DiscrDist::Pmf);
298 if (dist.HasCdf() ) ret |= unur_distr_discr_set_cdf(fUdistr, &DiscrDist::Cdf);
299
300 }
301 else {
302 // case user provides vector of probabilities
303 ret |= unur_distr_discr_set_pv(fUdistr, &dist.ProbVec().front(), dist.ProbVec().size() );
304 }
305
306 int xmin, xmax = 0;
307 if (dist.GetDomain(xmin,xmax) ) {
308 ret = unur_distr_discr_set_domain(fUdistr,xmin,xmax);
309 if (ret != 0) {
310 Error("SetDiscrDistribution","invalid domain xmin = %d xmax = %d ",xmin,xmax);
311 return false;
312 }
313 }
314 if (dist.HasMode() ) {
315 ret = unur_distr_discr_set_mode(fUdistr, dist.Mode());
316 if (ret != 0) {
317 Error("SetContDistribution","invalid mode given, mode = %d ",dist.Mode());
318 return false;
319 }
320 }
321 if (dist.HasProbSum() ) {
322 ret = unur_distr_discr_set_pmfsum(fUdistr, dist.ProbSum());
323 if (ret != 0) {
324 Error("SetContDistribution","invalid sum given, mode = %g ",dist.ProbSum());
325 return false;
326 }
327 }
328
329 return (ret ==0) ? true : false;
330}
331
333
334 // internal function to set a method from a distribution and
335 // initialize unuran with the given distribution.
336 if (fUdistr == nullptr) return false;
337
338 struct unur_slist *mlist = nullptr;
339
340 UNUR_PAR * par = _unur_str2par(fUdistr, fMethod.c_str(), &mlist);
341 if (par == nullptr) {
342 Error("SetMethod","missing distribution information or syntax error");
343 if (mlist != nullptr) _unur_slist_free(mlist);
344 return false;
345 }
346
347
348 // set unuran to not use a private copy of the distribution object
349 unur_set_use_distr_privatecopy (par, false);
350
351 // need to free fGen if already existing ?
352 if (fGen != nullptr ) unur_free(fGen);
353 fGen = unur_init(par);
354 _unur_slist_free(mlist);
355 if (fGen == nullptr) {
356 Error("SetMethod","initializing Unuran: condition for method violated");
357 return false;
358 }
359 return true;
360 }
361
362std::string TUnuran::GetInfo(bool extended)
363{
364 // get information string about Unuran generator
365 if (!fGen) return std::string();
366 return std::string(unur_gen_info(fGen, extended));
367}
368
369std::string TUnuran::GetGenId() const
370{
371 // get Unuran generator ID
372 if (!fGen) return std::string();
373 return std::string(unur_get_genid(fGen));
374}
375
377{
378 // get dimension of the UNURAN generator
379 if (!fGen) return 0;
380 return unur_get_dimension(fGen);
381}
382
384{
385 // get type of distribution
386 if (!fGen) return -1;
387 return unur_distr_get_type (unur_get_distr(fGen));
388}
389
391 if (!fGen) return false;
392 return unur_distr_is_cont (unur_get_distr(fGen));
393}
395 if (!fGen) return false;
396 return unur_distr_is_cvec (unur_get_distr(fGen));
397}
399 if (!fGen) return false;
400 return unur_distr_is_discr (unur_get_distr(fGen));
401}
403 if (!fGen) return false;
404 return unur_distr_is_cemp (unur_get_distr(fGen));
405}
406
408{
409 // sample one-dimensional distribution
410 assert(fGen != nullptr);
411 return unur_sample_discr(fGen);
412}
413
415{
416 // sample one-dimensional distribution
417 assert(fGen != nullptr);
418 return unur_sample_cont(fGen);
419}
420
422{
423 // sample multidimensional distribution
424 if (fGen == nullptr) return false;
425 unur_sample_vec(fGen,x);
426 return true;
427}
428
429void TUnuran::SetSeed(unsigned int seed) {
430 return fRng->SetSeed(seed);
431}
432
433bool TUnuran::SetLogLevel(unsigned int debugLevel)
434{
435 if (fGen == nullptr) return false;
436 int ret = 0;
437 if ( debugLevel > 1)
438 ret |= unur_chg_debug(fGen, UNUR_DEBUG_ALL);
439 else if (debugLevel == 1)
440 ret |= unur_chg_debug(fGen, UNUR_DEBUG_ALL);
441 else
442 ret |= unur_chg_debug(fGen, UNUR_DEBUG_OFF);
443
444 return (ret ==0) ? true : false;
445
446}
447
448bool TUnuran::InitPoisson(double mu, const std::string & method) {
449 // initialization for a Poisson
450 double p[1];
451 p[0] = mu;
452
453 fUdistr = unur_distr_poisson(p,1);
454
455 fMethod = method;
456 if (fUdistr == nullptr) return false;
457 if (! SetMethodAndInit() ) return false;
458 if (! SetRandomGenerator() ) return false;
459 return true;
460}
461
462bool TUnuran::InitBinomial(unsigned int ntot, double prob, const std::string & method ) {
463 // initialization for a Binomial
464 double par[2];
465 par[0] = ntot;
466 par[1] = prob;
467 fUdistr = unur_distr_binomial(par,2);
468
469 fMethod = method;
470 if (fUdistr == nullptr) return false;
471 if (! SetMethodAndInit() ) return false;
472 if (! SetRandomGenerator() ) return false;
473 return true;
474}
475
476
477bool TUnuran::ReInitDiscrDist(unsigned int npar, double * par) {
478 // re-initialization of UNURAN without freeing and creating a new fGen object
479 // works only for pre-defined distribution by changing their parameters
480 if (!fGen ) return false;
481 if (!fUdistr) return false;
482 unur_distr_discr_set_pmfparams(fUdistr,par,npar);
483 int iret = unur_reinit(fGen);
484 if (iret) Warning("ReInitDiscrDist","re-init failed - a full initizialization must be performed");
485 return (!iret);
486}
487
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
winID h TVirtualViewer3D TVirtualGLPainter p
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
float xmin
float xmax
R__EXTERN TRandom * gRandom
Definition TRandom.h:62
This is the base class for the ROOT Random number generators.
Definition TRandom.h:27
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition TRandom.cxx:615
TUnuranContDist class describing one dimensional continuous distribution.
TUnuranContDist * Clone() const override
Clone (required by base class)
TUnuranDiscrDist class for one dimensional discrete distribution.
TUnuranDiscrDist * Clone() const override
Clone (required by base class)
TUnuranEmpDist class for describing empirical distributions.
unsigned int NDim() const
Number of data dimensions.
TUnuranEmpDist * Clone() const override
Clone (required by base class)
bool IsBinned() const
Flag to control if data are binned.
TUnuranMultiContDist class describing multi dimensional continuous distributions.
TUnuranMultiContDist * Clone() const override
Clone (required by base class)
std::string GetGenId() const
Return an ID string about the unuran generator method.
Definition TUnuran.cxx:369
bool IsDistCont() const
Return true for a univariate continuous distribution.
Definition TUnuran.cxx:390
bool SetMethodAndInit()
change the method and initialize Unuran with the previously given distribution
Definition TUnuran.cxx:332
int SampleDiscr()
Sample discrete distributions.
Definition TUnuran.cxx:407
std::unique_ptr< TUnuranBaseDist > fDist
Definition TUnuran.h:308
bool SetDiscreteDistribution(const TUnuranDiscrDist &dist)
Definition TUnuran.cxx:287
int GetDistType() const
Return the type of the distribution.
Definition TUnuran.cxx:383
bool InitBinomial(unsigned int ntot, double prob, const std::string &method="dstd")
Initialize method for the Binomial distribution.
Definition TUnuran.cxx:462
bool SetContDistribution(const TUnuranContDist &dist)
Definition TUnuran.cxx:156
std::string GetInfo(bool extended=false)
Return an information string about the used Unuran generator method.
Definition TUnuran.cxx:362
bool SampleMulti(double *x)
Sample multidimensional distributions.
Definition TUnuran.cxx:421
bool ReInitDiscrDist(unsigned int npar, double *params)
Reinitialize UNURAN by changing the distribution parameters but maintaining same distribution and met...
Definition TUnuran.cxx:477
TUnuran(TRandom *r=nullptr, unsigned int log=0)
Constructor with a generator instance and given level of log output.
Definition TUnuran.cxx:32
bool IsDistMultiCont() const
Return true for a multivariate continuous distribution.
Definition TUnuran.cxx:394
UNUR_DISTR * fUdistr
Definition TUnuran.h:306
bool Init(const std::string &distr, const std::string &method)
Initialize with Unuran string API interface.
Definition TUnuran.cxx:62
UNUR_GEN * fGen
Definition TUnuran.h:305
bool SetRandomGenerator()
Definition TUnuran.cxx:139
bool SetLogLevel(unsigned int iflag=1)
set log level
Definition TUnuran.cxx:433
UNUR_URNG * fUrng
Definition TUnuran.h:307
TRandom * fRng
Definition TUnuran.h:309
bool SetMultiDistribution(const TUnuranMultiContDist &dist)
Definition TUnuran.cxx:202
bool IsDistEmpirical() const
Return true for an empirical distribution.
Definition TUnuran.cxx:402
double Sample()
Sample 1D distribution.
Definition TUnuran.cxx:414
bool SetEmpiricalDistribution(const TUnuranEmpDist &dist)
Definition TUnuran.cxx:246
~TUnuran()
Destructor.
Definition TUnuran.cxx:53
bool InitPoisson(double mu, const std::string &method="dstd")
Initialize method for the Poisson distribution.
Definition TUnuran.cxx:448
std::string fMethod
Definition TUnuran.h:310
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
bool IsDistDiscrete() const
Return true for a discrete distribution.
Definition TUnuran.cxx:398
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
static double Cdf(double x, const UNUR_DISTR *dist)
evaluate the Cumulative distribution function, integral of the pdf
static double Pdf(double x, const UNUR_DISTR *dist)
evaluate the probality density function
static double Dpdf(double x, const UNUR_DISTR *dist)
evaluate the derivative of the pdf
static double Pmf(int x, const UNUR_DISTR *dist)
evaluate the probality mesh function
static double Cdf(int x, const UNUR_DISTR *dist)
evaluate the cumulative function
static double Pdf(const double *x, UNUR_DISTR *dist)
evaluate the probality density function
static int Dpdf(double *grad, const double *x, UNUR_DISTR *dist)
static double Pdpdf(const double *x, int coord, UNUR_DISTR *dist)
UnuranRng class for interface ROOT random generators to Unuran.
Definition UnuranRng.h:22