00001 #include <iostream>
00002 #include <ctime>
00003 #include <algorithm>
00004 #include <vector>
00005
00006 #include <gsl/gsl_permutation.h>
00007
00008 #include <TRandom2.h>
00009 #include <TMath.h>
00010 #include <TStopwatch.h>
00011
00012 #include <TApplication.h>
00013 #include <TCanvas.h>
00014 #include <TH2F.h>
00015 #include <TGraph.h>
00016 #include <TLegend.h>
00017 #include <TAxis.h>
00018
00019 bool showGraphics = true;
00020
00021 const int npass = 2;
00022 const int minsize = 5;
00023 const int maxsize = 12;
00024 const int maxint = 5000;
00025 const int arraysize = (maxsize-minsize) + 1;
00026
00027 using namespace std;
00028
00029 ostream& operator <<(ostream& os, const vector<Int_t>& v)
00030 {
00031 os << "[ ";
00032 for ( vector<Int_t>::const_iterator i = v.begin(); i != v.end() ; ++i) {
00033 os << *i << ' ';
00034 }
00035 os << ']';
00036
00037 return os;
00038 }
00039
00040 void initArray(Int_t n, vector<Int_t>& array)
00041 {
00042 TRandom2 r( time( 0 ) );
00043 for ( Int_t i = 0; i < n; i++) {
00044 array[i] = r.Integer( maxint );
00045 }
00046 sort(array.begin(), array.end());
00047 }
00048
00049 bool checkPermute()
00050 {
00051 const Int_t n = minsize;
00052
00053 vector<Int_t> original(n);
00054 vector<Int_t> vM(n);
00055 vector<Int_t> vS(n);
00056
00057 bool equals = true;
00058
00059 initArray(n, original);
00060
00061
00062 copy(original.begin(), original.end(), vM.begin());
00063 copy(original.begin(), original.end(), vS.begin());
00064
00065
00066 while ( TMath::Permute(n, &vM[0]) ) {
00067 std::next_permutation(&vS[0], &vS[n]);
00068
00069 equals &= equal(vM.begin(), vM.end(), vS.begin());
00070 }
00071
00072 TMath::Permute(n, &vM[0]);
00073 std::next_permutation(vS.begin(), vS.end());
00074
00075
00076 return equals;
00077 }
00078
00079 void permuteTime(const int n, double* tTMath, double* tStd)
00080 {
00081 vector<Int_t> original(n);
00082 vector<Int_t> v(n);
00083
00084 TStopwatch t;
00085
00086 initArray(n, original);
00087
00088
00089 t.Start();
00090 for (int j = 0; j < npass; ++j) {
00091 copy(original.begin(), original.end(), v.begin());
00092 while ( TMath::Permute(n, &v[0]) ) {}
00093 }
00094 t.Stop();
00095 *tTMath = t.RealTime();
00096 cout << "TMath::Permute time :\t " << t.RealTime();
00097
00098
00099 t.Start();
00100 for (int j = 0; j < npass; ++j) {
00101 copy(original.begin(), original.end(), v.begin());
00102 while ( std::next_permutation(&v[0], &v[n]) ) {}
00103 }
00104 t.Stop();
00105 *tStd = t.RealTime();
00106 cout << " std::next_permutation time :\t " << t.RealTime();
00107 }
00108
00109 void testGSLPermute(Int_t n, double* tGSL)
00110 {
00111 TStopwatch t;
00112
00113 gsl_permutation *original = gsl_permutation_alloc(n);
00114 gsl_permutation *p = gsl_permutation_alloc(n);
00115
00116 gsl_permutation_init(original);
00117
00118 t.Start();
00119 for (int j = 0; j < npass; ++j) {
00120 gsl_permutation_memcpy(p, original);
00121 while ( gsl_permutation_next(p) == GSL_SUCCESS )
00122 {
00123
00124
00125 }
00126 }
00127 t.Stop();
00128 *tGSL = t.RealTime();
00129 cout << " gsl_permutation_next time :\t " << t.RealTime();
00130
00131 gsl_permutation_free(p);
00132 gsl_permutation_free(original);
00133 }
00134
00135 int testPermute()
00136 {
00137 int status = 0;
00138 bool equals;
00139
00140 vector<double> tM( arraysize );
00141 vector<double> tS( arraysize );
00142 vector<double> tG( arraysize );
00143 vector<double> index( arraysize );
00144
00145 equals = checkPermute();
00146
00147 cout << "checkPermute()...."
00148 << (equals? "OK" : "FAILED")
00149 << endl;
00150
00151 status += (equals == false);
00152
00153 for ( int i = minsize; i <= maxsize; i += 1)
00154 {
00155 permuteTime(i, &tM[ i - minsize ], &tS[ i -minsize ]);
00156 testGSLPermute(i, &tG[ i - minsize ]);
00157 index[ i - minsize ] = i;
00158 cout << endl;
00159 }
00160
00161 for ( int i = minsize; i <= maxsize; i += 1)
00162 cout << tM[ i - minsize ] << ' ' << tS[ i - minsize ] << ' ' << tG[ i - minsize ] << endl;
00163
00164 if ( showGraphics )
00165 {
00166 TCanvas* c1 = new TCanvas("c1", "Comparision of Permutation Time", 600, 400);
00167 TH2F* hpx = new TH2F("hpx", "Comparision of Permutation Time", arraysize, minsize, maxsize, arraysize, tM[0],tS[arraysize-1]);
00168 hpx->SetStats(kFALSE);
00169 hpx->Draw();
00170
00171 TGraph* gM = new TGraph(arraysize, &index[0], &tM[0]);
00172 gM->SetLineColor(2);
00173 gM->SetLineWidth(3);
00174 gM->SetTitle("TMath::Permute()");
00175 gM->Draw("SAME");
00176
00177 TGraph* gS = new TGraph(arraysize, &index[0], &tS[0]);
00178 gS->SetLineColor(3);
00179 gS->SetLineWidth(3);
00180 gS->SetTitle("std::next_permutation()");
00181 gS->Draw("SAME");
00182
00183 TGraph* gG = new TGraph(arraysize, &index[0], &tG[0]);
00184 gG->SetLineColor(4);
00185 gG->SetLineWidth(3);
00186 gG->SetTitle("gsl_permutation_next()");
00187 gG->Draw("SAME");
00188
00189 TLegend* legend = new TLegend(0.15,0.72,0.4,0.86);
00190 legend->AddEntry(gM, "TMath::Permute()");
00191 legend->AddEntry(gS, "std::next_permutation()");
00192 legend->AddEntry(gG, "gsl_permutation_next()");
00193 legend->Draw();
00194
00195 hpx->GetXaxis()->SetTitle("Array Size");
00196 hpx->GetYaxis()->SetTitle("Time");
00197
00198
00199 c1->Show();
00200 }
00201
00202 cout << "Test Done!" << endl;
00203
00204 return status;
00205 }
00206
00207 int main(int argc, char **argv)
00208 {
00209 int status = 0;
00210
00211 if ( argc > 1 && argc != 2 )
00212 {
00213 cerr << "Usage: " << argv[0] << " [-ng]\n";
00214 cerr << " where:\n";
00215 cerr << " -ng : no graphics mode";
00216 cerr << endl;
00217 exit(1);
00218 }
00219
00220 if ( argc == 2 && strcmp( argv[1], "-ng") == 0 )
00221 {
00222 showGraphics = false;
00223 }
00224
00225 TApplication* theApp = 0;
00226
00227 if ( showGraphics )
00228 theApp = new TApplication("App",&argc,argv);
00229
00230
00231 status += testPermute();
00232
00233 if ( showGraphics )
00234 {
00235 theApp->Run();
00236 delete theApp;
00237 theApp = 0;
00238 }
00239
00240 return status;
00241 }