CMS 3D CMS Logo

Combinatorics.cc
Go to the documentation of this file.
1 /*
2  * Combinatorics.cpp
3  *
4  * 03/04/2006 kasselmann@physik.rwth-aachen.de
5  * 19/08/2007 giffels@physik.rwth-aachen.de
6  *
7  */
8 //framework
10 
11 // Own header
13 
14 using namespace std;
15 
16 // **************************************************************************
17 // Class Constructor
18 // **************************************************************************
19 Combinatorics::Combinatorics(Int_t SetQuantity, Int_t SubsetQuantity)
20  :
21 
22  m_SetQuantity(SetQuantity),
23  m_SubsetQuantity(SubsetQuantity) {
24  // Get permutations
26 }
27 
28 // **************************************************************************
29 // Class Destructor
30 // **************************************************************************
32 
33 // **************************************************************************
34 // Get subset permutations
35 // **************************************************************************
36 vector<vector<UInt_t> > Combinatorics::GetPermutations() { return m_Permutations; }
37 
38 // **************************************************************************
39 // Calculate all subset permutations
40 // **************************************************************************
43  edm::LogWarning("Combinatorics") << "[Combinatorics] No valid choice of set or subset!" << endl;
44  return -1;
45  }
46 
47  Int_t* currentSubset = new Int_t[m_SubsetQuantity];
48  Int_t* currentMapping = new Int_t[m_SetQuantity];
49 
50  initial_subset(m_SubsetQuantity, currentSubset);
51  do {
52  initial_permutation(m_SetQuantity, currentMapping);
53  do {
54  for (UShort_t i = 0; i < m_SubsetQuantity; i++) {
55  m_Subset.push_back(currentSubset[currentMapping[i]]);
56  }
57  m_Permutations.push_back(m_Subset);
58  m_Subset.clear();
59  } while (next_permutation(m_SubsetQuantity, currentMapping));
60  } while (next_subset(m_SetQuantity, m_SubsetQuantity, currentSubset));
61 
62  delete[] currentSubset;
63  delete[] currentMapping;
64 
65  return 0;
66 }
67 
68 // **************************************************************************
69 // Build initial permutation
70 // **************************************************************************
71 void Combinatorics::initial_permutation(int size, int* permutation) {
72  for (int i = 0; i < size; i++) {
73  permutation[i] = i;
74  }
75 }
76 
77 // **************************************************************************
78 // Build initial subset
79 // **************************************************************************
80 void Combinatorics::initial_subset(int k, int* subset) {
81  for (int i = 0; i < k; i++) {
82  subset[i] = i;
83  }
84 }
85 
86 // **************************************************************************
87 // Get next permutation if a next permutation exists
88 // **************************************************************************
89 Bool_t Combinatorics::next_permutation(int size, int* permutation) {
90  int i, j, k;
91  if (size < 2)
92  return false;
93  i = size - 2;
94 
95  while ((permutation[i] > permutation[i + 1]) && (i != 0)) {
96  i--;
97  }
98  if ((i == 0) && (permutation[0] > permutation[1]))
99  return false;
100 
101  k = i + 1;
102  for (j = i + 2; j < size; j++) {
103  if ((permutation[j] > permutation[i]) && (permutation[j] < permutation[k])) {
104  k = j;
105  }
106  }
107 
108  // swap i and k
109  {
110  int tmp = permutation[i];
111  permutation[i] = permutation[k];
112  permutation[k] = tmp;
113  }
114 
115  for (j = i + 1; j <= ((size + i) / 2); j++) {
116  int tmp = permutation[j];
117  permutation[j] = permutation[size + i - j];
118  permutation[size + i - j] = tmp;
119  }
120 
121  // return whether a next permutation exists
122  return true;
123 }
124 
125 // **************************************************************************
126 // Get next subset if a next subset exists
127 //
128 // n: the size of the set
129 // k: the size of the subset
130 // **************************************************************************
131 Bool_t Combinatorics::next_subset(int n, int k, int* subset) {
132  int i;
133  int j;
134  int jsave;
135  bool done;
136 
137  if (subset[0] < n - k) {
138  done = false;
139  jsave = k - 1;
140  for (j = 0; j < k - 1; j++) {
141  if (subset[j] + 1 < subset[j + 1]) {
142  jsave = j;
143  break;
144  }
145  }
146  for (i = 0; i < jsave; i++)
147  subset[i] = i;
148  subset[jsave] = subset[jsave] + 1;
149  } else {
150  done = true;
151  }
152  // return whether a next subset exists
153  return !done;
154 }
155 
156 // **************************************************************************
157 // Get all subset combinations
158 // **************************************************************************
159 vector<vector<UInt_t> > Combinatorics::GetCombinations() {
160  if (m_Permutations.empty()) {
161  LogDebug("Combinatorics") << "Nothing to do." << endl;
162  return m_Combinations;
163  }
164 
165  m_Combinations.push_back(m_Permutations.at(0));
166 
167  for (UInt_t i = 1; i < m_Permutations.size(); i++) {
168  if (!EqualPermutation(m_Combinations.back(), m_Permutations.at(i))) {
169  m_Combinations.push_back(m_Permutations.at(i));
170  }
171  }
172  return m_Combinations;
173 }
174 
175 // **************************************************************************
176 // Returns true if two permutations of four "int" are equal
177 // (Equal means e.g.: 0123 = 1023 = 0132 = 1032)
178 // **************************************************************************
179 Int_t Combinatorics::EqualPermutation(const vector<UInt_t>& p1, const vector<UInt_t>& p2) {
180  if (p1.size() != p2.size()) {
181  edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutation] permutations have different size!" << endl;
182  return -1;
183  }
184 
185  Float_t p1_sum = 0.0;
186  Float_t p2_sum = 0.0;
187 
188  // Check whether permutations are equal (2^index)
189  for (UInt_t i = 0; i < p1.size(); i++)
190  p1_sum += (1 << p1.at(i));
191  for (UInt_t i = 0; i < p2.size(); i++)
192  p2_sum += (1 << p2.at(i));
193 
194  return (p1_sum == p2_sum ? 1 : 0);
195 }
196 
197 // **************************************************************************
198 // Get combinations: 4 out of n
199 //
200 // (The order of the first and second two is not important!
201 // 0123 = 1023 = 0132 = 1032 are equal therefore)
202 // **************************************************************************
203 vector<vector<UInt_t> > Combinatorics::GetCombinations_2_2() {
204  // combination vector returned
205  vector<vector<UInt_t> > FinalCombinations;
206 
207  if (m_Permutations.empty()) {
208  LogDebug("Combinatorics") << "[Combinatorics::GetCombinations_2_2] Nothing to do." << endl;
209  return FinalCombinations;
210  }
211 
212  // So far only for subsets of four indices
213  if (m_SubsetQuantity != 4) {
214  edm::LogWarning("Combinatorics") << "[Combinatorics::GetCombinations_2_2] Subset must be 4." << endl;
215  return FinalCombinations;
216  }
217 
218  // Skip specific permutations
219  Skip_2_2(m_Permutations, FinalCombinations);
220 
221  return FinalCombinations;
222 }
223 
224 // **************************************************************************
225 // Get combinations: 4 out of n
226 //
227 // (The order of the last two is important only:
228 // 0123 = 1023 are equal therefore)
229 // **************************************************************************
230 vector<vector<UInt_t> > Combinatorics::GetCombinations_2_0() {
231  // combination vector returned
232  vector<vector<UInt_t> > FinalCombinations;
233 
234  if (m_Permutations.empty()) {
235  LogDebug("Combinatorics") << "[Combinatorics::GetCombinations_2_0] Nothing to do." << endl;
236  return FinalCombinations;
237  }
238 
239  // So far only for subsets of four indices
240  if (m_SubsetQuantity != 4) {
241  edm::LogWarning("Combinatorics") << "[Combinatorics::GetCombinations_2_0] Subset must be 4." << endl;
242  return FinalCombinations;
243  }
244 
245  // Skip specific permutations
246  Skip_2_0(m_Permutations, FinalCombinations);
247 
248  return FinalCombinations;
249 }
250 
251 // **************************************************************************
252 // Skip permutation from p1 if already existing in p2
253 // **************************************************************************
254 void Combinatorics::Skip_2_0(const vector<vector<UInt_t> >& p1, vector<vector<UInt_t> >& p2) {
255  Bool_t Skip = kFALSE;
256 
257  p2.push_back(p1.at(0));
258 
259  for (UShort_t i = 1; i < p1.size(); i++) {
260  for (UShort_t j = 0; j < p2.size(); j++) {
261  if (EqualPermutation_2_0(p1.at(i), p2.at(j))) {
262  Skip = kTRUE;
263  }
264  }
265  if (!Skip)
266  p2.push_back(p1.at(i));
267 
268  Skip = kFALSE;
269  }
270 }
271 
272 // **************************************************************************
273 // Skip permutation from p1 if already existing in p2
274 // **************************************************************************
275 void Combinatorics::Skip_2_2(const vector<vector<UInt_t> >& p1, vector<vector<UInt_t> >& p2) {
276  Bool_t Skip = kFALSE;
277 
278  p2.push_back(p1.at(0));
279 
280  for (UShort_t i = 1; i < p1.size(); i++) {
281  for (UShort_t j = 0; j < p2.size(); j++) {
282  if (EqualPermutation_2_2(p1.at(i), p2.at(j))) {
283  Skip = kTRUE;
284  }
285  }
286  if (!Skip)
287  p2.push_back(p1.at(i));
288 
289  Skip = kFALSE;
290  }
291 }
292 
293 // **************************************************************************
294 // Returns true if the two first digm_ of two permutations are equal
295 // e.g.: 0123 = 1023
296 // **************************************************************************
297 Int_t Combinatorics::EqualPermutation_2_0(const vector<UInt_t>& p1, const vector<UInt_t>& p2) {
298  if (p1.size() < 2) {
299  edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutation_2_0] permutation has wrong size!" << endl;
300  return -1;
301  }
302 
303  // Check whether permutations are equal
304  if (((1 << p1.at(0)) + (1 << p1.at(1)) == (1 << p2.at(0)) + (1 << p2.at(1))) && p1.at(2) == p2.at(2) &&
305  p1.at(3) == p2.at(3)) {
306  return 1;
307  }
308  return 0;
309 }
310 
311 // **************************************************************************
312 // Returns true if two permutations of four "int" are equal
313 // e.g.: 0123 = 1023 = 0132 = 1032
314 // **************************************************************************
315 Int_t Combinatorics::EqualPermutation_2_2(const vector<UInt_t>& p1, const vector<UInt_t>& p2) {
316  // Returns true if two permutations of four "int" are equal
317  // (equal means e.g.: 0123 = 1023 = 0132 = 1032)
318 
319  if (p1.size() != 4 && p2.size() != 4) {
320  edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutationTwoByTwo] permutation(s) have wrong size!"
321  << endl;
322  return -1;
323  }
324 
325  // Check whether permutations are equal (2^index)
326  if (((1 << p1.at(0)) + (1 << p1.at(1)) == (1 << p2.at(0)) + (1 << p2.at(1))) &&
327  ((1 << p1.at(2)) + (1 << p1.at(3)) == (1 << p2.at(2)) + (1 << p2.at(3)))) {
328  return 1;
329  }
330  return 0;
331 }
332 
333 // **************************************************************************
334 // Returns true if two permutations of four are "equal"
335 // e.g.: 0123 = 1023
336 // **************************************************************************
337 Int_t Combinatorics::EqualPermutation_N_1(const vector<UInt_t>& p1, const vector<UInt_t>& p2) {
338  // Returns true if two permutations of four "int" are equal
339  // (equal means e.g.: 012 = 102)
340 
341  if (p1.size() != p2.size()) {
342  edm::LogWarning("Combinatorics") << "[Combinatorics::EqualPermutationTwoByTwo] permutation(s) have wrong size!"
343  << endl;
344  return -1;
345  }
346 
347  return (EqualPermutation(p1, p2) && p1.back() == p2.back() ? 1 : 0);
348 }
349 
350 // **************************************************************************
351 // Get combinations "N by 1"
352 // **************************************************************************
353 vector<vector<UInt_t> > Combinatorics::GetCombinations_N_1() {
354  // Get combinations
355  m_Combinations.clear();
356  GetCombinations();
357 
358  // combination vector returned
359  vector<vector<UInt_t> > FinalCombinations;
360 
361  if (m_Combinations.empty()) {
362  LogDebug("Combinatorics") << "[Combinatorics::GetCombinationsThreeByOne] Nothing to do." << endl;
363  return FinalCombinations;
364  }
365 
366  for (UInt_t i = 0; i < m_Combinations.size(); i++) {
367  vector<UInt_t> RotatingPermutation = m_Combinations.at(i);
368  FinalCombinations.push_back(m_Combinations.at(i));
369 
370  for (UInt_t j = 1; j < RotatingPermutation.size(); j++) {
371  FinalCombinations.push_back(Rotate(RotatingPermutation, j));
372  }
373  }
374  return FinalCombinations;
375 }
376 
377 // **************************************************************************
378 // Rotate permutation to the "left" by n digm_
379 // **************************************************************************
380 vector<UInt_t> Combinatorics::Rotate(const vector<UInt_t>& permutation, UInt_t digm_) {
381  vector<UInt_t> p;
382  vector<UInt_t> tmp;
383 
384  if (permutation.size() <= digm_) {
385  edm::LogWarning("Combinatorics") << "[Combinatorics::Rotate] WARNING: More rotations than digm_ in permutation!"
386  << endl;
387  }
388 
389  // Save the first i digm_
390  for (UInt_t i = 0; i < digm_; i++) {
391  tmp.push_back(permutation.at(i));
392  }
393  for (UInt_t j = 0; j < permutation.size() - digm_; j++) {
394  p.push_back(permutation.at(j + digm_));
395  }
396  for (UInt_t k = 0; k < digm_; k++)
397  p.push_back(tmp.at(k));
398 
399  return p;
400 }
401 
402 // **************************************************************************
403 // Print one permutation
404 // **************************************************************************
405 void Combinatorics::Print(const vector<UInt_t>& p) {
406  // Print permutations
407  for (UShort_t i = 0; i < p.size(); i++) {
408  LogDebug("Combinatorics") << (p.at(i));
409  }
410  LogDebug("Combinatorics") << endl;
411 }
412 
413 // **************************************************************************
414 // Print permutations
415 // **************************************************************************
416 void Combinatorics::Print(const vector<vector<UInt_t> >& p) {
417  LogDebug("Combinatorics") << "**************" << endl;
418  LogDebug("Combinatorics") << "Permutations: " << p.size() << endl;
419 
420  // Print permutations
421  for (UShort_t i = 0; i < p.size(); i++) {
422  for (UShort_t j = 0; j < (p.at(0)).size(); j++)
423  LogDebug("Combinatorics") << (p.at(i)).at(j);
424  LogDebug("Combinatorics") << endl;
425  }
426 }
#define LogDebug(id)
size
Write out results.
Int_t EqualPermutation_N_1(const std::vector< UInt_t > &permutation1, const std::vector< UInt_t > &permutation2)
std::vector< std::vector< UInt_t > > m_Combinations
Definition: Combinatorics.h:54
std::vector< std::vector< UInt_t > > GetCombinations()
Int_t EqualPermutation_2_2(const std::vector< UInt_t > &permutation1, const std::vector< UInt_t > &permutation2)
std::vector< std::vector< UInt_t > > GetCombinations_N_1()
Combinatorics(Int_t Set, Int_t Subset)
Int_t CalculatePermutations()
const Int_t m_SubsetQuantity
Definition: Combinatorics.h:50
std::vector< UInt_t > m_Subset
Definition: Combinatorics.h:52
Bool_t next_subset(int n, int k, int *subset)
const Int_t m_SetQuantity
Definition: Combinatorics.h:49
std::vector< std::vector< UInt_t > > GetCombinations_2_0()
Int_t EqualPermutation_2_0(const std::vector< UInt_t > &permutation1, const std::vector< UInt_t > &permutation2)
double p2[4]
Definition: TauolaWrapper.h:90
virtual ~Combinatorics()
std::vector< std::vector< UInt_t > > m_Permutations
Definition: Combinatorics.h:53
Bool_t next_permutation(int size, int *permutation)
void Skip_2_0(const std::vector< std::vector< UInt_t > > &permutation1, std::vector< std::vector< UInt_t > > &permutation2)
std::vector< std::vector< UInt_t > > GetPermutations()
std::vector< std::vector< UInt_t > > GetCombinations_2_2()
void Print(const std::vector< UInt_t > &permutation)
Int_t EqualPermutation(const std::vector< UInt_t > &permutation1, const std::vector< UInt_t > &permutation2)
void initial_permutation(int size, int *permutation)
double p1[4]
Definition: TauolaWrapper.h:89
void initial_subset(int k, int *subset)
tmp
align.sh
Definition: createJobs.py:716
std::vector< UInt_t > Rotate(const std::vector< UInt_t > &permutation, UInt_t digits)
void Skip_2_2(const std::vector< std::vector< UInt_t > > &permutation1, std::vector< std::vector< UInt_t > > &permutation2)