00001
00002
00003
00004
00005
00006
00007
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
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;
00045
00046 double poisson_pmf(double * x, double * p) {
00047
00048 double y = ROOT::Math::poisson_pdf(int(x[0]),p[0]);
00049
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
00056 return y;
00057 }
00058
00059 int testUnuran(TUnuran & unr, double & time, TH1 * h1, const TH1 * href, bool weightHist = false ) {
00060
00061
00062
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
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");
00092 else
00093 h1->Chi2Test(href,"UUP");
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
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
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
00164
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
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
00201
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
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
00234 bool ret = unr.InitPoisson(mu);
00235 if (!ret) iret = -1;
00236 testUnuran(unr,tU[imu],h3,h2);
00237
00238
00239
00240
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
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
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
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
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
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
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
00365
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
00388
00389 f->SetParameters(par);
00390 TUnuranDiscrDist dist = TUnuranDiscrDist(f);
00391
00392
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
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
00431 gErrorIgnoreLevel = 1001;
00432
00433
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