pyqrack-cuda 1.46.6__tar.gz → 1.47.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {pyqrack_cuda-1.46.6/pyqrack_cuda.egg-info → pyqrack_cuda-1.47.0}/PKG-INFO +1 -1
  2. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_ace_backend.py +252 -122
  3. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
  4. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/setup.py +1 -1
  5. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/LICENSE +0 -0
  6. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/MANIFEST.in +0 -0
  7. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/Makefile +0 -0
  8. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/README.md +0 -0
  9. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyproject.toml +0 -0
  10. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/__init__.py +0 -0
  11. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/neuron_activation_fn.py +0 -0
  12. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/pauli.py +0 -0
  13. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_circuit.py +0 -0
  14. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_neuron.py +0 -0
  15. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_neuron_torch_layer.py +0 -0
  16. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_simulator.py +0 -0
  17. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_stabilizer.py +0 -0
  18. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_system/__init__.py +0 -0
  19. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/qrack_system/qrack_system.py +0 -0
  20. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/quimb_circuit_type.py +0 -0
  21. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/stats/__init__.py +0 -0
  22. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/stats/load_quantized_data.py +0 -0
  23. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack/stats/quantize_by_range.py +0 -0
  24. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack_cuda.egg-info/SOURCES.txt +0 -0
  25. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
  26. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
  27. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack_cuda.egg-info/requires.txt +0 -0
  28. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/pyqrack_cuda.egg-info/top_level.txt +0 -0
  29. {pyqrack_cuda-1.46.6 → pyqrack_cuda-1.47.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqrack-cuda
3
- Version: 1.46.6
3
+ Version: 1.47.0
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -34,6 +34,7 @@ class QrackAceBackend:
34
34
  Attributes:
35
35
  sim(QrackSimulator): Corresponding simulator.
36
36
  alternating_codes(bool): Alternate repetition code elision by index?
37
+ recursive_stack_depth(int): How many recursive nestings?
37
38
  row_length(int): Qubits per row.
38
39
  col_length(int): Qubits per column.
39
40
  """
@@ -41,8 +42,10 @@ class QrackAceBackend:
41
42
  def __init__(
42
43
  self,
43
44
  qubit_count=1,
45
+ long_range_rows=0,
44
46
  recursive_stack_depth=1,
45
47
  alternating_codes=True,
48
+ reverse_row_and_col=False,
46
49
  isTensorNetwork=False,
47
50
  isStabilizerHybrid=False,
48
51
  isBinaryDecisionTree=False,
@@ -53,39 +56,72 @@ class QrackAceBackend:
53
56
  recursive_stack_depth = toClone.recursive_stack_depth
54
57
  if recursive_stack_depth < 1:
55
58
  recursive_stack_depth = 1
59
+ if long_range_rows < 0:
60
+ long_range_rows = 0
61
+
56
62
  self.recursive_stack_depth = recursive_stack_depth
63
+ self._factor_width(qubit_count, reverse_row_and_col)
64
+ self.alternating_codes = alternating_codes
65
+ self._is_init = [False] * qubit_count
66
+
67
+ col_seq = [False] + [True] * long_range_rows
68
+ self._is_col_long_range = col_seq * (self.row_length // len(col_seq))
69
+ self._is_col_long_range += [True] * (
70
+ self.row_length - len(self._is_col_long_range)
71
+ )
72
+ self._hardware_offset = []
73
+ tot_qubits = 0
74
+ for _ in range(self.row_length):
75
+ for c in self._is_col_long_range:
76
+ self._hardware_offset.append(tot_qubits)
77
+ tot_qubits += 1 if c else 3
78
+ self._ancilla = tot_qubits
79
+ tot_qubits += 1
80
+
57
81
  if recursive_stack_depth > 1:
58
82
  recursive_stack_depth -= 1
59
83
  self.sim = (
60
84
  toClone.sim
61
85
  if toClone
62
- else QrackAceBackend(3 * qubit_count + 1, recursive_stack_depth=recursive_stack_depth, alternating_codes=alternating_codes, isTensorNetwork=isTensorNetwork, isStabilizerHybrid=isStabilizerHybrid, isBinaryDecisionTree=isBinaryDecisionTree)
86
+ else QrackAceBackend(
87
+ tot_qubits,
88
+ recursive_stack_depth,
89
+ alternating_codes,
90
+ reverse_row_and_col,
91
+ isTensorNetwork,
92
+ isStabilizerHybrid,
93
+ isBinaryDecisionTree,
94
+ )
63
95
  )
96
+ # This leaves an "odd-man-out" ancillary qubit.
97
+ self.sim.row_length = 3 * self.row_length
98
+ self.sim.col_length = self.col_length
64
99
  else:
65
100
  self.sim = (
66
101
  toClone.sim.clone()
67
102
  if toClone
68
- else QrackSimulator(3 * qubit_count + 1, isTensorNetwork=isTensorNetwork, isStabilizerHybrid=isStabilizerHybrid, isBinaryDecisionTree=isBinaryDecisionTree)
103
+ else QrackSimulator(
104
+ tot_qubits,
105
+ isTensorNetwork=isTensorNetwork,
106
+ isStabilizerHybrid=isStabilizerHybrid,
107
+ isBinaryDecisionTree=isBinaryDecisionTree,
108
+ )
69
109
  )
70
- self._ancilla = 3 * qubit_count
71
- self._factor_width(qubit_count)
72
- self.alternating_codes = alternating_codes
73
- self._is_init = [False] * qubit_count
74
110
 
75
111
  def clone(self):
76
112
  return QrackAceBackend(toClone=self)
77
113
 
78
114
  def num_qubits(self):
79
- return self.sim.num_qubits() // 3
115
+ return self.row_length * self.col_length
80
116
 
81
- def _factor_width(self, width):
117
+ def _factor_width(self, width, reverse=False):
82
118
  col_len = math.floor(math.sqrt(width))
83
119
  while ((width // col_len) * col_len) != width:
84
120
  col_len -= 1
85
121
  row_len = width // col_len
86
122
 
87
- self.col_length = col_len
88
- self.row_length = row_len
123
+ self.col_length = row_len if reverse else col_len
124
+ self.row_length = col_len if reverse else row_len
89
125
 
90
126
  def _ct_pair_prob(self, q1, q2):
91
127
  p1 = self.sim.prob(q1)
@@ -127,44 +163,39 @@ class QrackAceBackend:
127
163
  self.sim.x(t)
128
164
 
129
165
  def _unpack(self, lq, reverse=False):
166
+ offset = self._hardware_offset[lq]
167
+
168
+ if self._is_col_long_range[lq % self.row_length]:
169
+ return [offset]
170
+
130
171
  return (
131
- [3 * lq + 2, 3 * lq + 1, 3 * lq]
172
+ [offset + 2, offset + 1, offset]
132
173
  if reverse
133
- else [3 * lq, 3 * lq + 1, 3 * lq + 2]
174
+ else [offset, offset + 1, offset + 2]
134
175
  )
135
176
 
136
- def _encode(self, hq, reverse=False):
137
- lq = hq[0] // 3
138
- row = lq // self.row_length
139
- even_row = not (row & 1)
177
+ def _encode(self, lq, hq, reverse=False):
178
+ even_row = not ((lq // self.row_length) & 1)
179
+ # Encode shadow-first
180
+ if self._is_init[lq]:
181
+ self._cx_shadow(hq[0], hq[2])
140
182
  if ((not self.alternating_codes) and reverse) or (even_row == reverse):
141
- if self._is_init[lq]:
142
- # Encode shadow-first
143
- self._cx_shadow(hq[0], hq[1])
144
- self.sim.mcx([hq[1]], hq[2])
145
- else:
146
- self.sim.mcx([hq[2]], hq[1])
183
+ self.sim.mcx([hq[2]], hq[1])
147
184
  else:
148
- if self._is_init[lq]:
149
- # Encode shadow-first
150
- self._cx_shadow(hq[0], hq[2])
151
185
  self.sim.mcx([hq[0]], hq[1])
152
186
  self._is_init[lq] = True
153
187
 
154
- def _decode(self, hq, reverse=False):
155
- lq = hq[0] // 3
188
+ def _decode(self, lq, hq, reverse=False):
156
189
  if not self._is_init[lq]:
157
190
  return
158
- row = lq // self.row_length
159
- even_row = not (row & 1)
191
+ even_row = not ((lq // self.row_length) & 1)
160
192
  if ((not self.alternating_codes) and reverse) or (even_row == reverse):
161
193
  # Decode entangled-first
162
- self.sim.mcx([hq[1]], hq[2])
163
- self._cx_shadow(hq[0], hq[1])
194
+ self.sim.mcx([hq[2]], hq[1])
164
195
  else:
165
196
  # Decode entangled-first
166
197
  self.sim.mcx([hq[0]], hq[1])
167
- self._cx_shadow(hq[0], hq[2])
198
+ self._cx_shadow(hq[0], hq[2])
168
199
 
169
200
  def _correct(self, lq):
170
201
  if not self._is_init[lq]:
@@ -172,20 +203,23 @@ class QrackAceBackend:
172
203
  # We can't use true syndrome-based error correction,
173
204
  # because one of the qubits in the code is separated.
174
205
  # However, we can get pretty close!
175
- shots = 1024
176
- even_row = not ((lq // self.row_length) & 1)
206
+ shots = 512
207
+
177
208
  single_bit = 0
178
209
  other_bits = []
179
- if not self.alternating_codes or even_row:
210
+ if not self.alternating_codes or not ((lq // self.row_length) & 1):
180
211
  single_bit = 2
181
212
  other_bits = [0, 1]
182
213
  else:
183
214
  single_bit = 0
184
215
  other_bits = [1, 2]
216
+
185
217
  hq = self._unpack(lq)
218
+
186
219
  single_bit_value = self.sim.prob(hq[single_bit])
187
220
  single_bit_polarization = max(single_bit_value, 1 - single_bit_value)
188
221
  samples = self.sim.measure_shots([hq[other_bits[0]], hq[other_bits[1]]], shots)
222
+
189
223
  syndrome_indices = (
190
224
  [other_bits[1], other_bits[0]]
191
225
  if (single_bit_value >= 0.5)
@@ -268,6 +302,11 @@ class QrackAceBackend:
268
302
  self._correct(lq)
269
303
 
270
304
  def u(self, lq, th, ph, lm):
305
+ hq = self._unpack(lq)
306
+ if self._is_col_long_range[lq % self.row_length]:
307
+ self.sim.u(hq[0], th, ph, lm)
308
+ return
309
+
271
310
  while ph > math.pi:
272
311
  ph -= 2 * math.pi
273
312
  while ph <= -math.pi:
@@ -276,81 +315,121 @@ class QrackAceBackend:
276
315
  lm -= 2 * math.pi
277
316
  while lm <= -math.pi:
278
317
  lm += 2 * math.pi
279
- hq = self._unpack(lq)
318
+
280
319
  if not math.isclose(ph, -lm) and not math.isclose(abs(ph), math.pi / 2):
320
+ # Produces/destroys superposition
281
321
  self._correct_if_like_h(th, lq)
282
- self._decode(hq)
322
+ self._decode(lq, hq)
283
323
  self.sim.u(hq[0], th, ph, lm)
284
324
  if not self._is_init[lq]:
285
325
  self.sim.u(hq[2], th, ph, lm)
286
- self._encode(hq)
326
+ self._encode(lq, hq)
287
327
  else:
328
+ # Shouldn't produce/destroy superposition
288
329
  for b in hq:
289
330
  self.sim.u(b, th, ph, lm)
290
331
 
291
332
  def r(self, p, th, lq):
333
+ hq = self._unpack(lq)
334
+ if self._is_col_long_range[lq % self.row_length]:
335
+ self.sim.r(p, th, hq[0])
336
+ return
337
+
292
338
  while th > math.pi:
293
339
  th -= 2 * math.pi
294
340
  while th <= -math.pi:
295
341
  th += 2 * math.pi
296
342
  if p == Pauli.PauliY:
297
343
  self._correct_if_like_h(th, lq)
298
- hq = self._unpack(lq)
344
+
299
345
  if (p == Pauli.PauliZ) or math.isclose(abs(th), math.pi):
346
+ # Doesn't produce/destroy superposition
300
347
  for b in hq:
301
348
  self.sim.r(p, th, b)
302
349
  else:
303
- self._decode(hq)
350
+ # Produces/destroys superposition
351
+ self._decode(lq, hq)
304
352
  self.sim.r(p, th, hq[0])
305
353
  if not self._is_init[lq]:
306
354
  self.sim.r(p, th, hq[2])
307
- self._encode(hq)
355
+ self._encode(lq, hq)
308
356
 
309
357
  def h(self, lq):
310
358
  hq = self._unpack(lq)
311
- self._decode(hq)
359
+ if self._is_col_long_range[lq % self.row_length]:
360
+ self.sim.h(hq[0])
361
+ return
362
+
363
+ self._decode(lq, hq)
312
364
  self.sim.h(hq[0])
313
365
  if not self._is_init[lq]:
314
366
  self.sim.h(hq[2])
315
- self._encode(hq)
367
+ self._encode(lq, hq)
316
368
 
317
369
  def s(self, lq):
318
370
  hq = self._unpack(lq)
371
+ if self._is_col_long_range[lq % self.row_length]:
372
+ self.sim.s(hq[0])
373
+ return
374
+
319
375
  for b in hq:
320
376
  self.sim.s(b)
321
377
 
322
378
  def adjs(self, lq):
323
379
  hq = self._unpack(lq)
380
+ if self._is_col_long_range[lq % self.row_length]:
381
+ self.sim.adjs(hq[0])
382
+ return
383
+
324
384
  for b in hq:
325
385
  self.sim.adjs(b)
326
386
 
327
387
  def x(self, lq):
328
388
  hq = self._unpack(lq)
389
+ if self._is_col_long_range[lq % self.row_length]:
390
+ self.sim.x(hq[0])
391
+ return
392
+
329
393
  for b in hq:
330
394
  self.sim.x(b)
331
395
 
332
396
  def y(self, lq):
333
397
  hq = self._unpack(lq)
398
+ if self._is_col_long_range[lq % self.row_length]:
399
+ self.sim.y(hq[0])
400
+ return
401
+
334
402
  for b in hq:
335
403
  self.sim.y(b)
336
404
 
337
405
  def z(self, lq):
338
406
  hq = self._unpack(lq)
407
+ if self._is_col_long_range[lq % self.row_length]:
408
+ self.sim.z(hq[0])
409
+ return
410
+
339
411
  for b in hq:
340
412
  self.sim.z(b)
341
413
 
342
414
  def t(self, lq):
343
415
  hq = self._unpack(lq)
416
+ if self._is_col_long_range[lq % self.row_length]:
417
+ self.sim.t(hq[0])
418
+ return
419
+
344
420
  for b in hq:
345
421
  self.sim.t(b)
346
422
 
347
423
  def adjt(self, lq):
348
424
  hq = self._unpack(lq)
425
+ if self._is_col_long_range[lq % self.row_length]:
426
+ self.sim.adjt(hq[0])
427
+ return
428
+
349
429
  for b in hq:
350
430
  self.sim.adjt(b)
351
431
 
352
432
  def _cpauli(self, lq1, lq2, anti, pauli):
353
- self._correct(lq1)
354
433
  gate = None
355
434
  shadow = None
356
435
  if pauli == Pauli.PauliX:
@@ -365,49 +444,104 @@ class QrackAceBackend:
365
444
  else:
366
445
  return
367
446
 
447
+ lq1_lr = self._is_col_long_range[lq1 % self.row_length]
448
+ lq2_lr = self._is_col_long_range[lq2 % self.row_length]
449
+ if lq1_lr and lq2_lr:
450
+ gate(self._unpack(lq1), self._unpack(lq2)[0])
451
+ return
452
+
453
+ self._correct(lq1)
454
+
368
455
  if not self._is_init[lq1]:
369
456
  hq1 = self._unpack(lq1)
370
457
  hq2 = self._unpack(lq2)
371
- gate([hq1[0]], hq2[0])
372
- gate([hq1[1]], hq2[1])
373
- gate([hq1[2]], hq2[2])
458
+ if lq1_lr:
459
+ self._decode(lq2, hq2)
460
+ gate(hq1, hq2[0])
461
+ self._encode(lq2, hq2)
462
+ elif lq1_lr:
463
+ self._decode(lq1, hq1)
464
+ gate([hq1[0]], hq2[0])
465
+ self._encode(lq1, hq1)
466
+ else:
467
+ gate([hq1[0]], hq2[0])
468
+ gate([hq1[1]], hq2[1])
469
+ gate([hq1[2]], hq2[2])
374
470
 
375
471
  return
376
472
 
377
- lq1_col = lq1 // self.row_length
378
- lq1_row = lq1 % self.row_length
379
- lq2_col = lq2 // self.row_length
380
- lq2_row = lq2 % self.row_length
473
+ lq1_row = lq1 // self.row_length
474
+ lq1_col = lq1 % self.row_length
475
+ lq2_row = lq2 // self.row_length
476
+ lq2_col = lq2 % self.row_length
381
477
 
382
478
  hq1 = None
383
479
  hq2 = None
384
- if (lq2_col == lq1_col) and (((lq1_row + 1) % self.row_length) == lq2_row):
385
- self._correct(lq2)
386
- hq1 = self._unpack(lq1, True)
387
- hq2 = self._unpack(lq2, False)
388
- self._decode(hq1, True)
389
- self._decode(hq2, False)
390
- gate([hq1[0]], hq2[0])
391
- self._encode(hq2, False)
392
- self._encode(hq1, True)
393
- elif (lq1_col == lq2_col) and (((lq2_row + 1) % self.row_length) == lq1_row):
394
- self._correct(lq2)
395
- hq2 = self._unpack(lq2, True)
396
- hq1 = self._unpack(lq1, False)
397
- self._decode(hq2, True)
398
- self._decode(hq1, False)
399
- gate([hq1[0]], hq2[0])
400
- self._encode(hq1, False)
401
- self._encode(hq2, True)
480
+ if (lq2_row == lq1_row) and (((lq1_col + 1) % self.row_length) == lq2_col):
481
+ if lq1_lr:
482
+ self._correct(lq2)
483
+ hq1 = self._unpack(lq1)
484
+ hq2 = self._unpack(lq2, False)
485
+ self._decode(lq2, hq2, False)
486
+ gate(hq1, hq2[0])
487
+ self._encode(lq2, hq2, False)
488
+ elif lq2_lr:
489
+ hq1 = self._unpack(lq1, True)
490
+ hq2 = self._unpack(lq2)
491
+ self._decode(lq1, hq1, True)
492
+ gate([hq1[0]], hq2[0])
493
+ self._encode(lq1, hq1, True)
494
+ else:
495
+ self._correct(lq2)
496
+ hq1 = self._unpack(lq1, True)
497
+ hq2 = self._unpack(lq2, False)
498
+ self._decode(lq1, hq1, True)
499
+ self._decode(lq2, hq2, False)
500
+ gate([hq1[0]], hq2[0])
501
+ self._encode(lq2, hq2, False)
502
+ self._encode(lq1, hq1, True)
503
+ elif (lq1_row == lq2_row) and (((lq2_col + 1) % self.row_length) == lq1_col):
504
+ if lq1_lr:
505
+ self._correct(lq2)
506
+ hq2 = self._unpack(lq2, True)
507
+ hq1 = self._unpack(lq1)
508
+ self._decode(lq2, hq2, True)
509
+ gate(hq1, hq2[0])
510
+ self._encode(lq2, hq2, True)
511
+ elif lq2_lr:
512
+ hq2 = self._unpack(lq2)
513
+ hq1 = self._unpack(lq1, False)
514
+ self._decode(lq1, hq1, False)
515
+ gate([hq1[0]], hq2[0])
516
+ self._encode(lq1, hq1, False)
517
+ else:
518
+ self._correct(lq2)
519
+ hq2 = self._unpack(lq2, True)
520
+ hq1 = self._unpack(lq1, False)
521
+ self._decode(lq2, hq2, True)
522
+ self._decode(lq1, hq1, False)
523
+ gate([hq1[0]], hq2[0])
524
+ self._encode(lq1, hq1, False)
525
+ self._encode(lq2, hq2, True)
402
526
  else:
403
527
  hq1 = self._unpack(lq1)
404
528
  hq2 = self._unpack(lq2)
405
- gate([hq1[0]], hq2[0])
406
- if self.alternating_codes and ((lq2_col & 1) != (lq1_col & 1)):
407
- shadow(hq1[1], hq2[1])
529
+ if lq1_lr:
530
+ self._correct(lq2)
531
+ self._decode(lq2, hq2)
532
+ gate(hq1, hq2[0])
533
+ self._encode(lq2, hq2)
534
+ elif lq2_lr:
535
+ self._decode(lq1, hq1)
536
+ gate([hq1[0]], hq2[0])
537
+ self._encode(lq1, hq1)
408
538
  else:
409
- gate([hq1[1]], hq2[1])
410
- gate([hq1[2]], hq2[2])
539
+ gate([hq1[0]], hq2[0])
540
+ if self.alternating_codes and ((lq2_row & 1) != (lq1_row & 1)):
541
+ shadow(hq1[1], hq2[1])
542
+ else:
543
+ gate([hq1[1]], hq2[1])
544
+ gate([hq1[2]], hq2[2])
411
545
 
412
546
  def cx(self, lq1, lq2):
413
547
  self._cpauli(lq1, lq2, False, Pauli.PauliX)
@@ -429,32 +563,44 @@ class QrackAceBackend:
429
563
 
430
564
  def mcx(self, lq1, lq2):
431
565
  if len(lq1) > 1:
432
- raise RuntimeError("QrackAceBackend.mcx() is provided for syntax convenience and only supports 1 control qubit!")
566
+ raise RuntimeError(
567
+ "QrackAceBackend.mcx() is provided for syntax convenience and only supports 1 control qubit!"
568
+ )
433
569
  self._cpauli(lq1[0], lq2, False, Pauli.PauliX)
434
570
 
435
571
  def mcy(self, lq1, lq2):
436
572
  if len(lq1) > 1:
437
- raise RuntimeError("QrackAceBackend.mcy() is provided for syntax convenience and only supports 1 control qubit!")
573
+ raise RuntimeError(
574
+ "QrackAceBackend.mcy() is provided for syntax convenience and only supports 1 control qubit!"
575
+ )
438
576
  self._cpauli(lq1[0], lq2, False, Pauli.PauliY)
439
577
 
440
578
  def mcz(self, lq1, lq2):
441
579
  if len(lq1) > 1:
442
- raise RuntimeError("QrackAceBackend.mcz() is provided for syntax convenience and only supports 1 control qubit!")
580
+ raise RuntimeError(
581
+ "QrackAceBackend.mcz() is provided for syntax convenience and only supports 1 control qubit!"
582
+ )
443
583
  self._cpauli(lq1[0], lq2, False, Pauli.PauliZ)
444
584
 
445
585
  def macx(self, lq1, lq2):
446
586
  if len(lq1) > 1:
447
- raise RuntimeError("QrackAceBackend.macx() is provided for syntax convenience and only supports 1 control qubit!")
587
+ raise RuntimeError(
588
+ "QrackAceBackend.macx() is provided for syntax convenience and only supports 1 control qubit!"
589
+ )
448
590
  self._cpauli(lq1[0], lq2, True, Pauli.PauliX)
449
591
 
450
592
  def macy(self, lq1, lq2):
451
593
  if len(lq1) > 1:
452
- raise RuntimeError("QrackAceBackend.macy() is provided for syntax convenience and only supports 1 control qubit!")
594
+ raise RuntimeError(
595
+ "QrackAceBackend.macy() is provided for syntax convenience and only supports 1 control qubit!"
596
+ )
453
597
  self._cpauli(lq1[0], lq2, True, Pauli.PauliY)
454
598
 
455
599
  def macz(self, lq1, lq2):
456
600
  if len(lq1) > 1:
457
- raise RuntimeError("QrackAceBackend.macz() is provided for syntax convenience and only supports 1 control qubit!")
601
+ raise RuntimeError(
602
+ "QrackAceBackend.macz() is provided for syntax convenience and only supports 1 control qubit!"
603
+ )
458
604
  self._cpauli(lq1[0], lq2, True, Pauli.PauliZ)
459
605
 
460
606
  def swap(self, lq1, lq2):
@@ -476,8 +622,10 @@ class QrackAceBackend:
476
622
 
477
623
  def m(self, lq):
478
624
  hq = self._unpack(lq)
479
- even_row = not ((lq // self.row_length) & 1)
480
- if not self.alternating_codes or even_row:
625
+ if self._is_col_long_range[lq % self.row_length]:
626
+ return self.sim.m(hq[0])
627
+
628
+ if not self.alternating_codes or not ((lq // self.row_length) & 1):
481
629
  single_bit = 2
482
630
  other_bits = [0, 1]
483
631
  else:
@@ -497,6 +645,9 @@ class QrackAceBackend:
497
645
 
498
646
  def force_m(self, lq, c):
499
647
  hq = self._unpack(lq)
648
+ if self._is_col_long_range[lq % self.row_length]:
649
+ return self.sim.force_m(hq[0])
650
+
500
651
  self._correct(lq)
501
652
  for q in hq:
502
653
  self.sim.force_m(q, c)
@@ -515,56 +666,35 @@ class QrackAceBackend:
515
666
  col_offset = random.randint(0, self.row_length - 1)
516
667
  col_reverse = self.alternating_codes and (lq_row & 1)
517
668
  for c in range(self.row_length):
518
- lq_col = (((self.row_length - (c + 1)) if col_reverse else c) + col_offset) % self.row_length
669
+ lq_col = (
670
+ ((self.row_length - (c + 1)) if col_reverse else c) + col_offset
671
+ ) % self.row_length
519
672
  lq = lq_row * self.row_length + lq_col
520
673
  if self.m(lq):
521
674
  result |= 1 << lq
522
675
 
523
676
  return result
524
677
 
525
- def measure_shots(self, q, s, high_accuracy=True):
526
- if high_accuracy:
527
- samples = []
528
- for _ in range(s):
529
- clone = self.clone()
530
- _sample = clone.m_all()
531
- sample = 0
532
- for i in range(len(q)):
533
- if (_sample >> q[i]) & 1:
534
- sample |= 1 << i
535
- samples.append(sample)
536
-
537
- return samples
538
-
539
- _q = []
540
- for i in q:
541
- _q.append(3 * i)
542
- _q.append(3 * i + 1)
543
- _q.append(3 * i + 2)
544
-
545
- samples = self.sim.measure_shots(_q, s)
546
-
547
- results = []
548
- for sample in samples:
549
- logical_sample = 0
678
+ def measure_shots(self, q, s):
679
+ samples = []
680
+ for _ in range(s):
681
+ clone = self.clone()
682
+ _sample = clone.m_all()
683
+ sample = 0
550
684
  for i in range(len(q)):
551
- logical_sample <<= 1
552
- bit_count = 0
553
- for _ in range(3):
554
- if sample & 1:
555
- bit_count += 1
556
- sample >>= 1
557
- if bit_count > 1:
558
- logical_sample |= 1
559
- results.append(logical_sample)
560
-
561
- return results
685
+ if (_sample >> q[i]) & 1:
686
+ sample |= 1 << i
687
+ samples.append(sample)
688
+
689
+ return samples
562
690
 
563
691
  def prob(self, lq):
564
- self._correct(lq)
565
692
  hq = self._unpack(lq)
566
- even_row = not ((lq // self.row_length) & 1)
567
- if not self.alternating_codes or even_row:
693
+ if self._is_col_long_range[lq % self.row_length]:
694
+ return self.sim.prob(hq[0])
695
+
696
+ self._correct(lq)
697
+ if not self.alternating_codes or not ((lq // self.row_length) & 1):
568
698
  other_bits = [0, 1]
569
699
  else:
570
700
  other_bits = [1, 2]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqrack-cuda
3
- Version: 1.46.6
3
+ Version: 1.47.0
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -7,7 +7,7 @@ from setuptools import setup
7
7
  from setuptools.command.build_py import build_py
8
8
 
9
9
 
10
- VERSION = "1.46.6"
10
+ VERSION = "1.47.0"
11
11
 
12
12
  # Read long description from README.
13
13
  README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'README.md')
File without changes
File without changes
File without changes
File without changes
File without changes