Go to the documentation of this file.00001 #ifndef _CombinationGenerator_H_
00002 #define _CombinationGenerator_H_
00003
00004 #include "CommonTools/Statistics/interface/PartitionGenerator.h"
00005 #include <vector>
00006 #include <stack>
00007 #include <algorithm>
00008 #include <functional>
00009
00018 template<class T>
00019 class CombinationGenerator {
00020
00021 public:
00022
00023 typedef std::vector<T> Collection;
00024
00025 typedef std::vector<Collection> Combination;
00026 typedef std::vector<Combination> VectorOfCombinations;
00027
00031 std::vector<Combination>
00032 combinations(const Collection & data, int numberOfCollections) const
00033 {
00034 std::vector<Combination> combinations;
00035 Collection sorted = data;
00036
00037
00038 if (prev_permutation(sorted.begin(), sorted.end())) {
00039 sort(sorted.begin(), sorted.end());
00040 }
00041
00042
00043 PartitionGenerator aPartitionGenerator;
00044 std::vector< std::vector<PartitionGenerator::Partition> > partitions
00045 = aPartitionGenerator.sortedPartitions(data.size());
00046
00047
00048 for (std::vector<PartitionGenerator::Partition>::const_iterator idiv
00049 = partitions[numberOfCollections-1].begin();
00050 idiv != partitions[numberOfCollections-1].end(); idiv++) {
00051
00052 const PartitionGenerator::Partition& partition = *idiv;
00053 std::vector<Combination> subCombinations
00054 = this->combinations(data, partition);
00055 for ( typename std::vector<Combination>::const_iterator iComb
00056 = subCombinations.begin();
00057 iComb != subCombinations.end(); iComb++) {
00058 combinations.push_back(*iComb);
00059 }
00060 }
00061 return combinations;
00062 }
00063
00064
00068 std::vector<Combination>
00069 combinations(const Collection & data,
00070 const PartitionGenerator::Partition & partition) const
00071 {
00072
00073 std::vector<Combination> combinations;
00074
00075
00076
00077 int nElts = 0;
00078 for (PartitionGenerator::Partition::const_iterator iSize
00079 = partition.begin(); iSize != partition.end(); iSize++) {
00080 nElts += *iSize;
00081 }
00082 if (nElts != data.size()) return combinations;
00083
00084 Collection sortedData = data;
00085
00086 if (prev_permutation(sortedData.begin(), sortedData.end())) {
00087 sort(sortedData.begin(), sortedData.end());
00088 }
00089
00090
00091 Combination comb;
00092 comb.push_back(sortedData);
00093 if (partition.size() == 1) {
00094
00095 combinations.push_back(comb);
00096 return combinations;
00097 }
00098 std::stack<Combination> cStack;
00099 cStack.push(comb);
00100
00101
00102
00103
00104 PartitionGenerator::Partition sortedPartition = partition;
00105 sort(sortedPartition.begin(), sortedPartition.end(), std::greater_equal<int>());
00106
00107 while (!cStack.empty()) {
00108
00109
00110 Combination combination = cStack.top(); cStack.pop();
00111
00112
00113
00114
00115
00116
00117 int k = sortedPartition.size() - combination.size();
00118 int size = 0;
00119 for (int iColl = 0; iColl != k; iColl++) {
00120 size += sortedPartition[iColl];
00121 }
00122 PartitionGenerator::Partition biPartition(2);
00123 biPartition[0] = size;
00124 biPartition[1] = sortedPartition[k];
00125
00126 VectorOfCombinations subCombinations
00127 = splitInTwoCollections(combination[0], biPartition[0]);
00128 for (typename std::vector<Combination>::const_iterator iComb = subCombinations.begin();
00129 iComb != subCombinations.end(); iComb++) {
00130
00131
00132 if (combination.size() > 1) {
00133 if ((*iComb)[1].size() == combination[1].size()) {
00134 Collection adjBins;
00135 adjBins.push_back((*iComb)[1][0]);
00136 adjBins.push_back(combination[1][0]);
00137
00138
00139 if (prev_permutation(adjBins.begin(), adjBins.end())) continue;
00140 }
00141 }
00142
00143
00144 Combination merged = *iComb;
00145 typename Combination::const_iterator it = combination.begin(); it++;
00146 for ( ; it != combination.end(); it++) { merged.push_back(*it); }
00147
00148
00149
00150 if (merged.size() == sortedPartition.size()) {
00151 combinations.push_back(merged);
00152 } else {
00153 cStack.push(merged);
00154 }
00155 }
00156 }
00157 return combinations;
00158 }
00159
00160
00163 std::vector<Combination> combinations(const Collection & data) const
00164 {
00165
00166 std::vector<Combination> combinations;
00167 Collection sorted = data;
00168
00169 if (prev_permutation(sorted.begin(), sorted.end())) {
00170 sort(sorted.begin(), sorted.end());
00171 }
00172
00173 PartitionGenerator aPartitionGenerator;
00174 std::vector<PartitionGenerator::Partition> partitions
00175 = aPartitionGenerator.partitions(data.size());
00176
00177 for (std::vector<PartitionGenerator::Partition>::const_iterator idiv
00178 = partitions.begin(); idiv != partitions.end(); idiv++) {
00179 const PartitionGenerator::Partition& partition = *idiv;
00180
00181 std::vector<Combination> subCombinations
00182 = this->combinations(data, partition);
00183 for ( typename std::vector<Combination>::const_iterator iComb
00184 = subCombinations.begin();
00185 iComb != subCombinations.end(); iComb++) {
00186 combinations.push_back(*iComb);
00187 }
00188 }
00189 return combinations;
00190 }
00191
00192
00193 private:
00194
00198 VectorOfCombinations splitInTwoCollections(const Collection & data,
00199 int sizeFirst) const
00200 {
00201 std::vector<Combination> combinations;
00202 std::stack<Combination> cStack;
00203
00204
00205 Combination comb; comb.push_back(data); comb.push_back(Collection());
00206 cStack.push(comb);
00207
00208 while (!cStack.empty()) {
00209 Combination combination = cStack.top();
00210 cStack.pop();
00211
00212 Collection collection = combination[0];
00213 std::vector<Combination> subCombinations = separateOneElement(collection);
00214
00215 for ( typename std::vector<Combination>::const_iterator iComb = subCombinations.begin();
00216 iComb != subCombinations.end(); iComb++) {
00217
00218 Collection second = combination[1];
00219 second.push_back((*iComb)[1][0]);
00220
00221
00222
00223 bool ordered = !prev_permutation(second.begin(), second.end());
00224 if (!ordered) continue;
00225 next_permutation(second.begin(), second.end());
00226
00227 if ((*iComb)[0].size() == second.size()) {
00228 Collection adjBins;
00229 adjBins.push_back((*iComb)[0][0]);
00230 adjBins.push_back(second[0]);
00231
00232
00233 if (prev_permutation(adjBins.begin(), adjBins.end())) continue;
00234 }
00235
00236 Combination stored;
00237 stored.push_back((*iComb)[0]);
00238 stored.push_back(second);
00239
00240 if (stored[0].size() == sizeFirst) {
00241 combinations.push_back(stored);
00242 } else {
00243 cStack.push(stored);
00244 }
00245 }
00246 }
00247 return combinations;
00248 }
00249
00253 std::vector<Combination> separateOneElement(const Collection & data) const
00254 {
00255 std::vector<Combination> combinations;
00256 for ( typename Collection::const_iterator i = data.begin(); i != data.end(); i++) {
00257 Combination comb;
00258 Collection single; single.push_back(*i);
00259 Collection coll;
00260 typename Collection::const_iterator j = data.begin();
00261 for ( ; j != i; j++) { coll.push_back(*j); }
00262 j++;
00263 for ( ; j != data.end(); j++) { coll.push_back(*j); }
00264 comb.push_back(coll); comb.push_back(single);
00265 combinations.push_back(comb);
00266 }
00267 return combinations;
00268 }
00269
00270 };
00271
00272 #endif