pyqrack-complex128 2.1.0__tar.gz → 2.1.2__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.
- {pyqrack_complex128-2.1.0/pyqrack_complex128.egg-info → pyqrack_complex128-2.1.2}/PKG-INFO +1 -1
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_ace_backend.py +81 -29
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2/pyqrack_complex128.egg-info}/PKG-INFO +1 -1
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/setup.py +1 -1
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/LICENSE +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/MANIFEST.in +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/Makefile +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/README.md +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyproject.toml +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/__init__.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/pauli.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/SOURCES.txt +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/dependency_links.txt +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/not-zip-safe +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/requires.txt +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/top_level.txt +0 -0
- {pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/setup.cfg +0 -0
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
#
|
|
3
3
|
# Use of this source code is governed by an MIT-style license that can be
|
|
4
4
|
# found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
5
|
+
#
|
|
6
|
+
# Produced with input from (OpenAI) ChatGPT and (Anthropic) Claude
|
|
5
7
|
import math
|
|
6
8
|
import os
|
|
7
9
|
import random
|
|
@@ -332,6 +334,50 @@ class QrackAceBackend:
|
|
|
332
334
|
def clone(self):
|
|
333
335
|
return QrackAceBackend(to_clone=self)
|
|
334
336
|
|
|
337
|
+
def measure_shots_consensus(self, q, s, n_instances=3, threshold=0.1):
|
|
338
|
+
# Consensus measurement across n_instances independent clones.
|
|
339
|
+
#
|
|
340
|
+
# For each shot, run n_instances clones of the current state and
|
|
341
|
+
# compare their marginal probabilities on every logical qubit via
|
|
342
|
+
# prob(). For each qubit, take the majority vote over all instances:
|
|
343
|
+
# if the average marginal >= 0.5, force_m to |1>; else to |0>.
|
|
344
|
+
#
|
|
345
|
+
# This resolves the parity ambiguity that causes XEB flip-flopping:
|
|
346
|
+
# a bit-flip on a boundary qubit appears as disagreement between
|
|
347
|
+
# instances (one sees p~0.9, another sees p~0.1). The majority vote
|
|
348
|
+
# across n_instances corrects isolated odd-parity errors without
|
|
349
|
+
# requiring a second full circuit run — just cheap prob() queries.
|
|
350
|
+
#
|
|
351
|
+
# threshold: minimum spread in marginals to trigger consensus
|
|
352
|
+
# correction (below threshold, instances agree and no correction needed).
|
|
353
|
+
n_qubits = self.num_qubits()
|
|
354
|
+
samples = []
|
|
355
|
+
for _ in range(s):
|
|
356
|
+
# Run n_instances clones, collect marginals for every qubit
|
|
357
|
+
clones = [self.clone() for _ in range(n_instances)]
|
|
358
|
+
marginals = [
|
|
359
|
+
[c.prob(lq) for lq in range(n_qubits)]
|
|
360
|
+
for c in clones
|
|
361
|
+
]
|
|
362
|
+
# Majority vote: average marginal across instances per qubit
|
|
363
|
+
avg_marginals = [
|
|
364
|
+
sum(marginals[i][lq] for i in range(n_instances)) / n_instances
|
|
365
|
+
for lq in range(n_qubits)
|
|
366
|
+
]
|
|
367
|
+
# Force all qubits in first clone to majority-vote outcome
|
|
368
|
+
primary = clones[0]
|
|
369
|
+
for lq in range(n_qubits):
|
|
370
|
+
result = avg_marginals[lq] >= 0.5
|
|
371
|
+
primary.force_m(lq, result)
|
|
372
|
+
# Read out requested qubits
|
|
373
|
+
_sample = primary.m_all()
|
|
374
|
+
sample = 0
|
|
375
|
+
for i in range(len(q)):
|
|
376
|
+
if (_sample >> q[i]) & 1:
|
|
377
|
+
sample |= 1 << i
|
|
378
|
+
samples.append(sample)
|
|
379
|
+
return samples
|
|
380
|
+
|
|
335
381
|
def num_qubits(self):
|
|
336
382
|
return self._row_length * self._col_length
|
|
337
383
|
|
|
@@ -672,8 +718,7 @@ class QrackAceBackend:
|
|
|
672
718
|
b = hq[lhv]
|
|
673
719
|
b.u(th, ph, lm)
|
|
674
720
|
|
|
675
|
-
|
|
676
|
-
self._correct(lq, True, False)
|
|
721
|
+
# Correction deferred to next 2-qubit gate (_cpauli calls _correct)
|
|
677
722
|
|
|
678
723
|
def r(self, p, th, lq):
|
|
679
724
|
hq = self._unpack(lq)
|
|
@@ -696,10 +741,7 @@ class QrackAceBackend:
|
|
|
696
741
|
elif p == Pauli.PauliZ:
|
|
697
742
|
b.rz(th)
|
|
698
743
|
|
|
699
|
-
|
|
700
|
-
self._correct(lq, False, p != Pauli.PauliX)
|
|
701
|
-
if p != Pauli.PauliX:
|
|
702
|
-
self._correct(lq, True)
|
|
744
|
+
# Correction deferred to next 2-qubit gate (_cpauli calls _correct)
|
|
703
745
|
|
|
704
746
|
def h(self, lq):
|
|
705
747
|
hq = self._unpack(lq)
|
|
@@ -719,7 +761,7 @@ class QrackAceBackend:
|
|
|
719
761
|
b = hq[lhv]
|
|
720
762
|
b.h()
|
|
721
763
|
|
|
722
|
-
|
|
764
|
+
# Correction deferred to next 2-qubit gate (_cpauli calls _correct)
|
|
723
765
|
|
|
724
766
|
def s(self, lq):
|
|
725
767
|
hq = self._unpack(lq)
|
|
@@ -1475,38 +1517,48 @@ class QrackAceBackend:
|
|
|
1475
1517
|
return self._coupling_map
|
|
1476
1518
|
|
|
1477
1519
|
# Designed by Dan, and implemented by Elara:
|
|
1478
|
-
def create_noise_model(self, x=0.
|
|
1520
|
+
def create_noise_model(self, x=0.125, y=0.25):
|
|
1479
1521
|
if not _IS_QISKIT_AER_AVAILABLE:
|
|
1480
1522
|
raise RuntimeError(
|
|
1481
1523
|
"Before trying to run_qiskit_circuit() with QrackAceBackend, you must install Qiskit Aer!"
|
|
1482
1524
|
)
|
|
1483
1525
|
noise_model = NoiseModel()
|
|
1484
1526
|
|
|
1527
|
+
# Single-qubit depolarizing only on boundary qubits
|
|
1528
|
+
boundary_qubits = set()
|
|
1529
|
+
for a, b in self.get_logical_coupling_map():
|
|
1530
|
+
col_a = a % self._row_length
|
|
1531
|
+
col_b = b % self._row_length
|
|
1532
|
+
is_long_a = self._is_col_long_range[col_a]
|
|
1533
|
+
is_long_b = self._is_col_long_range[col_b]
|
|
1534
|
+
if not (is_long_a and is_long_b):
|
|
1535
|
+
if not is_long_a:
|
|
1536
|
+
boundary_qubits.add(a)
|
|
1537
|
+
if not is_long_b:
|
|
1538
|
+
boundary_qubits.add(b)
|
|
1539
|
+
|
|
1540
|
+
for q in boundary_qubits:
|
|
1541
|
+
for gate in ["u", "u1", "u2", "u3", "h", "x", "y", "z",
|
|
1542
|
+
"s", "sdg", "t", "tdg", "rx", "ry", "rz"]:
|
|
1543
|
+
noise_model.add_quantum_error(
|
|
1544
|
+
depolarizing_error(x, 1), gate, [q])
|
|
1545
|
+
|
|
1546
|
+
# Two-qubit depolarizing on boundary-crossing and boundary-adjacent gates
|
|
1485
1547
|
for a, b in self.get_logical_coupling_map():
|
|
1486
|
-
col_a
|
|
1487
|
-
|
|
1548
|
+
col_a = a % self._row_length
|
|
1549
|
+
col_b = b % self._row_length
|
|
1488
1550
|
is_long_a = self._is_col_long_range[col_a]
|
|
1489
1551
|
is_long_b = self._is_col_long_range[col_b]
|
|
1490
1552
|
|
|
1491
1553
|
if is_long_a and is_long_b:
|
|
1492
|
-
continue
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
noise_model.add_quantum_error(depolarizing_error(
|
|
1501
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1502
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1503
|
-
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1504
|
-
else:
|
|
1505
|
-
y_cy = 1 - (1 - y) ** 2
|
|
1506
|
-
y_swap = 1 - (1 - y) ** 3
|
|
1507
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cx", [a, b])
|
|
1508
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1509
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1510
|
-
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1554
|
+
continue
|
|
1555
|
+
|
|
1556
|
+
p2 = 1 - (1 - y) ** 2 if (is_long_a or is_long_b) else y
|
|
1557
|
+
p3 = 1 - (1 - y) ** 3 if (is_long_a or is_long_b) else 1 - (1 - y) ** 2
|
|
1558
|
+
|
|
1559
|
+
for gate in ["cx", "cy", "cz"]:
|
|
1560
|
+
noise_model.add_quantum_error(depolarizing_error(p2, 2), gate, [a, b])
|
|
1561
|
+
for gate in ["swap", "iswap"]:
|
|
1562
|
+
noise_model.add_quantum_error(depolarizing_error(p3, 2), gate, [a, b])
|
|
1511
1563
|
|
|
1512
1564
|
return noise_model
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack/qrack_near_clifford_qec_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/requires.txt
RENAMED
|
File without changes
|
{pyqrack_complex128-2.1.0 → pyqrack_complex128-2.1.2}/pyqrack_complex128.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|