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