pyqrack-complex128 2.22.2__tar.gz → 2.22.4__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.22.2/pyqrack_complex128.egg-info → pyqrack_complex128-2.22.4}/PKG-INFO +1 -1
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_ace_backend.py +130 -31
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4/pyqrack_complex128.egg-info}/PKG-INFO +1 -1
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/setup.py +1 -1
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/LICENSE +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/MANIFEST.in +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/Makefile +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/README.md +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyproject.toml +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/__init__.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/pauli.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/SOURCES.txt +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/dependency_links.txt +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/not-zip-safe +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/requires.txt +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/top_level.txt +0 -0
- {pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/setup.cfg +0 -0
|
@@ -1552,7 +1552,7 @@ class QrackAceBackend:
|
|
|
1552
1552
|
# this gate family only -- same reasoning as the earlier
|
|
1553
1553
|
# single-replica CZ dual-check, just applied at the logical
|
|
1554
1554
|
# level now.
|
|
1555
|
-
anc1, anc2, anc1b = None, None, None
|
|
1555
|
+
anc1, anc2, anc1b, anc1c = None, None, None, None
|
|
1556
1556
|
if self.is_error_detection and not self._in_gadget_capture and ((len(hq1) > 1) or (len(hq2) > 1)):
|
|
1557
1557
|
anc1 = self._detect_ancilla1_lq[hq1[0][0]]
|
|
1558
1558
|
self._in_gadget_capture = True
|
|
@@ -1564,6 +1564,23 @@ class QrackAceBackend:
|
|
|
1564
1564
|
# Control bit-flip
|
|
1565
1565
|
self.cx(lq1, anc1b)
|
|
1566
1566
|
|
|
1567
|
+
# Third participant: hq1 is a boundary qubit here
|
|
1568
|
+
# (len(hq1) > 1), so it always carries a genuine physical
|
|
1569
|
+
# replica in the shared boundary "crossbar" simulator too
|
|
1570
|
+
# -- index 2 of its replica list, by construction (see
|
|
1571
|
+
# __init__'s qubit-building loop: the crossbar replica is
|
|
1572
|
+
# always appended right after the (up to two) patch
|
|
1573
|
+
# replicas, for every boundary qubit, edge or corner
|
|
1574
|
+
# alike). That replica was never checked by this gadget
|
|
1575
|
+
# before now, even though it's a distinct physical copy
|
|
1576
|
+
# of lq1's value -- give it its own dedicated ancilla,
|
|
1577
|
+
# already allocated in the crossbar sim alongside every
|
|
1578
|
+
# other simulator's pair, and capture lq1 through it the
|
|
1579
|
+
# same nested-cx way as anc1/anc1b, so it can vote
|
|
1580
|
+
# alongside them below instead of going unchecked.
|
|
1581
|
+
anc1c = self._detect_ancilla1_lq[hq1[2][0]]
|
|
1582
|
+
self.cx(lq1, anc1c)
|
|
1583
|
+
|
|
1567
1584
|
anc2 = self._detect_ancilla2_lq[hq1[0][0]]
|
|
1568
1585
|
# XOR on target
|
|
1569
1586
|
self.cx(lq2, anc2)
|
|
@@ -1645,38 +1662,120 @@ class QrackAceBackend:
|
|
|
1645
1662
|
# probability), reset the ancilla back to |0>, and apply
|
|
1646
1663
|
# a corrective X to lq1 to restore the detected
|
|
1647
1664
|
# invariant.
|
|
1648
|
-
if anc1b is not None:
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1665
|
+
if (anc1b is not None) or (anc1c is not None):
|
|
1666
|
+
# Generalized N-way version (N = 2 or 3, i.e. patch A and
|
|
1667
|
+
# patch B and/or the crossbar's own replica) of the
|
|
1668
|
+
# single-pair steering above: same per-participant rule,
|
|
1669
|
+
# just no longer hand-written per pair. Read every
|
|
1670
|
+
# participant's prob() BEFORE forcing any of them (a
|
|
1671
|
+
# forced measurement can affect correlated others), find
|
|
1672
|
+
# whichever one -- if any -- shows confident (within
|
|
1673
|
+
# ps_epsilon of certain) evidence of an actual flip, force
|
|
1674
|
+
# THAT one first (the branch its own probability actually
|
|
1675
|
+
# supports, never the near-impossible one), then for each
|
|
1676
|
+
# remaining participant either steer it to agree (force
|
|
1677
|
+
# True) if its own signal is too close to the hard-zero
|
|
1678
|
+
# boundary to trust as an honest independent reading, or
|
|
1679
|
+
# let it measure honestly otherwise -- exactly the same
|
|
1680
|
+
# judgment call the original single anc1b case made, now
|
|
1681
|
+
# just applied per-participant in a loop. If nobody shows
|
|
1682
|
+
# confident evidence of a flip, every participant is
|
|
1683
|
+
# forced to the "no error" branch, as before.
|
|
1684
|
+
ancs = [anc1] + ([anc1b] if anc1b is not None else []) + ([anc1c] if anc1c is not None else [])
|
|
1685
|
+
# Complete each participant's before/after XOR capture
|
|
1686
|
+
# (anc1's own second cx() already happened just above,
|
|
1687
|
+
# unconditionally) before reading any prob() below.
|
|
1688
|
+
if anc1b is not None:
|
|
1689
|
+
self.cx(lq1, anc1b)
|
|
1690
|
+
if anc1c is not None:
|
|
1691
|
+
self.cx(lq1, anc1c)
|
|
1692
|
+
probs = []
|
|
1693
|
+
for a in ancs:
|
|
1694
|
+
anc_sim, anc_idx = self._qubits[a][0]
|
|
1695
|
+
probs.append(self.sim[anc_sim].prob(anc_idx))
|
|
1696
|
+
|
|
1697
|
+
anchor = None
|
|
1698
|
+
for i in range(len(ancs)):
|
|
1699
|
+
if self._ps_epsilon >= (1.0 - probs[i]):
|
|
1700
|
+
anchor = i
|
|
1701
|
+
break
|
|
1702
|
+
|
|
1703
|
+
bits = [None] * len(ancs)
|
|
1704
|
+
if anchor is not None:
|
|
1705
|
+
bits[anchor] = self.force_m(ancs[anchor], True)
|
|
1706
|
+
for i in range(len(ancs)):
|
|
1707
|
+
if i == anchor:
|
|
1708
|
+
continue
|
|
1709
|
+
if self._ps_epsilon >= probs[i]:
|
|
1710
|
+
bits[i] = self.force_m(ancs[i], True)
|
|
1711
|
+
else:
|
|
1712
|
+
bits[i] = self.m(ancs[i])
|
|
1666
1713
|
else:
|
|
1667
|
-
|
|
1668
|
-
|
|
1714
|
+
bits = [self.force_m(a, False) for a in ancs]
|
|
1715
|
+
|
|
1716
|
+
# Map each participant to the SPECIFIC physical replica
|
|
1717
|
+
# of hq1 its own syndrome actually covers -- anc1 is
|
|
1718
|
+
# patch A (hq1[0]), anc1c is always the crossbar
|
|
1719
|
+
# (hq1[2], by construction), and anc1b is whichever of
|
|
1720
|
+
# hq1's replicas lives in hq2's own patch (found by sim
|
|
1721
|
+
# id rather than assumed to be a fixed index, since
|
|
1722
|
+
# corner qubits have patch replicas at indices 1, 3, and
|
|
1723
|
+
# 4). This can legitimately be absent: hq1 and hq2 may
|
|
1724
|
+
# share no common patch at all for an arbitrary (non-
|
|
1725
|
+
# adjacent) logical coupling -- confirmed directly
|
|
1726
|
+
# (hq1=[(2,1),(3,0),(4,2)] coupled to hq2=[(1,1)], no
|
|
1727
|
+
# overlap) -- in which case there is no single physical
|
|
1728
|
+
# replica to target for that participant specifically.
|
|
1729
|
+
replicas = [hq1[0]]
|
|
1730
|
+
if anc1b is not None:
|
|
1731
|
+
replicas.append(next((r for r in hq1 if r[0] == hq2[0][0]), None))
|
|
1732
|
+
if anc1c is not None:
|
|
1733
|
+
replicas.append(hq1[2])
|
|
1734
|
+
|
|
1735
|
+
# Majority vote decides whether the LOGICAL value itself
|
|
1736
|
+
# genuinely flipped (updating the LHV shadow, same as the
|
|
1737
|
+
# transversal self.x(lq1) used to do unconditionally);
|
|
1738
|
+
# any minority participant is still individually
|
|
1739
|
+
# corrected below regardless, since ITS replica is wrong
|
|
1740
|
+
# either way -- it just isn't treated as evidence the
|
|
1741
|
+
# logical value moved, the same way a repetition code's
|
|
1742
|
+
# decoded value doesn't change just because one physical
|
|
1743
|
+
# bit needed fixing.
|
|
1669
1744
|
is_flipped = False
|
|
1670
|
-
if
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1745
|
+
n_flipped = sum(1 for b in bits if b)
|
|
1746
|
+
if (n_flipped << 1) > len(ancs):
|
|
1747
|
+
is_flipped = True
|
|
1748
|
+
lhv = self._lhv.get(lq1)
|
|
1749
|
+
if lhv is not None:
|
|
1750
|
+
lhv.x()
|
|
1751
|
+
|
|
1752
|
+
for i, a in enumerate(ancs):
|
|
1753
|
+
if bits[i]:
|
|
1754
|
+
self.x(a)
|
|
1755
|
+
# Targeted, single-replica correction rather than
|
|
1756
|
+
# a transversal self.x(lq1): these replicas are a
|
|
1757
|
+
# pseudo-repetition code for lq1, and a
|
|
1758
|
+
# participant flipping means THAT PHYSICAL COPY
|
|
1759
|
+
# is the one in error, not the logical value as a
|
|
1760
|
+
# whole. Flipping every replica transversally is
|
|
1761
|
+
# only ever correct by coincidence when all
|
|
1762
|
+
# participants agree -- on a genuine minority
|
|
1763
|
+
# disagreement it would "fix" the actual error
|
|
1764
|
+
# while simultaneously breaking the (correct)
|
|
1765
|
+
# majority replicas that were never wrong. Fixing
|
|
1766
|
+
# per-replica is correct in the agreeing case too
|
|
1767
|
+
# (each flipped participant's own replica still
|
|
1768
|
+
# gets corrected), so this applies unconditionally,
|
|
1769
|
+
# not just when a disagreement is detected. Falls
|
|
1770
|
+
# back to the transversal correction only when no
|
|
1771
|
+
# single hq1 replica corresponds to this
|
|
1772
|
+
# participant at all (see the no-overlap case
|
|
1773
|
+
# above).
|
|
1774
|
+
b = replicas[i]
|
|
1775
|
+
if b is not None:
|
|
1776
|
+
self.sim[b[0]].x(b[1])
|
|
1777
|
+
else:
|
|
1778
|
+
self.x(lq1)
|
|
1680
1779
|
else:
|
|
1681
1780
|
anc_sim, anc_idx = self._qubits[anc1][0]
|
|
1682
1781
|
p = self.sim[anc_sim].prob(anc_idx)
|
|
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.22.2 → pyqrack_complex128-2.22.4}/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
|
{pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/qrack_system/qrack_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack/stats/load_quantized_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/requires.txt
RENAMED
|
File without changes
|
{pyqrack_complex128-2.22.2 → pyqrack_complex128-2.22.4}/pyqrack_complex128.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|