CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
IsoCounter.hh
Go to the documentation of this file.
1 #ifndef ISOCOUNTER_HH
2 #define ISOCOUNTER_HH
3 
4 
6 
7 namespace CASM {
8 
14  template<typename _Container, typename _value_type, typename _size_type, typename _Access, typename _Compare>
63  class IsoCounter;
64 
65  namespace CASM_TMP {
66  template<typename _Container, typename _value_type, typename _size_type, typename _Access, typename _Compare>
67  struct traits<IsoCounter<_Container, _value_type, _size_type, _Access, _Compare> > {
69  typedef _Container Container;
70  typedef _value_type value_type;
71  typedef _size_type size_type;
72  typedef _Access Access;
73  typedef _Compare Compare;
74  };
75  }
76 
77  template < typename _Container,
78  typename _value_type = typename _Container::value_type,
79  typename _size_type = typename _Container::size_type,
81  typename _Compare = CASM_TMP::MuchLessThan<_value_type> >
82  class IsoCounter : public BaseCounter<IsoCounter<_Container, _value_type, _size_type, _Access, _Compare> > {
84  using Base::_valid;
85  using Base::_initial;
86  using Base::_final;
87  using Base::_increment;
88  using Base::_current;
89  using Base::_upper;
90  using Base::_lower;
91  public:
92  typedef _Container Container;
93  typedef _value_type value_type;
94  typedef _size_type size_type;
95  typedef _Access Access;
96  typedef _Compare Compare;
97 
98  using Base::valid;
99  using Base::size;
100  using Base::compare;
101  using Base::initial;
102  using Base::final;
103  using Base::current;
104  using Base::operator();
105  using Base::operator[];
106  using Base::operator bool;
107 
111  IsoCounter() : IsoCounter(Container(), Container(), 0, 0) { }
112 
118  IsoCounter(const Container &_initial,
119  const Container &_final,
120  const value_type &_increment,
121  const value_type &_sum,
122  Access _access = Access(),
123  Compare _compare = Compare()) :
124  Base(_initial, _final, Array<value_type>(1, _increment), _access, _compare), m_sum_constraint(_sum) {
125  _init();
126  reset();
127  }
128 
129  const value_type &increment() const {
130  return _increment(0);
131  }
132 
133  value_type current_sum() const {
134  if(size() == 0)
135  return 0;
136  value_type result(current(0));
137  for(size_type i = 1; i < size(); i++) {
138  result += current(i);
139  }
140  return result;
141  }
142 
148  if(!valid())
149  return (*this);
150  size_type i(0), j(0);
151  bool continue_flag = valid();
152  value_type next_i, next_j;
153  for(i = 0; i + 1 < size(); i++) {
154  next_i = current(i) - increment();
155  if(compare(_upper(i), next_i) || compare(next_i, _lower(i)))
156  continue;
157  j = i + 1;
158  while(j < size() && !compare(_lower(j), _upper(j)))
159  j++;
160  if(j == size())
161  break;
162  next_j = current(j) + increment();
163  if(compare(_upper(j), next_j) || compare(next_j, _lower(j))) {
164  i = j - 1;
165  continue;
166  }
167 
168  _current(i) = next_i;
169  _current(j) = next_j;
170  //next_i -= m_increment;
171 
172  continue_flag = false;
173  break;
174  }
175 
176  // if the loop finished without breaking, there were no more elements to increment.
177  // that means we have reached the last permutation, so we invalidate counter and return
178  if(continue_flag || !valid()) {
179  _valid() = false;
180  return *this;
181  }
182 
183  j = 0;
184  next_j = current(j) + increment();
185  //next_i already contains _current(i) from above
186  next_i -= increment();
187  while(j < i) {
188 
189  while(!(compare(_upper(j), next_j)
190  || compare(next_j, _lower(j))
191  || compare(_upper(i), next_i)
192  || compare(next_i, _lower(i)))) {
193 
194  _current(i) = next_i;
195  next_i -= increment();
196 
197  _current(j) = next_j;
198  next_j += increment();
199  }
200 
201  while(j < i && (compare(_upper(i), next_i) || compare(next_i, _lower(i))))
202  next_i = current(--i) - increment();
203 
204  while(j < i && (compare(_upper(j), next_j) || compare(next_j, _lower(j))))
205  next_j = current(++j) + increment();
206 
207  }
208  return *this;
209  }
210 
211  void operator++(int) {
212  ++(*this);
213  }
214 
215  void set_sum_constraint(const value_type &new_sum) {
216  _sum_constraint() = new_sum;
217  reset();
218  }
219 
220  void set_current(const Container &new_current) {
221  if(current().size() != new_current.size()) {
222  std::cerr << "CRITICAL ERROR: In IsoCounter::set_current(), new state is incompatible with this counter.\n"
223  << " Exiting...\n";
224  exit(1);
225  }
226  _current() = new_current;
228  }
229 
231  void reset() {
232 
233  _valid() = size() != 0;
234 
235  _current() = initial();
236 
237  //Find the residual sum: m_sum_constraint - m_current.sum()
238  value_type sum_val(_sum_constraint() - current_sum());
239 
240  // if residual sum does not have same sign as increment, nothing can happen
241  if(compare(sum_val + sum_val, sum_val) != compare(increment() + increment(), increment())) {
242  _valid() = false;
243  return;
244  }
245 
246  size_type i;
247 
248  for(i = 0; i < size(); i++) {
249 
250  //if(almost_equal(m_initial[i], m_final[i])) //avoid operating on fixed elements
251  //continue;
252 
253  // if the i'th element isn't fixed, then increment it while decrementing sum_val
254  // until one or the other cannot be incremented/decremented further
255  while(!(compare(_upper(i), _current(i) + increment())
256  || compare(_current(i) + increment(), _lower(i))
257  || almost_zero(sum_val))) {
258  _current(i) += increment();
259  sum_val -= increment();
260  }
261  }
262  if(!almost_zero(sum_val)) {
263  _valid() = false;
264  }
265  return;
266 
267  }
268 
269 
270 
271  private:
272  value_type m_sum_constraint;
273 
274  value_type &_sum_constraint() {
275  return m_sum_constraint;
276  }
277 
278  const value_type &_sum_constraint() const {
279  return m_sum_constraint;
280  }
281 
283  value_type S(current_sum());
284  _valid() = !(compare(_sum_constraint(), S) || compare(S, _sum_constraint()));
285  for(size_type i = 0; i < size() && valid(); i++) {
286  _valid() = valid()
287  && compare(_current(i), _upper(i))
288  && compare(_lower(i), _current(i));
289  }
290  return valid();
291  }
292 
294  void _init() {
295  for(size_type i = 0; i < initial().size(); i++) {
296  if(compare(_initial(i), _final(i))) {
297  _lower(i) = _initial(i);
298  _upper(i) = _final(i);
299  }
300  else {
301  _lower(i) = _final(i);
302  _upper(i) = _initial(i);
303  }
304  }
305  }
306 
307  value_type &_increment() {
308  return Base::_increment(0);
309  }
310 
311  const value_type &_increment() const {
312  return Base::_increment(0);
313  }
314 
315  };
316 
317 
320 }
321 
322 
323 #endif
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:41
_Container Container
Definition: IsoCounter.hh:92
IsoCounter()
Default construct a IsoCounter Container must be default constructible value_type must be constructib...
Definition: IsoCounter.hh:111
bool compare(const T &A, const T &B, double tol)
Floating point comparison with tol, return A < B.
Definition: CASM_math.hh:89
value_type m_sum_constraint
Definition: IsoCounter.hh:272
BaseCounter< IsoCounter< _Container, _value_type, _size_type, _Access, _Compare > > Base
Definition: IsoCounter.hh:68
_Compare Compare
Definition: IsoCounter.hh:96
const value_type & increment() const
Definition: IsoCounter.hh:129
Main CASM namespace.
Definition: complete.cpp:8
void reset()
Reset thse current value of the Counter to the initial value.
Definition: IsoCounter.hh:231
bool _compute_validity()
Definition: IsoCounter.hh:282
value_type current_sum() const
Definition: IsoCounter.hh:133
_size_type size_type
Definition: IsoCounter.hh:94
void set_current(const Container &new_current)
Definition: IsoCounter.hh:220
void operator++(int)
Definition: IsoCounter.hh:211
A Counter allows looping over many incrementing variables in one loop.
Definition: BaseCounter.hh:114
value_type & _increment()
Definition: IsoCounter.hh:307
value_type & _sum_constraint()
Definition: IsoCounter.hh:274
IsoCounter(const Container &_initial, const Container &_final, const value_type &_increment, const value_type &_sum, Access _access=Access(), Compare _compare=Compare())
Construct a IsoCounter-type object.
Definition: IsoCounter.hh:118
Helper Functor for Counter container access using operator[].
Definition: CASM_TMP.hh:125
const value_type & _sum_constraint() const
Definition: IsoCounter.hh:278
A IsoCounter allows looping over many incrementing variables in one loop.
Definition: IsoCounter.hh:63
void set_sum_constraint(const value_type &new_sum)
Definition: IsoCounter.hh:215
const value_type & _increment() const
Definition: IsoCounter.hh:311
_value_type value_type
Definition: IsoCounter.hh:93
CASM_TMP::traits< IsoCounter >::Base Base
Definition: IsoCounter.hh:83
IsoCounter & operator++()
Definition: IsoCounter.hh:147
void _init()
Called from the constructor to set m_lower and m_upper appropriately.
Definition: IsoCounter.hh:294
typename std::conditional< boost::is_integral< T >::value, IntegralLessThan< T >, FloatingPointLessThan< T > >::type MuchLessThan
Definition: CASM_TMP.hh:117
Basic std::vector like container (deprecated)