unuranSimple.cxx

Go to the documentation of this file.
00001 // test unuran using the string interface to generate numbers according to the normal distributions
00002 // compare CPU performancecwith TRandom::Gaus and opitonally GSL (using MathMore ) and CLHEP for 
00003 // generating normal distributed random numbers 
00004 //
00005 // run within ROOT (.x unuranSimple.cxx+) or pass any extra parameter in the command line to get  
00006 // a graphics output 
00007 //
00008 #include "TStopwatch.h"
00009 #include "TUnuran.h"
00010 
00011 #include "TH1.h"
00012 #include "TF1.h"
00013 
00014 #include "TRandom.h"
00015 #include "TRandom1.h"
00016 #include "TRandom2.h"
00017 #include "TSystem.h"
00018 #include "TApplication.h"
00019 #include "TCanvas.h"
00020 //#include "TRint.h"
00021 #include "TVirtualFitter.h"
00022 #include "TFitter.h"
00023 #include "Math/DistFunc.h"
00024 
00025 #include <iostream> 
00026 
00027 #ifdef HAVE_MATHMORE
00028 #include "Math/Random.h"
00029 #include "Math/GSLRndmEngines.h"
00030 #endif
00031 
00032 
00033 
00034 #ifdef HAVE_CLHEP
00035 #include "CLHEP/Random/RandFlat.h"
00036 #include "CLHEP/Random/RandGauss.h"
00037 #include "CLHEP/Random/MTwistEngine.h"
00038 #include "CLHEP/Random/JamesRandom.h"
00039 #include "CLHEP/Random/RanluxEngine.h"
00040 #include "CLHEP/Random/Ranlux64Engine.h"
00041 #include "CLHEP/Random/RanecuEngine.h"
00042 #include "CLHEP/Random/Hurd160Engine.h"
00043 #include "CLHEP/Random/Hurd288Engine.h"
00044 #include "CLHEP/Random/RanshiEngine.h"
00045 #include "CLHEP/Random/DualRand.h"
00046 #include "CLHEP/Random/TripleRand.h"
00047 
00048 using namespace CLHEP;
00049 #endif
00050 
00051 
00052 using std::cout; 
00053 using std::endl; 
00054 
00055 int unuranSimple( ) { 
00056 
00057    // simple test of unuran
00058 
00059 
00060    std::cout << "Test Generation of Gaussian Numbers \n\n";
00061 
00062    TUnuran unr; 
00063    if (! unr.Init( "normal()", "method=arou") ) {
00064       cout << "Error initializing unuran" << endl;
00065       return -1;
00066    }
00067 
00068     // default is 10**7 but one should use 10**8 for serious timing
00069    int n = 10000000; 
00070 
00071    TStopwatch w;
00072    double time; 
00073    w.Start(); 
00074 
00075    for (int i = 0; i < n; ++i) 
00076       unr.Sample(); 
00077 
00078    w.Stop(); 
00079    time = w.CpuTime()*1.E9/n;
00080    cout << "Time using Unuran method arou =\t " <<   time << "\tns/call" << endl;
00081 
00082 
00083    if (! unr.Init( "normal()", "method=tdr") ) {
00084       cout << "Error initializing unuran" << endl;
00085       return -1;
00086    }
00087    w.Start(); 
00088    for (int i = 0; i < n; ++i) 
00089       unr.Sample(); 
00090 
00091    w.Stop(); 
00092    time = w.CpuTime()*1.E9/n;
00093    cout << "Time using Unuran method tdr =\t " <<   time << "\tns/call" << endl;
00094 
00095    if (! unr.Init( "normal()", "method=hinv") ) {
00096       cout << "Error initializing unuran" << endl;
00097       return -1;
00098    }
00099    w.Start(); 
00100    for (int i = 0; i < n; ++i) 
00101       unr.Sample(); 
00102 
00103    w.Stop(); 
00104    time = w.CpuTime()*1.E9/n;
00105    cout << "Time using Unuran method hinv =\t " <<   time << "\tns/call" << endl;
00106 
00107    w.Start();
00108    for (int i = 0; i < n; ++i) 
00109       gRandom->Gaus(0,1); 
00110    w.Stop(); 
00111    time = w.CpuTime()*1.E9/n;
00112    cout << "Time using TRandom::Gaus  =\t " <<   time << "\tns/call" << endl;
00113 
00114    // using Rannor
00115    w.Start();
00116    double x1,x2; 
00117    for (int i = 0; i < n/2; ++i) 
00118       gRandom->Rannor(x1,x2); 
00119    w.Stop(); 
00120    time = w.CpuTime()*1.E9/n;
00121    cout << "Time using TRandom::Rannor  =\t " <<   time << "\tns/call" << endl;
00122 
00123 #ifdef HAVE_MATHMORE
00124    // using GSL Ziggurat
00125    ROOT::Math::Random<ROOT::Math::GSLRngMT>     rgsl;
00126    w.Start();
00127    for (int i = 0; i < n; ++i) 
00128       rgsl.Gaus(0,1); 
00129    w.Stop(); 
00130    time = w.CpuTime()*1.E9/n;
00131    cout << "Time using GSL::Gaus  =\t\t " <<   time << "\tns/call" << endl;
00132 
00133    // using GSL BoxMuller method
00134    w.Start();
00135    for (int i = 0; i < n; ++i) 
00136       rgsl.GausBM(0,1); 
00137    w.Stop(); 
00138    time = w.CpuTime()*1.E9/n;
00139    cout << "Time using GSL::GausBM  =  \t " <<   time << "\tns/call" << endl;
00140 
00141    // using GSL Ratio method
00142    w.Start();
00143    for (int i = 0; i < n; ++i) 
00144       rgsl.GausR(0,1); 
00145    w.Stop(); 
00146    time = w.CpuTime()*1.E9/n;
00147    cout << "Time using GSL::GausR  =\t " <<   time << "\tns/call" << endl;
00148 #endif
00149 
00150 
00151    // run unuran standard Normal methods 2 (Polar from Marsaglia)
00152 
00153    if (! unr.Init( "normal()", "method=cstd;variant=2") ) {
00154       cout << "Error initializing unuran" << endl;
00155       return -1;
00156    }
00157    w.Start(); 
00158    for (int i = 0; i < n; ++i) 
00159       unr.Sample(); 
00160 
00161    w.Stop(); 
00162    time = w.CpuTime()*1.E9/n;
00163    cout << "Time using Unuran GausPolarR =\t " <<   time << "\tns/call" << endl;
00164 
00165    // run unuran standard Normal method 3 (KM)
00166 
00167    if (! unr.Init( "normal()", "method=cstd;variant=3") ) {
00168       cout << "Error initializing unuran" << endl;
00169       return -1;
00170    }
00171    w.Start(); 
00172    for (int i = 0; i < n; ++i) 
00173       unr.Sample(); 
00174 
00175    w.Stop(); 
00176    time = w.CpuTime()*1.E9/n;
00177    cout << "Time using Unuran Gaus  K-R   =\t " <<   time << "\tns/call" << endl;
00178   
00179    if (! unr.Init( "normal()", "method=cstd;variant=6") ) {
00180       cout << "Error initializing unuran" << endl;
00181       return -1;
00182    }
00183    w.Start(); 
00184    for (int i = 0; i < n; ++i) 
00185       unr.Sample(); 
00186 
00187    w.Stop(); 
00188    time = w.CpuTime()*1.E9/n;
00189    cout << "Time using Unuran Gaus exp6  =\t " <<   time << "\tns/call" << endl;
00190 
00191 
00192 //    w.Start();
00193 //    for (int i = 0; i < n; ++i) 
00194 //       rgsl.GausRatio(0,1); 
00195 //    w.Stop(); 
00196 //    time = w.CpuTime()*1.E9/n;
00197 //    cout << "Time using GSL::GausRatio  =\t\t " <<   time << "\tns/call" << endl;
00198 
00199 #ifdef HAVE_CLHEP
00200    MTwistEngine eng(111);
00201    RandGauss rg(eng);
00202    w.Start();
00203    for (int i = 0; i < n; ++i) 
00204       rg(0,1); 
00205    w.Stop(); 
00206    time = w.CpuTime()*1.E9/n;
00207    cout << "Time using CLHEP::Gaus  =\t " <<   time << "\tns/call" << endl;
00208 #endif
00209 
00210    std::cout << "\nTest uniform generator\n" << std::endl;
00211    w.Start();
00212    for (int i = 0; i < n; ++i) 
00213       gRandom->Rndm(); 
00214    w.Stop(); 
00215    time = w.CpuTime()*1.E9/n;
00216    cout << "Time using gRandom::Rndm  =\t " <<   time << "\tns/call" << endl;
00217 
00218    TRandom1 r1;
00219    w.Start();
00220    for (int i = 0; i < n; ++i) 
00221       r1.Rndm(); 
00222    w.Stop(); 
00223    time = w.CpuTime()*1.E9/n;
00224    cout << "Time using TRandom1::Rndm  =\t " <<   time << "\tns/call" << endl;
00225 
00226    TRandom2 r2;
00227    w.Start();
00228    for (int i = 0; i < n; ++i) 
00229       r2.Rndm(); 
00230    w.Stop(); 
00231    time = w.CpuTime()*1.E9/n;
00232    cout << "Time using TRandom2::Rndm  =\t " <<   time << "\tns/call" << endl;
00233 
00234 #ifdef HAVE_CLHEP
00235    RandFlat rf(eng);
00236    w.Start();
00237    for (int i = 0; i < n; ++i) 
00238       eng.flat(); // use directly the engine (faster!)
00239    w.Stop(); 
00240    time = w.CpuTime()*1.E9/n;
00241    cout << "Time using CLHEP::MT  =\t\t " <<   time << "\tns/call" << endl;
00242 
00243    { 
00244       RanecuEngine e; 
00245       RandFlat rf2(e);
00246       w.Start();
00247       for (int i = 0; i < n; ++i) 
00248          e.flat(); 
00249       w.Stop(); 
00250       time = w.CpuTime()*1.E9/n;
00251       cout << "Time using CLHEP::Ranecu  =\t " <<   time << "\tns/call" << endl;
00252    }
00253    { 
00254       Hurd160Engine e; 
00255       RandFlat rf2(e);
00256       w.Start();
00257       for (int i = 0; i < n; ++i) 
00258          e.flat();
00259       w.Stop(); 
00260       time = w.CpuTime()*1.E9/n;
00261       cout << "Time using CLHEP::Hard160  =\t " <<   time << "\tns/call" << endl;
00262    }
00263    { 
00264       Hurd288Engine e; 
00265       RandFlat rf2(e);
00266       w.Start();
00267       for (int i = 0; i < n; ++i) 
00268          e.flat();
00269          //rf2(); 
00270       w.Stop(); 
00271       time = w.CpuTime()*1.E9/n;
00272       cout << "Time using CLHEP::Hard288  =\t " <<   time << "\tns/call" << endl;
00273    }
00274    { 
00275       DualRand e; 
00276       RandFlat rf2(e);
00277       w.Start();
00278       for (int i = 0; i < n; ++i) 
00279          e.flat();
00280       //rf2(); 
00281       w.Stop(); 
00282       time = w.CpuTime()*1.E9/n;
00283       cout << "Time using CLHEP::DualRand  =\t " <<   time << "\tns/call" << endl;
00284    }
00285    {
00286       TripleRand e; 
00287       RandFlat rf2(e);
00288       w.Start();
00289       for (int i = 0; i < n; ++i) 
00290          e.flat();
00291       //rf2(); 
00292       w.Stop(); 
00293       time = w.CpuTime()*1.E9/n;
00294       cout << "Time using CLHEP::TripleRand  =\t " <<   time << "\tns/call" << endl;
00295    }
00296    {
00297       RanshiEngine e; 
00298       RandFlat rf2(e);
00299       w.Start();
00300       for (int i = 0; i < n; ++i) 
00301          //rf2(); 
00302          e.flat();
00303       w.Stop(); 
00304       time = w.CpuTime()*1.E9/n;
00305       cout << "Time using CLHEP::Runshi  =\t " <<   time << "\tns/call" << endl;
00306    }
00307    {
00308       RanluxEngine e; 
00309       RandFlat rf2(e);
00310       w.Start();
00311       for (int i = 0; i < n; ++i) 
00312          //rf2(); 
00313          e.flat();
00314       w.Stop(); 
00315       time = w.CpuTime()*1.E9/n;
00316       cout << "Time using CLHEP::RunLux  =\t " <<   time << "\tns/call" << endl;
00317    }
00318    {
00319       Ranlux64Engine e; 
00320       RandFlat rf2(e);
00321       w.Start();
00322       for (int i = 0; i < n; ++i) 
00323          e.flat(); 
00324       w.Stop(); 
00325       time = w.CpuTime()*1.E9/n;
00326       cout << "Time using CLHEP::RunLux64  =\t " <<   time << "\tns/call" << endl;
00327    }
00328    {
00329       HepJamesRandom e; 
00330       RandFlat rf2(e);
00331       w.Start();
00332       for (int i = 0; i < n; ++i) 
00333          //rf2(); 
00334          e.flat(); 
00335       w.Stop(); 
00336       time = w.CpuTime()*1.E9/n;
00337       cout << "Time using CLHEP::HepJames  =\t " <<   time << "\tns/call" << endl;
00338    }
00339 
00340 #endif
00341 
00342 
00343    // test the quality by looking at the cdf
00344    cout <<"\n\nTest quality of Unuran arou" << endl;
00345    if (! unr.Init( "normal()", "method=arou") ) {
00346       cout << "Error initializing unuran" << endl;
00347       return -1;
00348    }
00349 
00350    TH1D * h1 = new TH1D("h1","cdf on the data ",1000,0,1);
00351    for (int i = 0; i < 1000000; ++i) {
00352       double x = unr.Sample();
00353       h1->Fill( ROOT::Math::normal_cdf( x , 1.0) ); 
00354    }
00355 
00356    new TCanvas("c1_unuranGaus","unuran Gaus CDF");
00357 
00358    h1->Fit("pol0","Q");
00359    TF1 * f = h1->GetFunction("pol0");
00360 
00361    std::cout << "CDF Uniform Fit:  chi2 = " << f->GetChisquare() << " ndf = " << f->GetNDF() << std::endl;
00362    std::cout << "Fit Prob = " << f->GetProb() << std::endl;
00363    h1->Draw("E");
00364 
00365    if (f->GetProb() < 1.E-4) { 
00366       std::cerr << "\nERROR: UnuranSimple Test:\t Failed !!!!"; 
00367       return -1; 
00368    }
00369    std::cerr << "\nUnuranSimple Test:\t OK !" << std::endl;
00370 
00371    return 0; 
00372 
00373 }
00374 
00375 #ifndef __CINT__
00376 int main(int argc, char **argv)
00377 {
00378    int iret = 0;
00379    if (argc > 1) { 
00380       TApplication theApp("App",&argc,argv);
00381       iret = unuranSimple();
00382       theApp.Run();
00383    } 
00384    else 
00385       iret = unuranSimple();
00386 
00387    return iret;
00388 }
00389 #endif
00390 

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