00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "TUnuran.h"
00014
00015 #include "TUnuranContDist.h"
00016 #include "TUnuranMultiContDist.h"
00017 #include "TUnuranDiscrDist.h"
00018 #include "TUnuranEmpDist.h"
00019
00020 #include "UnuranRng.h"
00021 #include "UnuranDistrAdapter.h"
00022
00023 #include "TRandom.h"
00024 #include "TSystem.h"
00025
00026 #include "TH1.h"
00027
00028 #include <cassert>
00029
00030
00031 #include <unuran.h>
00032
00033 #include "TError.h"
00034
00035
00036 TUnuran::TUnuran(TRandom * r, unsigned int debugLevel) :
00037 fGen(0),
00038 fUdistr(0),
00039 fUrng(0),
00040 fRng(r)
00041 {
00042
00043
00044 if (fRng == 0) fRng = gRandom;
00045
00046
00047 if ( debugLevel > 1)
00048 unur_set_default_debug(UNUR_DEBUG_ALL);
00049 else if (debugLevel == 1)
00050 unur_set_default_debug(UNUR_DEBUG_INIT);
00051 else
00052 unur_set_default_debug(UNUR_DEBUG_OFF);
00053
00054 }
00055
00056
00057 TUnuran::~TUnuran()
00058 {
00059
00060 if (fGen != 0) unur_free(fGen);
00061 if (fUrng != 0) unur_urng_free(fUrng);
00062
00063 if (fUdistr != 0) unur_distr_free(fUdistr);
00064 }
00065
00066
00067 TUnuran::TUnuran(const TUnuran &)
00068 {
00069
00070 }
00071
00072 TUnuran & TUnuran::operator = (const TUnuran &rhs)
00073 {
00074
00075 if (this == &rhs) return *this;
00076 return *this;
00077 }
00078
00079 bool TUnuran::Init(const std::string & dist, const std::string & method)
00080 {
00081
00082 std::string s = dist + " & " + method;
00083 fGen = unur_str2gen(s.c_str() );
00084 if (fGen == 0) {
00085 Error("Init","Cannot create generator object");
00086 return false;
00087 }
00088 if (! SetRandomGenerator() ) return false;
00089
00090 return true;
00091 }
00092
00093 bool TUnuran::Init(const TUnuranContDist & distr, const std::string & method)
00094 {
00095
00096
00097
00098 TUnuranContDist * distNew = distr.Clone();
00099 fDist = std::auto_ptr< TUnuranBaseDist>(distNew);
00100
00101 fMethod = method;
00102 if (! SetContDistribution(*distNew) ) return false;
00103 if (! SetMethodAndInit() ) return false;
00104 if (! SetRandomGenerator() ) return false;
00105 return true;
00106 }
00107
00108
00109 bool TUnuran::Init(const TUnuranMultiContDist & distr, const std::string & method)
00110 {
00111
00112
00113
00114 TUnuranMultiContDist * distNew = distr.Clone();
00115 fDist = std::auto_ptr< TUnuranBaseDist>(distNew);
00116
00117 fMethod = method;
00118 if (! SetMultiDistribution(*distNew) ) return false;
00119 if (! SetMethodAndInit() ) return false;
00120 if (! SetRandomGenerator() ) return false;
00121 return true;
00122 }
00123
00124
00125 bool TUnuran::Init(const TUnuranDiscrDist & distr, const std::string & method ) {
00126
00127
00128
00129 TUnuranDiscrDist * distNew = distr.Clone();
00130 fDist = std::auto_ptr< TUnuranBaseDist>(distNew);
00131
00132 fMethod = method;
00133 if (! SetDiscreteDistribution(*distNew) ) return false;
00134 if (! SetMethodAndInit() ) return false;
00135 if (! SetRandomGenerator() ) return false;
00136 return true;
00137 }
00138
00139 bool TUnuran::Init(const TUnuranEmpDist & distr, const std::string & method ) {
00140
00141
00142
00143 TUnuranEmpDist * distNew = distr.Clone();
00144 fDist = std::auto_ptr< TUnuranBaseDist>(distNew);
00145
00146 fMethod = method;
00147 if (distr.IsBinned()) fMethod = "hist";
00148 else if (distr.NDim() > 1) fMethod = "vempk";
00149 if (! SetEmpiricalDistribution(*distNew) ) return false;
00150 if (! SetMethodAndInit() ) return false;
00151 if (! SetRandomGenerator() ) return false;
00152 return true;
00153 }
00154
00155
00156 bool TUnuran::SetRandomGenerator()
00157 {
00158
00159 if (fRng == 0) return false;
00160 if (fGen == 0) return false;
00161
00162 fUrng = unur_urng_new(&UnuranRng<TRandom>::Rndm, fRng );
00163 if (fUrng == 0) return false;
00164 unsigned int ret = 0;
00165 ret |= unur_urng_set_delete(fUrng, &UnuranRng<TRandom>::Delete);
00166 ret |= unur_urng_set_seed(fUrng, &UnuranRng<TRandom>::Seed);
00167 if (ret != 0) return false;
00168
00169 unur_chg_urng( fGen, fUrng);
00170 return true;
00171 }
00172
00173 bool TUnuran::SetContDistribution(const TUnuranContDist & dist )
00174 {
00175
00176 if (fUdistr != 0) unur_distr_free(fUdistr);
00177 fUdistr = unur_distr_cont_new();
00178 if (fUdistr == 0) return false;
00179 unsigned int ret = 0;
00180 ret = unur_distr_set_extobj(fUdistr, &dist);
00181 if ( ! dist.IsLogPdf() ) {
00182 ret |= unur_distr_cont_set_pdf(fUdistr, &ContDist::Pdf);
00183 ret |= unur_distr_cont_set_dpdf(fUdistr, &ContDist::Dpdf);
00184 if (dist.HasCdf() ) ret |= unur_distr_cont_set_cdf(fUdistr, &ContDist::Cdf);
00185 }
00186 else {
00187
00188 ret |= unur_distr_cont_set_logpdf(fUdistr, &ContDist::Pdf);
00189 ret |= unur_distr_cont_set_dlogpdf(fUdistr, &ContDist::Dpdf);
00190 }
00191
00192 double xmin, xmax = 0;
00193 if (dist.GetDomain(xmin,xmax) ) {
00194 ret = unur_distr_cont_set_domain(fUdistr,xmin,xmax);
00195 if (ret != 0) {
00196 Error("SetContDistribution","invalid domain xmin = %g xmax = %g ",xmin,xmax);
00197 return false;
00198 }
00199 }
00200 if (dist.HasMode() ) {
00201 ret = unur_distr_cont_set_mode(fUdistr, dist.Mode());
00202 if (ret != 0) {
00203 Error("SetContDistribution","invalid mode given, mode = %g ",dist.Mode());
00204 return false;
00205 }
00206 }
00207 if (dist.HasPdfArea() ) {
00208 ret = unur_distr_cont_set_pdfarea(fUdistr, dist.PdfArea());
00209 if (ret != 0) {
00210 Error("SetContDistribution","invalid area given, area = %g ",dist.PdfArea());
00211 return false;
00212 }
00213 }
00214
00215 return (ret ==0) ? true : false;
00216 }
00217
00218
00219 bool TUnuran::SetMultiDistribution(const TUnuranMultiContDist & dist )
00220 {
00221
00222 if (fUdistr != 0) unur_distr_free(fUdistr);
00223 fUdistr = unur_distr_cvec_new(dist.NDim() );
00224 if (fUdistr == 0) return false;
00225 unsigned int ret = 0;
00226 ret |= unur_distr_set_extobj(fUdistr, &dist );
00227 if ( ! dist.IsLogPdf() ) {
00228 ret |= unur_distr_cvec_set_pdf(fUdistr, &MultiDist::Pdf);
00229 ret |= unur_distr_cvec_set_dpdf(fUdistr, &MultiDist::Dpdf);
00230 ret |= unur_distr_cvec_set_pdpdf(fUdistr, &MultiDist::Pdpdf);
00231 }
00232 else {
00233 ret |= unur_distr_cvec_set_logpdf(fUdistr, &MultiDist::Pdf);
00234 ret |= unur_distr_cvec_set_dlogpdf(fUdistr, &MultiDist::Dpdf);
00235 ret |= unur_distr_cvec_set_pdlogpdf(fUdistr, &MultiDist::Pdpdf);
00236 }
00237
00238 const double * xmin = dist.GetLowerDomain();
00239 const double * xmax = dist.GetUpperDomain();
00240 if ( xmin != 0 || xmax != 0 ) {
00241 ret = unur_distr_cvec_set_domain_rect(fUdistr,xmin,xmax);
00242 if (ret != 0) {
00243 Error("SetMultiDistribution","invalid domain");
00244 return false;
00245 }
00246 #ifdef OLDVERS
00247 Error("SetMultiDistribution","domain setting not available in UNURAN 0.8.1");
00248 #endif
00249
00250 }
00251
00252 const double * xmode = dist.GetMode();
00253 if (xmode != 0) {
00254 ret = unur_distr_cvec_set_mode(fUdistr, xmode);
00255 if (ret != 0) {
00256 Error("SetMultiDistribution","invalid mode");
00257 return false;
00258 }
00259 }
00260 return (ret ==0) ? true : false;
00261 }
00262
00263 bool TUnuran::SetEmpiricalDistribution(const TUnuranEmpDist & dist) {
00264
00265
00266 if (fUdistr != 0) unur_distr_free(fUdistr);
00267 if (dist.NDim() == 1)
00268 fUdistr = unur_distr_cemp_new();
00269 else
00270 fUdistr = unur_distr_cvemp_new(dist.NDim() );
00271
00272 if (fUdistr == 0) return false;
00273 unsigned int ret = 0;
00274
00275
00276
00277 if (dist.IsBinned() ) {
00278 int nbins = dist.Data().size();
00279 double min = dist.LowerBin();
00280 double max = dist.UpperBin();
00281 const double * pv = &(dist.Data().front());
00282 ret |= unur_distr_cemp_set_hist(fUdistr, pv, nbins, min, max);
00283 #ifdef OLDVERS
00284 Error("SetEmpiricalDistribution","hist method not available in UNURAN 0.8.1");
00285 #endif
00286 }
00287 else {
00288 const double * pv = &dist.Data().front();
00289
00290 int n = dist.Data().size()/dist.NDim();
00291 if (dist.NDim() == 1)
00292 ret |= unur_distr_cemp_set_data(fUdistr, pv, n);
00293 else
00294 ret |= unur_distr_cvemp_set_data(fUdistr, pv, n);
00295 }
00296 if (ret != 0) {
00297 Error("SetEmpiricalDistribution","invalid distribution object");
00298 return false;
00299 }
00300 return true;
00301 }
00302
00303
00304 bool TUnuran::SetDiscreteDistribution(const TUnuranDiscrDist & dist)
00305 {
00306
00307 if (fUdistr != 0) unur_distr_free(fUdistr);
00308 fUdistr = unur_distr_discr_new();
00309 if (fUdistr == 0) return false;
00310 unsigned int ret = 0;
00311
00312 if (dist.ProbVec().size() == 0) {
00313 ret = unur_distr_set_extobj(fUdistr, &dist );
00314 ret |= unur_distr_discr_set_pmf(fUdistr, &DiscrDist::Pmf);
00315 if (dist.HasCdf() ) ret |= unur_distr_discr_set_cdf(fUdistr, &DiscrDist::Cdf);
00316
00317 }
00318 else {
00319
00320 ret |= unur_distr_discr_set_pv(fUdistr, &dist.ProbVec().front(), dist.ProbVec().size() );
00321 }
00322
00323 int xmin, xmax = 0;
00324 if (dist.GetDomain(xmin,xmax) ) {
00325 ret = unur_distr_discr_set_domain(fUdistr,xmin,xmax);
00326 if (ret != 0) {
00327 Error("SetDiscrDistribution","invalid domain xmin = %d xmax = %d ",xmin,xmax);
00328 return false;
00329 }
00330 }
00331 if (dist.HasMode() ) {
00332 ret = unur_distr_discr_set_mode(fUdistr, dist.Mode());
00333 if (ret != 0) {
00334 Error("SetContDistribution","invalid mode given, mode = %d ",dist.Mode());
00335 return false;
00336 }
00337 }
00338 if (dist.HasProbSum() ) {
00339 ret = unur_distr_discr_set_pmfsum(fUdistr, dist.ProbSum());
00340 if (ret != 0) {
00341 Error("SetContDistribution","invalid sum given, mode = %g ",dist.ProbSum());
00342 return false;
00343 }
00344 }
00345
00346 return (ret ==0) ? true : false;
00347 }
00348
00349
00350
00351 bool TUnuran::SetMethodAndInit() {
00352
00353
00354
00355 if (fUdistr == 0) return false;
00356
00357 struct unur_slist *mlist = NULL;
00358
00359 UNUR_PAR * par = _unur_str2par(fUdistr, fMethod.c_str(), &mlist);
00360 if (par == 0) {
00361 Error("SetMethod","missing distribution information or syntax error");
00362 if (mlist != 0) _unur_slist_free(mlist);
00363 return false;
00364 }
00365
00366
00367
00368 unur_set_use_distr_privatecopy (par, false);
00369
00370
00371 if (fGen != 0 ) unur_free(fGen);
00372 fGen = unur_init(par);
00373 _unur_slist_free(mlist);
00374 if (fGen == 0) {
00375 Error("SetMethod","initializing Unuran: condition for method violated");
00376 return false;
00377 }
00378 return true;
00379 }
00380
00381
00382 int TUnuran::SampleDiscr()
00383 {
00384
00385 assert(fGen != 0);
00386 return unur_sample_discr(fGen);
00387 }
00388
00389 double TUnuran::Sample()
00390 {
00391
00392 assert(fGen != 0);
00393 return unur_sample_cont(fGen);
00394 }
00395
00396 bool TUnuran::SampleMulti(double * x)
00397 {
00398
00399 if (fGen == 0) return false;
00400 unur_sample_vec(fGen,x);
00401 return true;
00402 }
00403
00404 void TUnuran::SetSeed(unsigned int seed) {
00405 return fRng->SetSeed(seed);
00406 }
00407
00408 bool TUnuran::SetLogLevel(unsigned int debugLevel)
00409 {
00410 if (fGen == 0) return false;
00411 int ret = 0;
00412 if ( debugLevel > 1)
00413 ret |= unur_chg_debug(fGen, UNUR_DEBUG_ALL);
00414 else if (debugLevel == 1)
00415 ret |= unur_chg_debug(fGen, UNUR_DEBUG_ALL);
00416 else
00417 ret |= unur_chg_debug(fGen, UNUR_DEBUG_OFF);
00418
00419 return (ret ==0) ? true : false;
00420
00421 }
00422
00423 bool TUnuran::InitPoisson(double mu, const std::string & method) {
00424
00425 double p[1];
00426 p[0] = mu;
00427
00428 fUdistr = unur_distr_poisson(p,1);
00429
00430 fMethod = method;
00431 if (fUdistr == 0) return false;
00432 if (! SetMethodAndInit() ) return false;
00433 if (! SetRandomGenerator() ) return false;
00434 return true;
00435 }
00436
00437
00438 bool TUnuran::InitBinomial(unsigned int ntot, double prob, const std::string & method ) {
00439
00440 double par[2];
00441 par[0] = ntot;
00442 par[1] = prob;
00443 fUdistr = unur_distr_binomial(par,2);
00444
00445 fMethod = method;
00446 if (fUdistr == 0) return false;
00447 if (! SetMethodAndInit() ) return false;
00448 if (! SetRandomGenerator() ) return false;
00449 return true;
00450 }
00451
00452
00453 bool TUnuran::ReInitDiscrDist(unsigned int npar, double * par) {
00454
00455
00456 if (!fGen ) return false;
00457 if (!fUdistr) return false;
00458 unur_distr_discr_set_pmfparams(fUdistr,par,npar);
00459 int iret = unur_reinit(fGen);
00460 if (iret) Warning("ReInitDiscrDist","re-init failed - a full initizialization must be performed");
00461 return (!iret);
00462 }
00463