Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
n_aryGrayCodeCounter.cpp
Go to the documentation of this file.
1 
17 #include "n_aryGrayCodeCounter.h"
18 #include <cstring>
19 #include <iostream>
20 
21 
22 
28 
29 
30  offset_max = 0;
31  offset = 0;
32 
33 }
34 
35 
41 
42  n_ary_limits = n_ary_limits_in.copy();
43 
44  if ( n_ary_limits.size() == 0 ) {
45  offset_max = 0;
46  offset = 0;
47  return;
48  }
49 
51  for (size_t idx=1; idx<static_cast<size_t>(n_ary_limits.size()); idx++) {
52  offset_max *= static_cast<int64_t>(n_ary_limits[static_cast<int>(idx)]);
53  }
54 
55  offset_max--;
56  offset = 0;
57 
58  // initialize the counter
59  initialize(0);
60 
61 }
62 
63 
69 n_aryGrayCodeCounter::n_aryGrayCodeCounter( matrix_base<int>& n_ary_limits_in, int64_t initial_offset) {
70 
71  n_ary_limits = n_ary_limits_in.copy();
72 
73  if ( n_ary_limits.size() == 0 ) {
74  offset_max = 0;
75  offset = 0;
76  return;
77  }
78 
80  for (size_t idx=1; idx<static_cast<size_t>(n_ary_limits.size()); idx++) {
81  offset_max *= static_cast<int64_t>(n_ary_limits[static_cast<int>(idx)]);
82  }
83 
84  offset_max--;
85  offset = initial_offset;
86 
87  // initialize the counter
88  initialize(initial_offset);
89 
90 }
91 
92 
93 
94 
98 void
100 
101  initialize(0);
102 
103 }
104 
105 
110 void
111 n_aryGrayCodeCounter::initialize( int64_t initial_offset ) {
112 
113  if ( initial_offset < 0 || initial_offset > offset_max ) {
114  std::string error("n_aryGrayCodeCounter::initialize: Wrong value of initial_offset");
115  throw error;
116  }
117 
118  // generate counter chain
120 
121  for (size_t idx = 0; idx < static_cast<size_t>(n_ary_limits.size()); idx++) {
122  counter_chain[static_cast<int>(idx)] = static_cast<int>(initial_offset % static_cast<int64_t>(n_ary_limits[static_cast<int>(idx)]));
123  initial_offset /= static_cast<int64_t>(n_ary_limits[static_cast<int>(idx)]);
124  }
125 
126  // determine the initial gray code corresponding to the given offset
128  int parity = 0;
129  for (unsigned long long jdx = static_cast<unsigned long long>(n_ary_limits.size()-1); jdx != ~0ULL; jdx--) {
130  size_t jdx_size = static_cast<size_t>(jdx);
131  int jdx_int = static_cast<int>(jdx);
132  gray_code[jdx_size] = parity ? n_ary_limits[jdx_int] - 1 - counter_chain[jdx_int] : counter_chain[jdx_int];
133  parity = parity ^ (gray_code[jdx_size] & 1);
134  }
135 
136 
137 
138 }
139 
140 
141 
146 GrayCode
148 
149 
150  return gray_code.copy();
151 
152 }
153 
154 
158 int
160 
161  int changed_index;
162 
163  int&& ret = next(changed_index);
164  return ret;
165 
166 }
167 
168 
173 int
174 n_aryGrayCodeCounter::next( int& changed_index) {
175 
176 
177  int value_prev, value;
178  int&& ret = next( changed_index, value_prev, value);
179  return ret;
180 
181 }
182 
189 int
190 n_aryGrayCodeCounter::next( int& changed_index, int& value_prev, int& value) {
191 
192 
193  // determine the index which is about to modify
194  changed_index = 0;
195 
196  if ( offset >= offset_max ) {
197  return 1;
198  }
199 
200 
201  bool update_counter = true;
202  int counter_chain_idx = 0;
203  while( update_counter ) {
204 
205  if ( counter_chain[counter_chain_idx] < n_ary_limits[counter_chain_idx]-1 ) {
206  counter_chain[counter_chain_idx]++;
207  update_counter = false;
208  }
209  else if ( counter_chain[counter_chain_idx] == n_ary_limits[counter_chain_idx]-1 ) {
210  counter_chain[counter_chain_idx] = 0;
211  update_counter = true;
212  }
213 
214  counter_chain_idx++;
215 
216  }
217 
218 
219  // determine the updated gray code
220  int parity = 0;
221  for (size_t jdx = static_cast<size_t>(n_ary_limits.size()-1); jdx != ~0ULL; jdx--) {
222  int jdx_int = static_cast<int>(jdx);
223  int gray_code_new_val = parity ? n_ary_limits[jdx_int] - 1 - counter_chain[jdx_int] : counter_chain[jdx_int];
224  parity = parity ^ (gray_code_new_val & 1);
225 
226  if ( gray_code_new_val != gray_code[jdx] ) {
227  value_prev = gray_code[jdx];
228  value = gray_code_new_val;
229  gray_code[jdx] = gray_code_new_val;
230  changed_index = static_cast<int>(jdx);
231  break;
232  }
233  }
234 
235  offset++;
236 
237  return 0;
238 
239 }
240 
254 int64_t n_aryGrayCodeCounter::advance(int counter_pos) {
255  const int L = (int)n_ary_limits.size();
256  if (L == 0) return 0;
257  if (counter_pos < 0) counter_pos = 0;
258  if (counter_pos >= L) counter_pos = L - 1;
259 
260  // Try to bump digit at counter_pos; if not possible, carry left
261  int p = counter_pos;
262  if (counter_chain[p] + 1 < n_ary_limits[p]) {
263  counter_chain[p] += 1;
264  if (p > 0) std::fill(counter_chain.data, counter_chain.data + p, 0);
265  } else {
266  // carry left: find the rightmost position < p that can be increased
267  int r = p + 1;
268  while (r < L && counter_chain[r] + 1 >= n_ary_limits[r]) ++r;
269  if (r < L) {
270  counter_chain[r] += 1;
271  std::fill(counter_chain.data, counter_chain.data + r, 0);
272  } else {
273  // no forward state remains in this lex-slab
274  return 0;
275  }
276  }
277 
278  // Compute the new mixed-radix rank (offset) from digits d (LSD at index 0).
279  int64_t new_offset = 0;
280  int64_t mul = 1;
281  for (int j = 0; j < L; ++j) {
282  new_offset += mul * (int64_t)counter_chain[j];
283  mul *= (int64_t)n_ary_limits[j];
284  }
285 
286  //printf("Advancing from offset %lld to offset %lld max %lld\n", offset, new_offset, offset_max);
287  // If somehow not moving forward, do nothing
288  if (new_offset <= offset || new_offset > offset_max) return 0;
289 
290  // Reinitialize counter to the new offset (rebuilds counter_chain & gray_code)
291  initialize(new_offset);
292 
293  // Return exact number of states skipped
294  return new_offset - offset; // note: initialize() set offset=new_offset
295 }
296 
297 void
298 n_aryGrayCodeCounter::set_offset_max( const int64_t& value ) {
299 
300 
301  offset_max = value;
302 
303 }
304 
305 
306 
GrayCode gray_code
the current gray code associated to the offset value
int64_t offset_max
the maximal offset in the counter offset = prod( n_ary_limits[i] )
n_aryGrayCodeCounter()
Default constructor of the class.
int64_t offset
the current offset in the counter 0<= offset <= offset_max
matrix_base< scalar > copy() const
Call to create a copy of the matrix.
int64_t advance(int counter_pos)
Advance the n-ary Gray code counter by incrementing the digit at a specified position.
scalar * data
pointer to the stored data
Definition: matrix_base.hpp:48
void set_offset_max(const int64_t &value)
int next()
Iterate the counter to the next value.
void initialize()
Initialize the gray counter by zero offset.
GrayCode_base< int > GrayCode
alias for Piquassoboost state with values of type int64_t
Definition: GrayCode.h:40
int size() const
Call to get the number of the allocated elements.
GrayCode_base copy() const
Call to create a copy of the state.
GrayCode get()
Get the current gray code counter value.
matrix_base< int > n_ary_limits
The maximal value of the individual gray code elements.
matrix_base< int > counter_chain
The incremental counter chain associated to the gray code.