CMS 3D CMS Logo

Combinatorics.cc

Go to the documentation of this file.
00001 /*
00002  * Combinatorics.cpp
00003  *
00004  * 03/04/2006 kasselmann@physik.rwth-aachen.de
00005  * 19/08/2007 giffels@physik.rwth-aachen.de
00006  *
00007  */
00008 //framework
00009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00010 
00011 // Own header
00012 #include "HeavyFlavorAnalysis/Skimming/interface/Combinatorics.h"
00013 
00014 using namespace std;
00015 
00016 // **************************************************************************
00017 //  Class Constructor
00018 // **************************************************************************
00019 Combinatorics::Combinatorics(Int_t SetQuantity, Int_t SubsetQuantity) :
00020 
00021   m_SetQuantity(SetQuantity),
00022   m_SubsetQuantity(SubsetQuantity)
00023 {
00024   // Get permutations
00025   CalculatePermutations();
00026 }
00027 
00028 
00029 // **************************************************************************
00030 //  Class Destructor
00031 // **************************************************************************
00032 Combinatorics::~Combinatorics() 
00033 {}
00034 
00035 
00036 // **************************************************************************
00037 //  Get subset permutations 
00038 // **************************************************************************
00039 vector <vector <UInt_t> > Combinatorics::GetPermutations() 
00040 {
00041   return m_Permutations;
00042 }
00043 
00044 // **************************************************************************
00045 //  Calculate all subset permutations 
00046 // **************************************************************************
00047 Int_t Combinatorics::CalculatePermutations() 
00048 {
00049   if (m_SetQuantity < 1 || m_SubsetQuantity < 1 || (m_SetQuantity < m_SubsetQuantity)) 
00050     {
00051       edm::LogWarning("Combinatorics") << "[Combinatorics] No valid choice of set or subset!" << endl;
00052       return -1;
00053     }
00054   
00055   Int_t* currentSubset = new Int_t[m_SubsetQuantity];
00056   Int_t* currentMapping = new Int_t[m_SetQuantity];
00057 
00058   initial_subset(m_SubsetQuantity, currentSubset);    
00059   do
00060     {
00061       initial_permutation(m_SetQuantity, currentMapping);        
00062       do
00063         {
00064           for (UShort_t i = 0; i < m_SubsetQuantity; i++) 
00065             {
00066               m_Subset.push_back(currentSubset[currentMapping[i]]);
00067             }
00068           m_Permutations.push_back(m_Subset);
00069           m_Subset.clear();
00070         }
00071       while (next_permutation(m_SubsetQuantity, currentMapping));
00072     }
00073   while (next_subset(m_SetQuantity, m_SubsetQuantity, currentSubset));
00074 
00075   delete[] currentSubset;
00076   delete[] currentMapping;
00077 
00078   return 0;
00079 }
00080 
00081 
00082 // **************************************************************************
00083 // Build initial permutation
00084 // **************************************************************************
00085 void Combinatorics::initial_permutation(int size, int *permutation)
00086 {
00087   for (int i = 0; i < size; i++) 
00088     {
00089       permutation[i] = i;
00090     }
00091 }
00092 
00093 
00094 // **************************************************************************
00095 // Build initial subset
00096 // **************************************************************************
00097 void Combinatorics::initial_subset(int k, int *subset)
00098 {
00099   for (int i = 0; i < k; i++) 
00100     {
00101       subset[i] = i;
00102     }
00103 }
00104 
00105 
00106 // **************************************************************************
00107 // Get next permutation if a next permutation exists
00108 // **************************************************************************
00109 Bool_t Combinatorics::next_permutation(int size, int *permutation)
00110 {
00111   int i, j, k;
00112   if (size < 2) return false;
00113   i = size - 2;
00114   
00115   while ((permutation[i] > permutation[i+1]) && (i != 0)) 
00116     {
00117       i--;
00118     }
00119   if ((i == 0) && (permutation[0] > permutation[1])) return false;
00120   
00121   k = i + 1;
00122   for (j = i + 2; j < size; j++ ) 
00123     {
00124       if ((permutation[j] > permutation[i]) && (permutation[j] < permutation[k])) 
00125         {
00126           k = j;
00127         }
00128     }
00129   
00130   // swap i and k 
00131   {
00132     int tmp = permutation[i];
00133     permutation[i] = permutation[k];
00134     permutation[k] = tmp;
00135   }
00136   
00137   for (j = i + 1; j <= ((size + i) / 2); j++) 
00138     {
00139       int tmp = permutation[j];
00140       permutation[j] = permutation[size + i - j];
00141       permutation[size + i - j] = tmp;
00142     }
00143 
00144   // return whether a next permutation exists
00145   return true;
00146 }
00147 
00148 
00149 // **************************************************************************
00150 // Get next subset if a next subset exists
00151 // 
00152 // n: the size of the set
00153 // k: the size of the subset
00154 // **************************************************************************
00155 Bool_t Combinatorics::next_subset(int n, int k, int *subset)
00156 {
00157   int i;
00158   int j;
00159   int jsave;
00160   bool done;
00161   
00162   if ( subset[0] < n-k )
00163     {
00164       done = false;
00165       jsave = k-1;
00166       for ( j = 0; j < k-1; j++ )
00167         {
00168           if ( subset[j] + 1 < subset[j+1] )
00169             {
00170               jsave = j;
00171               break;
00172             }
00173         }
00174       for ( i = 0; i < jsave; i++ ) subset[i] = i;
00175       subset[jsave] = subset[jsave] + 1;
00176     }
00177   else
00178     {
00179       done = true;
00180     }
00181   // return whether a next subset exists
00182   return !done;
00183 }
00184 
00185 
00186 // **************************************************************************
00187 //  Get all subset combinations
00188 // **************************************************************************
00189 vector < vector <UInt_t> > Combinatorics::GetCombinations()
00190 {
00191   if (m_Permutations.size() == 0) 
00192     {
00193       LogDebug("Combinatorics") << "Nothing to do." << endl;
00194       return m_Combinations;
00195     }
00196   
00197   m_Combinations.push_back(m_Permutations.at(0));
00198 
00199   for (UInt_t i = 1; i < m_Permutations.size(); i++)
00200     {
00201       if (!EqualPermutation(m_Combinations.back(), m_Permutations.at(i))) 
00202         {
00203           m_Combinations.push_back(m_Permutations.at(i));
00204         }
00205     }
00206   return m_Combinations;
00207 }
00208 
00209 
00210 // **************************************************************************
00211 // Returns true if two permutations of four "int" are equal
00212 // (Equal means e.g.: 0123 = 1023 = 0132 = 1032)
00213 // **************************************************************************
00214 Int_t Combinatorics::EqualPermutation(vector<UInt_t> p1, vector <UInt_t> p2)
00215 {
00216   if (p1.size() != p2.size())
00217     {
00218       edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutation] permutations have different size!" << endl;
00219       return -1;
00220     }
00221   
00222   Float_t p1_sum = 0.0;
00223   Float_t p2_sum = 0.0;
00224 
00225   // Check whether permutations are equal (2^index)
00226   for (UInt_t i = 0; i < p1.size(); i++) p1_sum += (1 << p1.at(i));
00227   for (UInt_t i = 0; i < p2.size(); i++) p2_sum += (1 << p2.at(i));
00228   
00229   return (p1_sum == p2_sum ? 1 : 0);
00230 }
00231 
00232 
00233 // **************************************************************************
00234 //  Get combinations: 4 out of n 
00235 // 
00236 //  (The order of the first and second two is not important!
00237 //   0123 = 1023 = 0132 = 1032 are equal therefore)
00238 // **************************************************************************
00239 vector < vector <UInt_t> > Combinatorics::GetCombinations_2_2()
00240 {
00241   // combination vector returned
00242   vector< vector <UInt_t> > FinalCombinations; 
00243 
00244   if (m_Permutations.size() == 0) 
00245     {
00246       LogDebug("Combinatorics") << "[Combinatorics::GetCombinations_2_2] Nothing to do." << endl;
00247       return FinalCombinations;
00248     }
00249   
00250   // So far only for subsets of four indices
00251   if (m_SubsetQuantity != 4) 
00252     {
00253       edm::LogWarning("Combinatorics") << "[Combinatorics::GetCombinations_2_2] Subset must be 4." << endl;
00254       return FinalCombinations;
00255     }
00256 
00257   // Skip specific permutations
00258   Skip_2_2(m_Permutations, FinalCombinations);
00259 
00260   return FinalCombinations;
00261 }
00262 
00263 
00264 // **************************************************************************
00265 //  Get combinations: 4 out of n 
00266 // 
00267 //  (The order of the last two is important only: 
00268 //   0123 = 1023 are equal therefore)
00269 // **************************************************************************
00270 vector < vector <UInt_t> > Combinatorics::GetCombinations_2_0()
00271 {
00272   // combination vector returned
00273   vector< vector <UInt_t> > FinalCombinations; 
00274 
00275   if (m_Permutations.size() == 0) 
00276     {
00277       LogDebug("Combinatorics") << "[Combinatorics::GetCombinations_2_0] Nothing to do." << endl;
00278       return FinalCombinations;
00279     }
00280   
00281   // So far only for subsets of four indices
00282   if (m_SubsetQuantity != 4) 
00283     {
00284       edm::LogWarning("Combinatorics") << "[Combinatorics::GetCombinations_2_0] Subset must be 4." << endl;
00285       return FinalCombinations;
00286     }
00287 
00288   // Skip specific permutations
00289   Skip_2_0(m_Permutations, FinalCombinations);
00290 
00291   return FinalCombinations;
00292 }
00293 
00294 
00295 // **************************************************************************
00296 // Skip permutation from p1 if already existing in p2
00297 // **************************************************************************
00298 void Combinatorics::Skip_2_0(vector <vector <UInt_t> > p1, 
00299                              vector <vector <UInt_t> > &p2)
00300 {
00301   Bool_t Skip = kFALSE;
00302 
00303   p2.push_back(p1.at(0));
00304   
00305   for (UShort_t i = 1; i < p1.size(); i++)
00306     {
00307       for (UShort_t j = 0; j < p2.size(); j++)
00308         {
00309           if (EqualPermutation_2_0(p1.at(i), p2.at(j))) 
00310             {
00311               Skip = kTRUE;
00312             }
00313         }
00314       if (!Skip) p2.push_back(p1.at(i));
00315 
00316       Skip = kFALSE;
00317     }
00318 }
00319 
00320 
00321 // **************************************************************************
00322 // Skip permutation from p1 if already existing in p2
00323 // **************************************************************************
00324 void Combinatorics::Skip_2_2(vector <vector <UInt_t> > p1, 
00325                              vector <vector <UInt_t> > &p2)
00326 {
00327   Bool_t Skip = kFALSE;
00328 
00329   p2.push_back(p1.at(0));
00330   
00331   for (UShort_t i = 1; i < p1.size(); i++)
00332     {
00333       for (UShort_t j = 0; j < p2.size(); j++)
00334         {
00335           if (EqualPermutation_2_2(p1.at(i), p2.at(j))) 
00336             {
00337               Skip = kTRUE;
00338             }
00339         }
00340       if (!Skip) p2.push_back(p1.at(i));
00341 
00342       Skip = kFALSE;
00343     }
00344 }
00345 
00346 
00347 // **************************************************************************
00348 // Returns true if the two first digm_ of two permutations are equal
00349 // e.g.: 0123 = 1023 
00350 // **************************************************************************
00351 Int_t Combinatorics::EqualPermutation_2_0(vector<UInt_t> p1, vector<UInt_t> p2)
00352 {
00353   if (p1.size() < 2) 
00354     {
00355       edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutation_2_0] permutation has wrong size!" << endl;
00356       return -1;
00357     }
00358   
00359   // Check whether permutations are equal
00360   if ( ((1 << p1.at(0)) + (1 << p1.at(1)) == (1 << p2.at(0)) + (1 << p2.at(1)) ) &&
00361        p1.at(2) == p2.at(2) &&  p1.at(3) == p2.at(3) )
00362     {
00363       return 1;
00364     }
00365   return 0;
00366 }
00367 
00368 
00369 // **************************************************************************
00370 // Returns true if two permutations of four "int" are equal
00371 // e.g.: 0123 = 1023 = 0132 = 1032
00372 // **************************************************************************
00373 Int_t Combinatorics::EqualPermutation_2_2(vector<UInt_t> p1, vector<UInt_t> p2)
00374 {
00375   // Returns true if two permutations of four "int" are equal 
00376   // (equal means e.g.: 0123 = 1023 = 0132 = 1032)
00377 
00378   if (p1.size() != 4 && p2.size() != 4) 
00379     {
00380       edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutationTwoByTwo] permutation(s) have wrong size!" << endl;
00381       return -1;
00382     }
00383   
00384   // Check whether permutations are equal (2^index)
00385   if ( ((1 << p1.at(0)) + (1 << p1.at(1)) == (1 << p2.at(0)) + (1 << p2.at(1)) ) && 
00386        ((1 << p1.at(2)) + (1 << p1.at(3)) == (1 << p2.at(2)) + (1 << p2.at(3)) ) ) 
00387     {
00388       return 1;
00389     }
00390   return 0;
00391 }
00392 
00393 
00394 // **************************************************************************
00395 // Returns true if two permutations of four are "equal"
00396 // e.g.: 0123 = 1023 
00397 // **************************************************************************
00398 Int_t Combinatorics::EqualPermutation_N_1(vector<UInt_t> p1, vector<UInt_t> p2)
00399 {
00400   // Returns true if two permutations of four "int" are equal 
00401   // (equal means e.g.: 012 = 102)
00402 
00403   if (p1.size() !=  p2.size()) 
00404     {
00405       edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutationTwoByTwo] permutation(s) have wrong size!" << endl;
00406       return -1;
00407     }
00408   
00409   return (EqualPermutation(p1, p2) && p1.back() == p2.back() ? 1 : 0);
00410 }
00411 
00412 
00413 // **************************************************************************
00414 //  Get combinations "N by 1"
00415 // **************************************************************************
00416 vector < vector <UInt_t> > Combinatorics::GetCombinations_N_1()
00417 {
00418   // Get combinations 
00419   m_Combinations.clear();
00420   GetCombinations();
00421   
00422   // combination vector returned
00423   vector < vector <UInt_t> > FinalCombinations;
00424 
00425   if (m_Combinations.size() == 0) 
00426     {
00427       LogDebug("Combinatorics") << "[Combinatorics::GetCombinationsThreeByOne] Nothing to do." << endl;
00428       return FinalCombinations;
00429     }
00430   
00431   for (UInt_t i = 0; i < m_Combinations.size(); i++)
00432     {
00433       vector <UInt_t> RotatingPermutation = m_Combinations.at(i);
00434       FinalCombinations.push_back(m_Combinations.at(i));
00435 
00436       for (UInt_t j = 1; j < RotatingPermutation.size(); j++)
00437         {
00438           FinalCombinations.push_back(Rotate(RotatingPermutation,j));
00439         }
00440     }
00441   return FinalCombinations;
00442 }
00443 
00444 
00445 // **************************************************************************
00446 // Rotate permutation to the "left" by n digm_
00447 // **************************************************************************
00448 vector<UInt_t> Combinatorics::Rotate(vector <UInt_t> permutation, UInt_t digm_)
00449 {
00450   vector<UInt_t> p;
00451   vector<UInt_t> tmp;
00452   
00453   if (permutation.size() <= digm_) 
00454     {
00455       edm::LogWarning("Combinatorics") << "[Combinatorics::Rotate] WARNING: More rotations than digm_ in permutation!" << endl;   
00456     }
00457 
00458   // Save the first i digm_
00459   for (UInt_t i = 0; i < digm_; i++) 
00460     {
00461       tmp.push_back(permutation.at(i));
00462     }
00463   for (UInt_t j = 0; j < permutation.size() - digm_; j++)
00464     {
00465       p.push_back(permutation.at(j + digm_));
00466     }
00467   for (UInt_t k = 0; k < digm_; k++) p.push_back(tmp.at(k));
00468 
00469   return p;
00470 }
00471 
00472   
00473 // **************************************************************************
00474 //  Print one permutation
00475 // **************************************************************************
00476 void Combinatorics::Print(vector<UInt_t> p)
00477 {
00478   // Print permutations
00479   for (UShort_t i = 0; i < p.size(); i++)
00480     {
00481       LogDebug("Combinatorics") << (p.at(i));
00482     }
00483   LogDebug("Combinatorics") << endl;
00484 }
00485 
00486 
00487 // **************************************************************************
00488 //  Print permutations 
00489 // **************************************************************************
00490 void Combinatorics::Print(vector <vector <UInt_t> > p)
00491 {
00492   LogDebug("Combinatorics") << "**************" << endl;
00493   LogDebug("Combinatorics") << "Permutations: " << p.size() << endl;
00494 
00495   // Print permutations
00496   for (UShort_t i = 0; i < p.size(); i++)
00497     {
00498       for(UShort_t j = 0; j < (p.at(0)).size(); j++) LogDebug("Combinatorics") << (p.at(i)).at(j);
00499       LogDebug("Combinatorics") << endl;
00500     }
00501 }
00502 
00503 
00504 
00505 
00506 
00507 
00508 
00509 
00510 
00511 
00512 

Generated on Tue Jun 9 17:37:35 2009 for CMSSW by  doxygen 1.5.4