CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CombinationGenerator.h
Go to the documentation of this file.
1 #ifndef _CombinationGenerator_H_
2 #define _CombinationGenerator_H_
3 
5 #include <vector>
6 #include <stack>
7 #include <algorithm>
8 #include <functional>
9 
18 template<class T>
20 
21 public:
22 
23  typedef std::vector<T> Collection;
24 
25  typedef std::vector<Collection> Combination;
26  typedef std::vector<Combination> VectorOfCombinations;
27 
31  std::vector<Combination>
32  combinations(const Collection & data, int numberOfCollections) const
33  {
34  std::vector<Combination> combinations;
35  Collection sorted = data;
36 
37  // Sort if needed
38  if (prev_permutation(sorted.begin(), sorted.end())) {
39  sort(sorted.begin(), sorted.end());
40  }
41 
42  // Create sorted partitions
43  PartitionGenerator aPartitionGenerator;
44  std::vector< std::vector<PartitionGenerator::Partition> > partitions
45  = aPartitionGenerator.sortedPartitions(data.size());
46 
47  // Use partitions of size 'numberOfCollections' only
48  for (std::vector<PartitionGenerator::Partition>::const_iterator idiv
49  = partitions[numberOfCollections-1].begin();
50  idiv != partitions[numberOfCollections-1].end(); idiv++) {
51 
52  const PartitionGenerator::Partition& partition = *idiv;
53  std::vector<Combination> subCombinations
54  = this->combinations(data, partition);
55  for ( typename std::vector<Combination>::const_iterator iComb
56  = subCombinations.begin();
57  iComb != subCombinations.end(); iComb++) {
58  combinations.push_back(*iComb);
59  }
60  }
61  return combinations;
62  }
63 
64 
68  std::vector<Combination>
70  const PartitionGenerator::Partition & partition) const
71  {
72 
73  std::vector<Combination> combinations;
74 
75  // Check that sum of collection sizes in 'partition'
76  // amounts to number of elements in 'data'
77  int nElts = 0;
78  for (PartitionGenerator::Partition::const_iterator iSize
79  = partition.begin(); iSize != partition.end(); iSize++) {
80  nElts += *iSize;
81  }
82  if (nElts != data.size()) return combinations;
83 
84  Collection sortedData = data;
85  // Sort if needed
86  if (prev_permutation(sortedData.begin(), sortedData.end())) {
87  sort(sortedData.begin(), sortedData.end());
88  }
89 
90  // Create initial combination and put it on the stack
92  comb.push_back(sortedData);
93  if (partition.size() == 1) {
94  // Return only one combination with only one collection
95  combinations.push_back(comb);
96  return combinations;
97  }
98  std::stack<Combination> cStack;
99  cStack.push(comb);
100 
101  // Sort partitions by size
102  // Let 'sortedPartition' = ( n0, n1,... nk, nk+1,... nm )
103  // Ordering is >= to speed up partitioning: n0 >= n1 >=... >= nm
104  PartitionGenerator::Partition sortedPartition = partition;
105  sort(sortedPartition.begin(), sortedPartition.end(), std::greater_equal<int>());
106 
107  while (!cStack.empty()) {
108 
109  // 'combination' popped out of the stack
110  Combination combination = cStack.top(); cStack.pop();
111 
112  // At this stage 'combination' is made of collections
113  // of sizes ( n0+n1+...+nk, nk+1,... nm )
114  // Now generate all combinations obtained by splitting
115  // the first collection of 'combination' in two,
116  // according to Partition 'biPartition' = (n0+n1+...+nk-1, nk)
117  int k = sortedPartition.size() - combination.size();
118  int size = 0;
119  for (int iColl = 0; iColl != k; iColl++) {
120  size += sortedPartition[iColl];
121  }
122  PartitionGenerator::Partition biPartition(2);
123  biPartition[0] = size;
124  biPartition[1] = sortedPartition[k];
125 
126  VectorOfCombinations subCombinations
127  = splitInTwoCollections(combination[0], biPartition[0]);
128  for (typename std::vector<Combination>::const_iterator iComb = subCombinations.begin();
129  iComb != subCombinations.end(); iComb++) {
130 
131  // Check ordering of successive bins of equal size
132  if (combination.size() > 1) {
133  if ((*iComb)[1].size() == combination[1].size()) {
134  Collection adjBins;
135  adjBins.push_back((*iComb)[1][0]);
136  adjBins.push_back(combination[1][0]);
137  // Drop 'combination' if successive bins of equal size not ordered
138  // i.e. if previous permutation exists
139  if (prev_permutation(adjBins.begin(), adjBins.end())) continue;
140  }
141  }
142 
143  // Append remaining collections of 'combination'
144  Combination merged = *iComb;
145  typename Combination::const_iterator it = combination.begin(); it++;
146  for ( ; it != combination.end(); it++) { merged.push_back(*it); }
147 
148  // Store combination 'merged' if partitioning is complete,
149  // otherwise put it on the stack for further partitioning.
150  if (merged.size() == sortedPartition.size()) {
151  combinations.push_back(merged);
152  } else {
153  cStack.push(merged);
154  }
155  }
156  }
157  return combinations;
158  }
159 
160 
163  std::vector<Combination> combinations(const Collection & data) const
164  {
165 
166  std::vector<Combination> combinations;
167  Collection sorted = data;
168  // Sort if needed
169  if (prev_permutation(sorted.begin(), sorted.end())) {
170  sort(sorted.begin(), sorted.end());
171  }
172 
173  PartitionGenerator aPartitionGenerator;
174  std::vector<PartitionGenerator::Partition> partitions
175  = aPartitionGenerator.partitions(data.size());
176 
177  for (std::vector<PartitionGenerator::Partition>::const_iterator idiv
178  = partitions.begin(); idiv != partitions.end(); idiv++) {
179  const PartitionGenerator::Partition& partition = *idiv;
180 
181  std::vector<Combination> subCombinations
182  = this->combinations(data, partition);
183  for ( typename std::vector<Combination>::const_iterator iComb
184  = subCombinations.begin();
185  iComb != subCombinations.end(); iComb++) {
186  combinations.push_back(*iComb);
187  }
188  }
189  return combinations;
190  }
191 
192 
193 private:
194 
199  int sizeFirst) const
200  {
201  std::vector<Combination> combinations;
202  std::stack<Combination> cStack;
203 
204  // Create first combination with 2 partitions
205  Combination comb; comb.push_back(data); comb.push_back(Collection());
206  cStack.push(comb);
207 
208  while (!cStack.empty()) {
209  Combination combination = cStack.top();
210  cStack.pop();
211 
212  Collection collection = combination[0];
213  std::vector<Combination> subCombinations = separateOneElement(collection);
214 
215  for ( typename std::vector<Combination>::const_iterator iComb = subCombinations.begin();
216  iComb != subCombinations.end(); iComb++) {
217 
218  Collection second = combination[1];
219  second.push_back((*iComb)[1][0]);
220 
221  // Abandon current combination if not ordered,
222  // i.e. if previous permutation exists
223  bool ordered = !prev_permutation(second.begin(), second.end());
224  if (!ordered) continue;
225  next_permutation(second.begin(), second.end());
226 
227  if ((*iComb)[0].size() == second.size()) {
228  Collection adjBins;
229  adjBins.push_back((*iComb)[0][0]);
230  adjBins.push_back(second[0]);
231  // Abandon current combination if successive bins of equal size
232  // not ordered, i.e. if previous permutation exists
233  if (prev_permutation(adjBins.begin(), adjBins.end())) continue;
234  }
235 
236  Combination stored;
237  stored.push_back((*iComb)[0]);
238  stored.push_back(second);
239 
240  if (stored[0].size() == sizeFirst) {
241  combinations.push_back(stored);
242  } else {
243  cStack.push(stored);
244  }
245  }
246  }
247  return combinations;
248  }
249 
253  std::vector<Combination> separateOneElement(const Collection & data) const
254  {
255  std::vector<Combination> combinations;
256  for ( typename Collection::const_iterator i = data.begin(); i != data.end(); i++) {
258  Collection single; single.push_back(*i);
259  Collection coll;
260  typename Collection::const_iterator j = data.begin();
261  for ( ; j != i; j++) { coll.push_back(*j); }
262  j++;
263  for ( ; j != data.end(); j++) { coll.push_back(*j); }
264  comb.push_back(coll); comb.push_back(single);
265  combinations.push_back(comb);
266  }
267  return combinations;
268  }
269 
270 };
271 
272 #endif
std::vector< std::vector< Partition > > sortedPartitions(int collectionSize, int minCollectionSize=1) const
int i
Definition: DBlmapReader.cc:9
VectorOfCombinations splitInTwoCollections(const Collection &data, int sizeFirst) const
U second(std::pair< T, U > const &p)
std::vector< Partition > partitions(int collectionSize, int minCollectionSize=1) const
std::vector< Combination > combinations(const Collection &data, int numberOfCollections) const
dictionary comb
std::vector< Collection > Combination
int j
Definition: DBlmapReader.cc:9
std::vector< Combination > combinations(const Collection &data, const PartitionGenerator::Partition &partition) const
JetCorrectorParametersCollection coll
Definition: classes.h:10
std::vector< int > Partition
std::vector< T > Collection
std::vector< Combination > VectorOfCombinations
std::vector< Combination > combinations(const Collection &data) const
#define begin
Definition: vmac.h:30
std::vector< Combination > separateOneElement(const Collection &data) const
tuple size
Write out results.