TUnuran.cxx

Go to the documentation of this file.
00001 // @(#)root/unuran:$Id: TUnuran.cxx 37419 2010-12-08 21:19:45Z moneta $
00002 // Authors: L. Moneta, J. Leydold Tue Sep 26 16:25:09 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class TUnuran
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    // constructor implementation with a ROOT random generator
00043    // if no generator is given the ROOT default is used
00044    if (fRng == 0) fRng = gRandom; 
00045    // set debug level at global level 
00046    // (should be in a static  initialization function of the library ? )
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    // Destructor implementation
00060    if (fGen != 0) unur_free(fGen); 
00061    if (fUrng != 0) unur_urng_free(fUrng);
00062   // we can delete now the distribution object
00063    if (fUdistr != 0) unur_distr_free(fUdistr);
00064 }
00065 
00066 //private (no impl.)
00067 TUnuran::TUnuran(const TUnuran &) 
00068 {
00069    // Implementation of copy constructor.
00070 }
00071 
00072 TUnuran & TUnuran::operator = (const TUnuran &rhs) 
00073 {
00074    // Implementation of assignment operator.
00075    if (this == &rhs) return *this;  // time saving self-test
00076    return *this;
00077 }
00078 
00079 bool  TUnuran::Init(const std::string & dist, const std::string & method) 
00080 {
00081    // initialize with a string
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    // initialization with a distribution and and generator
00096    // the distribution object is copied in and managed by this class
00097    // use auto_ptr to manage previously existing distribution objects
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    //  initialization with a distribution and method
00112    // the distribution object is copied in and managed by this class
00113    // use auto_ptr to manage previously existing distribution objects
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    //   initialization with a distribution and and generator
00127    // the distribution object is copied in and managed by this class
00128    // use auto_ptr to manage previously existing distribution objects
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    //   initialization with a distribution and and generator
00141    // the distribution object is copied in and managed by this class
00142    // use auto_ptr to manage previously existing distribution objects
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    // set an external random generator
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    // internal method to set in unuran the function pointer for a continous univariate distribution 
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       // case user provides log of pdf 
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    // internal method to set in unuran the function pointer for a multivariate distribution 
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    // internal method to set in unuran the function pointer for am empiral distribution (from histogram)
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    // get info from histogram 
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       // n is number of points (size/ndim)
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    // internal method to set in unuran the function pointer for a discrete univariate distribution 
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    // if a probability mesh function is provided 
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       // case user provides vector of probabilities 
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 //bool TUnuran::SetMethodAndInit(const std::string & s) { 
00351 bool TUnuran::SetMethodAndInit() { 
00352 
00353    // internal function to set a method from a distribution and 
00354    // initialize unuran with the given distribution.
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    // set unuran to not use a private copy of the distribution object
00368    unur_set_use_distr_privatecopy (par, false);
00369 
00370    // need to free fGen if already existing ? 
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    // sample one-dimensional distribution
00385    assert(fGen != 0); 
00386    return unur_sample_discr(fGen);
00387 }
00388 
00389 double TUnuran::Sample()
00390 {
00391    // sample one-dimensional distribution
00392    assert(fGen != 0); 
00393    return unur_sample_cont(fGen);
00394 }
00395 
00396 bool TUnuran::SampleMulti(double * x)
00397 {
00398    // sample multidimensional distribution
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    // initializaton for a Poisson
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    // initializaton for a Binomial
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    // re-initialization of UNURAN without freeing and creating a new fGen object
00455    // works only for pre-defined distribution by changing their parameters 
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 

Generated on Tue Jul 5 14:43:41 2011 for ROOT_528-00b_version by  doxygen 1.5.1