numeric
LimitedCombination.hpp
Go to the documentation of this file.
1 #ifndef __NUMERIC_LIMITED_COMBINATION_HPP__
2 #define __NUMERIC_LIMITED_COMBINATION_HPP__
3 
4 #include <map>
5 #include <vector>
6 #include <numeric/Combinatorics.hpp>
7 
8 namespace numeric {
9 
35 template<typename AtomType>
37 {
38  typedef uint32_t CoreType;
39  typedef std::map<AtomType, size_t> AtomType2CountMap;
40  typedef std::vector<AtomType> AtomTypeList;
41  typedef std::vector<CoreType> CombinationDescriptor;
42 
43  // Model with the number of available models of this type
44  AtomType2CountMap mAtomTypeAvailablilityMap;
45  AtomTypeList mAtomTypeList;
46 
47  std::vector<CoreType> mLimits;
48  std::vector<CoreType> mCurrentCombination;
49 
51  size_t mSize;
52  numeric::Mode mMode;
53 
58  void prepare()
59  {
60  CoreType currentType = 0;
61  typename AtomType2CountMap::const_iterator cit = mAtomTypeAvailablilityMap.begin();
62  for(; cit != mAtomTypeAvailablilityMap.end(); ++cit, ++currentType)
63  {
64  mAtomTypeList.push_back(cit->first);
65  size_t numberPerType = cit->second;
66  mLimits.at(currentType) = numberPerType;
67  }
68 
69  // Making sure this behaves like the other combinatorics loops
70  if(!next())
71  {
72  throw std::runtime_error("numeric::LimitedCombination::prepare: preparation failed "
73  "check the given parameters");
74  }
75  }
76 
81  std::vector<AtomType> mapToAtomTypes(const std::vector<CoreType>& combination) const
82  {
83  std::vector<AtomType> atomTypeList;
84  for(size_t coreType = 0; coreType < combination.size(); ++coreType)
85  {
86  size_t count = combination[coreType];
87  for(size_t i = 0; i < count; ++i)
88  {
89  atomTypeList.push_back( mAtomTypeList[coreType] );
90  }
91  }
92  return atomTypeList;
93  }
94 
95  bool increment(std::vector<uint32_t>& combination, const std::vector<uint32_t>& limits) const
96  {
97  for(size_t pos = 0; pos < combination.size(); ++pos)
98  {
99  if( combination[pos] < limits[pos] )
100  {
101  ++combination[pos];
102  if(pos == 0)
103  {
104  return true;
105  }
106 
107  // reset lower values after overflow
108  for(int lpos = pos-1; lpos >= 0; --lpos)
109  {
110  combination[lpos] = 0;
111  }
112  return true;
113  } else if(pos == combination.size() - 1)
114  {
115  return false;
116  }
117  }
118  throw std::runtime_error("numeric::LimitedCombination::increment internal error -- "
119  " please check consistency of your input");
120  }
121 
122 public:
129  LimitedCombination(const AtomType2CountMap& countMap, size_t size, numeric::Mode mode)
130  : mAtomTypeAvailablilityMap(countMap)
131  , mLimits(countMap.size(),0)
132  , mCurrentCombination(countMap.size(),0)
133  , mSize(size)
134  , mMode(mode)
135  {
136  size_t totalCount = totalNumberOfAtoms(mAtomTypeAvailablilityMap);
137  if(countMap.empty() || totalCount == 0)
138  {
139  throw std::invalid_argument("numeric::LimitedCombination no atoms to generate combination from -- check for empty map");
140  }
141  if(mSize > totalCount)
142  {
143  mSize = totalCount;
144  }
145 
146  prepare();
147  }
148 
153  static size_t totalNumberOfAtoms(const AtomType2CountMap& countMap)
154  {
155  typename AtomType2CountMap::const_iterator cit = countMap.begin();
156  size_t count = 0;
157  for(; cit != countMap.end(); ++cit)
158  {
159  count += cit->second;
160  }
161  return count;
162  }
163 
168  std::vector<AtomType> current() const
169  {
170  std::vector<AtomType> atomTypeList = mapToAtomTypes(mCurrentCombination);
171  std::sort(atomTypeList.begin(), atomTypeList.end());
172  return atomTypeList;
173  }
174 
175  size_t getCombinationSize(const std::vector<CoreType>& combination) const
176  {
177  size_t combinationSize = 0;
178  std::vector<CoreType>::const_iterator cit = combination.begin();
179  for(; cit != combination.end(); ++cit)
180  {
181  combinationSize += *cit;
182  }
183  return combinationSize;
184  }
185 
192  bool next()
193  {
194  while(true)
195  {
196  bool hasNext = increment(mCurrentCombination, mLimits);
197  if(hasNext)
198  {
199  // check for size constraint
200  size_t combinationSize = getCombinationSize(mCurrentCombination);
201 
202  switch(mMode)
203  {
204  case EXACT:
205  if(combinationSize != mSize)
206  {
207  continue;
208  }
209  break;
210  case MAX:
211  if(combinationSize > mSize)
212  {
213  continue;
214  }
215  break;
216  case MIN:
217  if(combinationSize < mSize)
218  {
219  continue;
220  }
221  break;
222  }
223  return true;
224  }
225 
226  return false;
227  }
228 
229  return false;
230  }
231 
232 };
233 
234 } // numeric
235 #endif // __NUMERIC_LIMITED_COMBINATION_HPP__
size_t getCombinationSize(const std::vector< CoreType > &combination) const
Definition: LimitedCombination.hpp:175
Definition: Circle.hpp:6
Compute combinatorics on a given set of limited but typed resources, e.g. for available resource A:2...
Definition: LimitedCombination.hpp:36
Definition: Combinatorics.hpp:82
Definition: Combinatorics.hpp:82
Mode
Definition: Combinatorics.hpp:82
bool next()
Definition: LimitedCombination.hpp:192
std::vector< AtomType > current() const
Definition: LimitedCombination.hpp:168
LimitedCombination(const AtomType2CountMap &countMap, size_t size, numeric::Mode mode)
Definition: LimitedCombination.hpp:129
static size_t totalNumberOfAtoms(const AtomType2CountMap &countMap)
Definition: LimitedCombination.hpp:153
Definition: Combinatorics.hpp:82