The ChainCon Software (Release 0.03)
shuffles.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file
4 ///
5 /// An iterator of shuffles.
6 ///
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // Copyright (C) 2009-2016 by Pawel Pilarczyk.
10 //
11 // This file is part of my research software package. This is free software:
12 // you can redistribute it and/or modify it under the terms of the GNU
13 // General Public License as published by the Free Software Foundation,
14 // either version 3 of the License, or (at your option) any later version.
15 //
16 // This software is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this software; see the file "license.txt". If not,
23 // please, see <http://www.gnu.org/licenses/>.
24 
25 // Started on March 24, 2009. Last revision: August 21, 2013.
26 
27 
28 #ifndef _CHAINCON_SHUFFLES_H_
29 #define _CHAINCON_SHUFFLES_H_
30 
31 
32 // include some standard C++ header files
33 #include <istream>
34 #include <ostream>
35 #include <vector>
36 
37 // include selected header files from the CHomP library
38 #include "chomp/system/config.h"
39 
40 // include relevant local header files
41 
42 
43 // --------------------------------------------------
44 // -------------------- shuffles --------------------
45 // --------------------------------------------------
46 
47 /// An iterator of all the (p,q)-shuffles.
48 /// A (p,q)-shuffle (alpha, beta) is a partition of the set {0,...,p+q-1}
49 /// into two disjoint subsets, such that alpha_1 < ... < alpha_p
50 /// and beta_1 < ... < beta_q.
51 class Shuffles
52 {
53 public:
54  /// The constructor in which the size of the shuffle is given.
55  Shuffles (int p, int q);
56 
57  /// Rewinds the counter of the (p,q)-shuffles.
58  void rewind ();
59 
60  /// Gets a (p,q)-shuffle and its signature.
61  /// Returns true if more (p,q)-shuffles are available,
62  /// or false if this was the last one (and rewinds the iterator).
63  template <class ArrayP, class ArrayQ>
64  bool get (ArrayP &alpha, ArrayQ &beta, int &sig);
65 
66 private:
67  /// The number p of the elements of the first set in the partition.
68  int _p;
69 
70  /// The sum of the numbers of the elements of both sets
71  /// in the partition: p + q.
72  int _pq;
73 
74  /// A vector of counters that correspond to the first set
75  /// in the partition.
76  std::vector<int> _alpha;
77 
78 }; /* class Shuffles */
79 
80 // --------------------------------------------------
81 
82 inline Shuffles::Shuffles (int p, int q): _p (p), _pq (p + q),
83  _alpha ((p > 0) ? p : 1)
84 {
85  if ((p < 0) || (q < 0))
86  throw "Trying to define shuffles with negative p or q.";
87  rewind ();
88  return;
89 } /* Shuffles::Shuffles */
90 
91 inline void Shuffles::rewind ()
92 {
93  for (int i = 0; i < _p; ++ i)
94  _alpha [i] = i;
95  return;
96 } /* Shuffles::rewind */
97 
98 template <class ArrayP, class ArrayQ>
99 inline bool Shuffles::get (ArrayP &alpha, ArrayQ &beta, int &sig)
100 {
101  // copy the current shuffle
102  int alpha_i = 0;
103  int beta_i = 0;
104  int cur = 0;
105  for (int i = 0; i < _pq; ++ i)
106  {
107  if ((cur < _p) && (_alpha [cur] == i))
108  {
109  alpha [alpha_i ++] = i;
110  ++ cur;
111  }
112  else
113  {
114  beta [beta_i ++] = i;
115  }
116  }
117 
118  // compute the signature
119  sig = 0;
120  for (int i = 0; i < _p; ++ i)
121  sig += _alpha [i] - i;
122 
123  // prepare the next shuffle following this algorithm
124  // (http://stackoverflow.com/questions/17435030/)
125  //int s = (1 << k) - 1;
126  //while (!(s & 1 << N))
127  //{
128  // // do stuff with s
129  // int lo = s & ~(s - 1); // lowest one bit
130  // int lz = (s + lo) & ~s; // lowest zero bit above lo
131  // s |= lz; // add lz to the set
132  // s &= ~(lz - 1); // reset bits below lz
133  // s |= (lz / lo / 2) - 1; // put back right number of bits
134  //}
135 
136  // find the lowest number in the p-tuple
137 // int lo = _alpha [0];
138  // find the first number in the p-tuple that can be increased
139  cur = 0;
140  while ((cur < _p - 1) && (_alpha [cur + 1] - _alpha [cur] == 1))
141  ++ cur;
142  // if this is the last number and it cannot be increased then rewind
143  if ((cur >= _p) || ((cur == _p - 1) && (_alpha [cur] == _pq - 1)))
144  {
145  rewind ();
146  return false;
147  }
148  // increase this number and rewind the numbers below it
149  ++ (_alpha [cur]);
150  for (int i = 0; i < cur; ++ i)
151  _alpha [i] = i;
152 
153  return true;
154 } /* Shuffles::get */
155 
156 
157 #endif // _CHAINCON_SHUFFLES_H_
158 
An iterator of all the (p,q)-shuffles.
Definition: shuffles.h:51
std::vector< int > _alpha
A vector of counters that correspond to the first set in the partition.
Definition: shuffles.h:76
Shuffles(int p, int q)
The constructor in which the size of the shuffle is given.
Definition: shuffles.h:82
int _p
The number p of the elements of the first set in the partition.
Definition: shuffles.h:68
void rewind()
Rewinds the counter of the (p,q)-shuffles.
Definition: shuffles.h:91
bool get(ArrayP &alpha, ArrayQ &beta, int &sig)
Gets a (p,q)-shuffle and its signature.
Definition: shuffles.h:99
int _pq
The sum of the numbers of the elements of both sets in the partition: p + q.
Definition: shuffles.h:72