Honeycomb  0.1
Component-Model Framework
Permute.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
5 
6 namespace honey
7 {
8 
10 
26 template<class Real>
27 class Permute_
28 {
29  typedef typename Numeral<Real>::Real_ Real_;
30  typedef typename Real_::DoubleType Double_;
31  typedef typename Double_::Real Double;
32  typedef Alge_<Real> Alge;
33 
34 public:
35 
37  template<class T>
38  class Iter
39  {
40  friend class Permute_;
41  typedef function<bool (const vector<const T*>&)> Func;
42 
43  struct State : public SharedObj<State>
44  {
45  State(const vector<T>& list, const Func& func = nullptr)
46  : list(list), func(func), count(0), countMax(0), k(-1), n(0) {}
47 
48  const vector<T>& list;
49  Func func;
50  vector<const T*> perm;
51  sdt count;
52  sdt countMax;
53 
54  vector<sdt> a;
55  vector<sdt> l;
56  vector<sdt> u;
57  sdt p;
58  sdt q;
59  sdt k;
60  sdt n;
61  };
62 
63  public:
64  typedef std::forward_iterator_tag iterator_category;
65  typedef const vector<const T*> value_type;
67  typedef const vector<const T*>* pointer;
68  typedef const vector<const T*>& reference;
69 
70  Iter() = default;
71  Iter(SharedPtr<State> state);
72 
73  Iter& operator++();
74  Iter operator++(int) { auto tmp = *this; ++*this; return tmp; }
75 
76  bool operator==(const Iter& rhs) const;
77  bool operator!=(const Iter& rhs) const { return !operator==(rhs); }
78 
80  vector<const T*>& operator*() const { return _ps->perm; }
81  vector<const T*>* operator->() const { return &_ps->perm; }
82 
84  sdt count() const { return _ps->count; }
86  sdt countMax() const { return _ps->countMax; }
87 
88  private:
89  bool isEnd() const { return !_ps; }
90 
91  SharedPtr<State> _ps;
92  };
93 
95  template<class T>
96  static Range_<Iter<T>, Iter<T>>
97  range(const vector<T>& list, const typename Iter<T>::Func& func = nullptr)
98  { return honey::range(Iter<T>(new typename Iter<T>::State(list, func)), Iter<T>(nullptr)); }
99 };
100 
101 template<class Real>
102 template<class T>
104  _ps(state)
105 {
106  if (isEnd() || _ps->list.size() == 0)
107  return;
108 
109  _ps->n = _ps->list.size();
110  _ps->countMax = GammaFunc_<Double>::factorial(_ps->n);
111  _ps->count = 0;
112  _ps->a.resize(_ps->n+1, -1);
113  _ps->l.resize(_ps->n+1, -1);
114  _ps->u.resize(_ps->n+1, -1);
115 
116  for (sdt i = 0; i < _ps->n; ++i)
117  _ps->l[i] = i+1;
118  _ps->l[_ps->n] = 0;
119  _ps->k = 1;
120  //Init level k
121  _ps->p = 0;
122  _ps->q = _ps->l[0];
123  operator++();
124 }
125 
126 template<class Real>
127 template<class T>
129 {
130  if (_ps->k <= 0)
131  {
132  if (_ps->k == 0)
133  --_ps->k; //Put iterator into end state
134  return *this;
135  }
136 
137  while(1)
138  {
139  //Call functor to test for level k culling
140  bool visit = false;
141  bool func = true;
142 
143  _ps->a[_ps->k] = _ps->q;
144 
145  //Only call functor if we're using one, otherwise assume it returned true
146  if (_ps->func)
147  {
148  //Build permutation up to level k
149  _ps->perm.resize(_ps->k);
150  for (sdt i = 1; i <= _ps->k; ++i)
151  _ps->perm[i-1] = &_ps->list[_ps->a[i]-1];
152  //Call functor for cull test
153  func = _ps->func(const_cast<const vector<const T*>&>(_ps->perm));
154  }
155 
156  if (func && _ps->k < _ps->n)
157  {
158  //Functor true, not full permutation. Advance and init level k
159  _ps->u[_ps->k] = _ps->p;
160  _ps->l[_ps->p] = _ps->l[_ps->q];
161  ++_ps->k;
162  _ps->p = 0;
163  _ps->q = _ps->l[0];
164  continue;
165  }
166  else if (func)
167  {
168  //Functor true, full permutation. Visit
169  visit = true;
170  _ps->count++;
171 
172  //If we're using a functor then the full permutation has already been built and is ready for visiting
173  if (!_ps->func)
174  {
175  _ps->perm.resize(_ps->k);
176  for (sdt i = 1; i <= _ps->k; ++i)
177  _ps->perm[i-1] = &_ps->list[_ps->a[i]-1];
178  }
179  }
180  else
181  {
182  //Functor false, skip subtree. Increase a[k]
183  _ps->p = _ps->q;
184  _ps->q = _ps->l[_ps->p];
185  _ps->count = _ps->count + GammaFunc_<Double>::factorial(_ps->n - _ps->k);
186  if (_ps->q != 0)
187  continue;
188  }
189 
190  while (1)
191  {
192  //Fallback levels. Decrease k
193  --_ps->k;
194  if (_ps->k <= 0)
195  return *this;
196  _ps->p = _ps->u[_ps->k];
197  _ps->q = _ps->a[_ps->k];
198  _ps->l[_ps->p] = _ps->q;
199 
200  //Increase a[k]
201  _ps->p = _ps->q;
202  _ps->q = _ps->l[_ps->p];
203  if (_ps->q != 0)
204  break;
205  }
206 
207  if (visit)
208  break;
209  }
210 
211  return *this;
212 }
213 
214 template<class Real>
215 template<class T>
217 {
218  if (!isEnd() && !rhs.isEnd())
219  return _ps == rhs._ps;
220  if (isEnd() && rhs.isEnd())
221  return true;
222 
223  //Comparing to end, check if done
224  const Iter& it = isEnd() ? rhs : *this;
225  return it._ps->k < 0;
226 }
227 
228 
232 
233 }
234 
const vector< const T * > & reference
Definition: Permute.h:68
Algebra.
Definition: Alge.h:13
Permute_< Double > Permute_d
Definition: Permute.h:231
std::forward_iterator_tag iterator_category
Definition: Permute.h:64
Generate all permutations of a list. A functor can be specified for fast culling of entire subtrees o...
Definition: Permute.h:27
sdt count() const
Get current permutation number. Every perm has a unique associated number: the first perm is 1...
Definition: Permute.h:84
ptrdiff_t sdt
Size difference type, shorthand for ptrdiff_t.
Definition: Core.h:92
sdt countMax() const
Get total number of permutations for this list.
Definition: Permute.h:86
Reference-counted object for intrusive shared pointers.
Definition: SharedPtr.h:93
std::enable_if< mt::isIterator< Iter1 >::value, Range_< Iter1, Iter2 > >::type range(Iter1 &&first, Iter2 &&last)
Range from iterators [first, last)
Definition: Range.h:116
bool operator!=(const Iter &rhs) const
Definition: Permute.h:77
const vector< const T * > value_type
Definition: Permute.h:65
Permute_< Float > Permute_f
Definition: Permute.h:230
static Range_< Iter< T >, Iter< T > > range(const vector< T > &list, const typename Iter< T >::Func &func=nullptr)
Create a permutation range.
Definition: Permute.h:97
Permute_< Real > Permute
Definition: Permute.h:229
vector< const T * > * operator->() const
Definition: Permute.h:81
const vector< const T * > * pointer
Definition: Permute.h:67
static Real factorial(Real n)
Factorial, N!. N can be any Real including fractional numbers.
Definition: Gamma.cpp:407
Numeric type information, use numeral() to get instance safely from a static context.
Definition: Numeral.h:17
bool operator==(const Iter &rhs) const
Definition: Permute.h:216
sdt difference_type
Definition: Permute.h:66
Iter & operator++()
Definition: Permute.h:128
double Real
Definition: Real.h:14
vector< const T * > & operator*() const
Get current permutation list.
Definition: Permute.h:80
bool operator==(const String &lhs, const String &rhs)
Definition: String.h:139
Iter operator++(int)
Definition: Permute.h:74
Global Honeycomb namespace.
Iter for permutations of a list.
Definition: Permute.h:38