unuranDiscrete.cxx

Go to the documentation of this file.
00001 // test using discrete distribution. 
00002 // Generate numbers from a given probability vector or from a discrete distribution like 
00003 // the Poisson distribution. 
00004 // Compare also the Unuran method for generating Poisson numbers with TRandom::Poisson
00005 //
00006 // run within ROOT (.x unuranDiscrete.cxx+) or pass any extra parameter in the command line to get  
00007 // a graphics output (./unuranDiscrete 1 )
00008 
00009 
00010 #include "TUnuran.h"
00011 #include "TUnuranDiscrDist.h"
00012 
00013 #include "TH1.h"
00014 #include "TMath.h"
00015 #include "TF1.h"
00016 #include "TRandom3.h"
00017 #include "TApplication.h"
00018 #include "TCanvas.h"
00019 #include "TStopwatch.h"
00020 #include "TError.h"
00021 
00022 
00023 #ifdef WRITE_OUTPUT
00024 #include "TFile.h"
00025 #include "TGraph.h"
00026 #endif
00027 
00028 #include "Math/Functor.h"
00029 #include "Math/DistFunc.h"
00030 #include "Math/Util.h"
00031 
00032 #include <iostream>
00033 #include <iomanip>
00034 
00035 //#define DEBUG
00036 #ifdef DEBUG
00037 int n = 100;
00038 #else
00039 int n = 1000000;
00040 #endif
00041 TCanvas * c1; 
00042 int icanv = 1;
00043 
00044 bool useRandomSeed = false;   // to use a random seed different every time
00045 
00046 double poisson_pmf(double * x, double * p) { 
00047 
00048    double y = ROOT::Math::poisson_pdf(int(x[0]),p[0]);
00049 //   std::cout << x[0] << " f(x) = " << y << std::endl;
00050    return y; 
00051 }
00052 double binomial_pmf(double * x, double * p) { 
00053 
00054    double y = ROOT::Math::binomial_pdf(static_cast<unsigned int>(x[0]),p[1], static_cast<unsigned int>(p[0]));
00055 //   std::cout << x[0] << " f(x) = " << y << std::endl;
00056    return y; 
00057 }
00058 
00059 int testUnuran(TUnuran & unr, double & time, TH1 * h1, const TH1 * href,  bool weightHist = false ) { 
00060 
00061 
00062    // test first the time
00063    TStopwatch w; 
00064 
00065    w.Start(); 
00066    for (int i = 0; i < n; ++i) 
00067       unr.SampleDiscr(); 
00068 
00069    w.Stop(); 
00070    time = w.CpuTime()*1.E9/n; 
00071 
00072 
00073    // test quality (use cdf to avoid zero bins)
00074    h1->Reset();
00075    int n2 = n/10;
00076    int x;
00077    for (int i = 0; i<n2; ++i) { 
00078       x =  unr.SampleDiscr(); 
00079       h1->Fill( double( x) ); 
00080    } 
00081    double prob; 
00082    if (weightHist) 
00083       prob = h1->Chi2Test(href,"UW");
00084    else
00085       prob = h1->Chi2Test(href,"UU");
00086    std::string s = "Time using Unuran  " +  unr.MethodName();
00087    std::cout << std::left << std::setw(40) << s << "\t=\t " << time << "\tns/call \t\tChi2 Prob = "<< prob << std::endl;
00088    if (prob < 1E-06) { 
00089       std::cout << "Chi2 Test failed for method " << unr.MethodName() << std::endl;
00090       if (weightHist) 
00091          h1->Chi2Test(href,"UWP"); // print all chi2 test info
00092       else 
00093          h1->Chi2Test(href,"UUP"); // print all chi2 test info
00094 
00095       return 1;
00096    }
00097    return 0; 
00098 }  
00099 
00100 int testRootPoisson(double mu, double &time, TH1 * h2) { 
00101    TStopwatch w; 
00102 
00103    w.Start(); 
00104    for (int i = 0; i < n; ++i) 
00105       gRandom->Poisson(mu);
00106 
00107    w.Stop(); 
00108    time = w.CpuTime()*1.E9/n; 
00109 
00110    // make ref histo
00111    int n2 = n/10;
00112    for (int i = 0; i< n2; ++i) { 
00113       h2->Fill ( gRandom->Poisson(mu) );
00114    }
00115 
00116    std::string s = "Time using TRandom::Poisson";
00117    std::cout << std::left << std::setw(40) << s << "\t=\t " << time << std::endl;
00118    return 0;
00119 }
00120 
00121 int testRootBinomial(int m, double p, double &time, TH1 * h2) { 
00122 
00123    TStopwatch w; 
00124 
00125    w.Start(); 
00126    for (int i = 0; i < n; ++i) 
00127       gRandom->Binomial(m,p);
00128 
00129    w.Stop(); 
00130    time = w.CpuTime()*1.E9/n; 
00131 
00132    // make ref histo
00133    int n2 = n/10;
00134    for (int i = 0; i< n2; ++i) { 
00135       h2->Fill ( gRandom->Binomial(m,p) );
00136    }
00137 
00138    std::string s = "Time using TRandom::Binomial";
00139    std::cout << std::left << std::setw(40) << s << "\t=\t " << time << std::endl;
00140    return 0;
00141 }
00142 
00143 int testProbVector() { 
00144 
00145    int iret = 0;
00146 
00147    TH1D * h0 = new TH1D("h0","reference prob",10,-0.5,9.5);
00148    TH1D * h1 = new TH1D("h1","UNURAN gen prob",10,-0.5,9.5);
00149 
00150 
00151    double p[10] = {1.,2.,3.,5.,3.,2.,1.,0.5,0.3,0.5 };
00152    for (int i = 0; i< 10; ++i) { 
00153       h0->SetBinContent(i+1,p[i]);
00154       h0->SetBinError(i+1,0.);
00155    }
00156    double sum = h0->GetSumOfWeights();
00157    std::cout << " prob sum = " << sum << std::endl; 
00158       
00159    TUnuran unr(gRandom,2); 
00160 
00161    TUnuranDiscrDist dist(p,p+10);
00162 
00163 //    TUnuranDiscrDist fDDist = dist; 
00164 //    std::cout << fDDist.ProbVec().size() << std::endl;
00165 
00166    std::cout << "Test  generation with a PV :\n\n";
00167    
00168    double time;
00169 
00170    bool ret = unr.Init(dist,"method=dau");
00171    if (!ret) iret = -1;
00172    iret |= testUnuran(unr,time,h1,h0,true);
00173 
00174    ret = unr.Init(dist,"method=dgt");
00175    if (!ret) iret = -1;
00176    iret |= testUnuran(unr,time,h1,h0,true);
00177 
00178    // dss require the sum
00179    dist.SetProbSum(sum);
00180    ret = unr.Init(dist,"method=dss");
00181    if (!ret) iret = -1;
00182    iret |= testUnuran(unr,time,h1,h0,true);
00183 
00184    
00185 
00186 
00187 
00188    c1->cd(icanv++);
00189    h1->Sumw2();
00190    h1->Scale( h0->GetSumOfWeights()/(h1->GetSumOfWeights() ) ); 
00191    h0->Draw();
00192    h1->SetLineColor(kBlue);
00193    h1->Draw("Esame");
00194    c1->Update();
00195 
00196    return iret; 
00197 }
00198 
00199 int testPoisson() { 
00200    // test with a function 
00201    // Poisson distribution
00202 
00203    int iret = 0;
00204    std::cout << "\nTest  generation with a Probability function (Poisson) :\n\n";
00205 
00206    TF1 * f = new TF1("f",poisson_pmf,1,0,1);
00207 
00208    // loop on mu values for Nmu times 
00209 
00210    const int Nmu = 5;
00211    double muVal[Nmu] = {5,10,20,50,100};
00212    double tR[Nmu]; 
00213    double tU[Nmu]; 
00214    double tUdari[Nmu];
00215    double tUdsrou[Nmu];
00216 
00217   TUnuran unr(gRandom,2); 
00218 
00219   for (int imu = 0; imu < Nmu; ++imu) {  
00220 
00221      const double mu = muVal[imu]; 
00222 
00223      int nmax = static_cast<int>(mu*3);
00224      TH1D * h2 = new TH1D("h2","reference Poisson prob",nmax,0,nmax);
00225      TH1D * h3 = new TH1D("h3","UNURAN gen prob",nmax,0,nmax);
00226      TH1D * h4 = new TH1D("h4","UNURAN gen prob 2",nmax,0,nmax);
00227 
00228 
00229      std::cout << "\nPoisson mu = " << mu << std::endl << std::endl;
00230 
00231      testRootPoisson(mu,tR[imu],h2);
00232 
00233      // test UNURAN with standard method
00234      bool ret = unr.InitPoisson(mu);
00235      if (!ret) iret = -1;
00236      testUnuran(unr,tU[imu],h3,h2);
00237 
00238       
00239      // test changing all the time the mu
00240      // use re-init for a fast re-initialization 
00241      TStopwatch w;
00242      unr.InitPoisson(mu,"dstd");
00243      double p[1]; p[0] = mu; 
00244      w.Start(); 
00245      for (int i = 0; i < n; ++i) {
00246         unr.ReInitDiscrDist(1,p);  
00247         int k = unr.SampleDiscr(); 
00248         if (n % 10 == 0) h4->Fill(k);
00249      }
00250      w.Stop(); 
00251      double time = w.CpuTime()*1.E9/n; 
00252      double prob = h2->Chi2Test(h4,"UU");
00253      std::string s = "Time using Unuran w/ re-init  method=" + unr.MethodName(); 
00254      std::cout << std::left << std::setw(40) << s << "\t=\t " << time 
00255                << "\tns/call \t\tChi2 Prob = "<< prob << std::endl;
00256       
00257      if (prob < 1E-06) { 
00258         std::cout << "Chi2 Test failed for re-init " << std::endl;
00259         iret = -2; 
00260      }
00261  
00262      f->SetParameter(0,mu);
00263 
00264 #ifdef USE_FUNCTOR
00265      ROOT::Math::Functor1D f2(f);
00266      TUnuranDiscrDist dist2 = TUnuranDiscrDist(f2);
00267 #else 
00268      TUnuranDiscrDist dist2 = TUnuranDiscrDist(f);
00269 #endif
00270 
00271      // dari method (needs mode and pdf sum)
00272      dist2.SetMode(int(mu) );
00273      dist2.SetProbSum(1. );
00274      ret = unr.Init(dist2,"method=dari");
00275      if (!ret) iret = -1;
00276 
00277      iret |= testUnuran(unr,tUdari[imu],h3,h2);
00278 
00279      // dsrou method (needs mode and sum)
00280 
00281      dist2.SetProbSum(1);
00282      ret = unr.Init(dist2,"method=dsrou");
00283      if (!ret) iret = -1;
00284 
00285      iret |= testUnuran(unr,tUdsrou[imu],h3,h2);
00286 
00287 
00288      c1->cd(icanv++);
00289      h2->DrawCopy();
00290      h3->SetLineColor(kBlue);
00291      h3->DrawCopy("Esame");
00292      c1->Update();
00293 
00294      delete h2; 
00295      delete h3;
00296      delete h4;
00297   }
00298 
00299 #ifdef WRITE_OUTPUT
00300 
00301    TFile * file = new TFile("unuranPoisson.root","RECREATE");
00302    // create graphs with results
00303    TGraph * gR = new TGraph(Nmu,muVal,tR);   
00304    TGraph * gU = new TGraph(Nmu,muVal,tU);
00305    TGraph * gU2 = new TGraph(Nmu,muVal,tUdari);
00306    TGraph * gU3 = new TGraph(Nmu,muVal,tUdsrou);
00307    gR->Write();
00308    gU->Write();
00309    gU2->Write();
00310    gU3->Write();
00311    file->Close();
00312 
00313 #endif
00314 
00315    return iret; 
00316 }
00317 
00318 int testBinomial() { 
00319    // test using binomial distribution
00320    int iret = 0; 
00321 
00322    std::cout << "\nTest  generation with a Probability function (Binomimal) :\n\n";
00323 
00324    TF1 * f = new TF1("f",binomial_pmf,1,0,2);
00325 
00326    // loop on binomual values
00327 
00328    const int NBin = 3;
00329    double pVal[NBin] = {0.5,0.1,0.01};
00330    double NVal[NBin] = {20,100,1000}; 
00331    double tR[NBin]; 
00332    double tU[NBin]; 
00333    double tUdari[NBin];
00334    double tUdsrou[NBin];
00335 
00336 
00337   TUnuran unr(gRandom,2); 
00338 
00339 
00340   for (int ib = 0; ib < NBin; ++ib) {  
00341 
00342     
00343      double par[2]; 
00344      par[0] = NVal[ib];
00345      par[1] = pVal[ib];
00346 
00347      int nmax = static_cast<int>(par[0]*par[1]*3);
00348      TH1D * h2 = new TH1D("h2","reference Binomial prob",nmax,0,nmax);
00349      TH1D * h3 = new TH1D("h3","UNURAN gen prob",nmax,0,nmax);
00350      TH1D * h4 = new TH1D("h4","UNURAN gen prob 2",nmax,0,nmax);
00351 
00352 
00353      std::cout << "\nBinomial n = " << par[0] << "  " << par[1] << std::endl;
00354 
00355      testRootBinomial(static_cast<int>(par[0]),par[1],tR[ib],h2);
00356 
00357 
00358      // test UNURAN with standard method
00359      bool ret = unr.InitBinomial(static_cast<int>(par[0]),par[1]);
00360      if (!ret) iret = -1;
00361      testUnuran(unr,tU[ib],h3,h2);
00362 
00363       
00364      // test changing all the time the mu
00365      // use re-init for a fast re-initialization 
00366 
00367      TStopwatch w;
00368      unr.InitBinomial(static_cast<int>(par[0]), par[1],"dstd");
00369      w.Start(); 
00370      for (int i = 0; i < n; ++i) {
00371         unr.ReInitDiscrDist(2,par);  
00372         int k = unr.SampleDiscr(); 
00373         if (n % 10 == 0) h4->Fill(k);
00374      }
00375      w.Stop(); 
00376      double time = w.CpuTime()*1.E9/n; 
00377      double prob = h2->Chi2Test(h4,"UU");
00378      std::string s = "Time using Unuran w/ re-init  method=" + unr.MethodName(); 
00379      std::cout << std::left << std::setw(40) << s << "\t=\t " << time 
00380                << "\tns/call \t\tChi2 Prob = "<< prob << std::endl;
00381       
00382      if (prob < 1E-06) { 
00383         std::cout << "Chi2 Test failed for re-init " << std::endl;
00384         iret = -2; 
00385      }
00386 
00387      // test the universal methods 
00388 
00389      f->SetParameters(par);
00390      TUnuranDiscrDist dist = TUnuranDiscrDist(f);
00391 
00392      // dari method (needs mode and pdf sum)
00393      dist.SetMode(int(par[0]*par[1]) );
00394      dist.SetProbSum(1. );
00395      ret = unr.Init(dist,"method=dari");
00396      if (!ret) iret = -1;
00397 
00398      iret |= testUnuran(unr,tUdari[ib],h3,h2);
00399 
00400      // dsrou method (needs mode and sum)
00401 
00402      ret = unr.Init(dist,"method=dsrou");
00403      if (!ret) iret = -1;
00404 
00405      iret |= testUnuran(unr,tUdsrou[ib],h3,h2);
00406 
00407 
00408      c1->cd(icanv++);
00409      h2->DrawCopy();
00410      h3->SetLineColor(kBlue);
00411      h3->DrawCopy("Esame");
00412      c1->Update();
00413 
00414      delete h2; 
00415      delete h3;
00416      delete h4;
00417   }
00418 
00419 
00420    return iret; 
00421 }
00422 
00423 int unuranDiscrete() {
00424 
00425    int iret = 0; 
00426 
00427    c1 = new TCanvas("c1_unuranDiscr_PV","Discrete distribution from PV",10,10,800,800); 
00428    c1->Divide(3,3);
00429 
00430    // switch off printing of  info messages from chi2 test
00431    gErrorIgnoreLevel = 1001; 
00432 
00433    // check if using a random seed
00434    if (useRandomSeed) gRandom->SetSeed(0);
00435 
00436    iret |= testProbVector(); 
00437    iret |= testPoisson(); 
00438    iret |= testBinomial(); 
00439 
00440    if (iret != 0) 
00441       std::cerr <<"\n\nUnuRan Discrete Distribution Test:\t  Failed !!!!!!!" << std::endl;
00442    else 
00443       std::cerr << "\n\nUnuRan Discrete Distribution Test:\t OK" << std::endl;
00444    return iret; 
00445 
00446    return iret;
00447 }
00448 
00449 
00450 #ifndef __CINT__
00451 int main(int argc, char **argv)
00452 {
00453    int iret = 0; 
00454    if (argc > 1) { 
00455       TApplication theApp("App",&argc,argv);
00456       iret =  unuranDiscrete();
00457       theApp.Run();
00458    } 
00459    else 
00460       iret =  unuranDiscrete();
00461    
00462 }
00463 #endif

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