00001 #ifndef RecoTauTag_RecoTau_CombinatoricGenerator_h
00002 #define RecoTauTag_RecoTau_CombinatoricGenerator_h
00003
00004 #include <boost/iterator/iterator_facade.hpp>
00005 #include <boost/iterator/filter_iterator.hpp>
00006 #include <boost/iterator/transform_iterator.hpp>
00007 #include <vector>
00008 #include <set>
00009 #include <memory>
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 namespace reco { namespace tau {
00048
00049 template <typename T>
00050 class Combinatoric
00051 {
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 typedef typename T::const_iterator value_iter;
00066 typedef typename T::value_type value_type;
00067 typedef size_t index_type;
00068 typedef typename std::vector<index_type> indices_collection;
00069 typedef typename indices_collection::const_iterator index_iter;
00070 typedef typename std::set<index_type> indices_set;
00071
00072 class IndexInSet {
00073
00074 public:
00075 IndexInSet(const indices_set& combo, bool negate):
00076 combo_(combo),negate_(negate){}
00077 bool operator()(const index_type& index) const {
00078 return (negate_) ? !combo_.count(index) : combo_.count(index);
00079 }
00080 private:
00081 indices_set combo_;
00082 bool negate_;
00083 };
00084
00085 class ValueAccessor : public std::unary_function<index_type const&, const value_type&>
00086 {
00087
00088
00089 public:
00090 ValueAccessor(const value_iter& begin):
00091 begin_(begin){}
00092 const value_type& operator()(index_type const & index) const {
00093 return *(begin_+index);
00094 }
00095 private:
00096 value_iter begin_;
00097 };
00098
00099 public:
00100
00101 Combinatoric(const value_iter& begin, const indices_collection& indices,
00102 indices_collection combo, bool done):
00103 begin_(begin), combo_(combo.begin(), combo.end()),
00104 comboSet_(combo.begin(), combo.end()),
00105 indices_(indices),
00106 done_(done),
00107 valueAccessor_(begin), inChoice_(comboSet_, false),
00108 notInChoice_(comboSet_, true) {}
00109
00110 typedef typename boost::filter_iterator<IndexInSet, index_iter> ComboIter;
00111 typedef typename boost::transform_iterator<ValueAccessor, ComboIter> ValueIter;
00112
00114 ValueIter combo_begin() const { return ValueIter(ComboIter(inChoice_, indices_.begin(), indices_.end()), valueAccessor_); }
00116 ValueIter combo_end() const { return ValueIter(ComboIter(inChoice_, indices_.end(), indices_.end()), valueAccessor_); }
00117
00119 ValueIter remainder_end() const { return ValueIter(ComboIter(notInChoice_, indices_.end(), indices_.end()), valueAccessor_); }
00121 ValueIter remainder_begin() const { return ValueIter(ComboIter(notInChoice_, indices_.begin(), indices_.end()), valueAccessor_); }
00122
00124 Combinatoric<T> next() const
00125 {
00126
00127
00128
00129
00130
00131 indices_collection newCombo(combo_);
00132
00133
00134
00135
00136
00137
00138
00139 size_t distanceFromEnd = 0;
00140 size_t nElements = indices_.size();
00141 indices_collection::reverse_iterator pos = newCombo.rbegin();
00142 for(; pos != newCombo.rend(); ++pos, ++distanceFromEnd)
00143 {
00144
00145
00146 if( *pos < (nElements - 1 - distanceFromEnd) )
00147 {
00148 (*pos)++;
00149 break;
00150 } else {
00151
00152 (*pos) = nElements;
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161 index_type next_pos_value = (*pos)+1;
00162
00163 indices_collection::iterator forward_pos = pos.base();
00164
00165
00166
00167 bool done = true;
00168 if (forward_pos != newCombo.begin()) {
00169 done = false;
00170 for (; forward_pos != newCombo.end(); ++forward_pos, ++next_pos_value) {
00171 *forward_pos = next_pos_value;
00172 }
00173 }
00174
00175
00176
00177
00178
00179
00180 return Combinatoric<T>(begin_, indices_, newCombo, done);
00181 }
00182
00183
00184 bool done() const { return done_; }
00185
00187 const indices_set& combo() const { return comboSet_; }
00188
00190 bool operator==(const Combinatoric<T>& rhs) const
00191 {
00192 return (this->combo() == rhs.combo() && this->done() == rhs.done());
00193 }
00194
00195 private:
00196
00197
00198 value_iter begin_;
00199 indices_collection combo_;
00200 indices_set comboSet_;
00201 indices_collection indices_;
00202 bool done_;
00203 ValueAccessor valueAccessor_;
00204 IndexInSet inChoice_;
00205 IndexInSet notInChoice_;
00206 };
00207
00208 template<typename T>
00209 class CombinatoricIterator : public boost::iterator_facade<
00210 CombinatoricIterator<T>,
00211 const Combinatoric<T>,
00212 boost::forward_traversal_tag>
00213 {
00214
00215 public:
00216 typedef Combinatoric<T> value_type;
00217 explicit CombinatoricIterator(const Combinatoric<T>& c):node_(c) {}
00218
00219 private:
00220 friend class boost::iterator_core_access;
00221
00222 bool equal(CombinatoricIterator const& other) const {
00223 return this->node_ == other.node_;
00224 }
00225
00226 void increment() {
00227 node_ = node_.next();
00228 }
00229
00230 const Combinatoric<T>& dereference() const {
00231 return node_;
00232 }
00233
00234 Combinatoric<T> node_;
00235 };
00236
00237 template<typename T>
00238 class CombinatoricGenerator
00239 {
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 typedef typename T::const_iterator value_iter;
00251 typedef typename T::value_type value_type;
00252 typedef size_t index_type;
00253 typedef typename std::vector<index_type> indices_collection;
00254 typedef typename indices_collection::iterator index_iter;
00255 typedef typename std::set<index_type> indices_set;
00256
00257 public:
00258
00259 typedef std::auto_ptr<CombinatoricIterator<T> > CombIterPtr;
00260 typedef CombinatoricIterator<T> iterator;
00261 typedef typename iterator::value_type::ValueIter combo_iterator;
00262
00263 explicit CombinatoricGenerator(const value_iter& begin, const value_iter& end, size_t choose)
00264 {
00265
00266 indices_collection initialCombo(choose);
00267 indices_collection finalCombo(choose);
00268
00269 size_t totalElements = end-begin;
00270
00271 indices_collection allIndices(totalElements);
00272 for(size_t i=0; i < totalElements; ++i)
00273 {
00274 allIndices[i] = i;
00275 }
00276
00277 for(size_t i=0; i < choose; ++i)
00278 {
00279 initialCombo[i] = i;
00280
00281 finalCombo[i] = totalElements;
00282 }
00283
00284 beginning_ = CombIterPtr(new CombinatoricIterator<T>(Combinatoric<T>(
00285 begin, allIndices, initialCombo, false)));
00286
00287 ending_ = CombIterPtr(new CombinatoricIterator<T>(Combinatoric<T>(
00288 begin, allIndices, finalCombo, true)));
00289 }
00290
00291 CombinatoricIterator<T> begin() {
00292 return *beginning_;
00293 }
00294
00295 CombinatoricIterator<T> end() {
00296 return *ending_;
00297 }
00298
00299 private:
00300 CombIterPtr beginning_;
00301 CombIterPtr ending_;
00302 };
00303
00304 } }
00305 #endif