pyqrack-complex128 2.29.2__tar.gz → 2.29.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.29.2/pyqrack_complex128.egg-info → pyqrack_complex128-2.29.4}/PKG-INFO +1 -1
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_ace_backend.py +139 -85
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4/pyqrack_complex128.egg-info}/PKG-INFO +1 -1
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/setup.py +1 -1
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/LICENSE +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/MANIFEST.in +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/Makefile +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/README.md +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyproject.toml +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/__init__.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/pauli.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_ace_mps_backend.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/SOURCES.txt +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/dependency_links.txt +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/not-zip-safe +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/requires.txt +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/top_level.txt +0 -0
- {pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/setup.cfg +0 -0
|
@@ -262,7 +262,7 @@ class QrackAceBackend:
|
|
|
262
262
|
is_torus=True,
|
|
263
263
|
is_1d_chain=False,
|
|
264
264
|
is_error_detection=True,
|
|
265
|
-
is_boundary_repetition_code=
|
|
265
|
+
is_boundary_repetition_code=True,
|
|
266
266
|
use_crossbars=True,
|
|
267
267
|
to_clone=None,
|
|
268
268
|
):
|
|
@@ -471,31 +471,39 @@ class QrackAceBackend:
|
|
|
471
471
|
lq_idx = len(self.qubits)
|
|
472
472
|
self.qubits.append([(sim_id, phys_idx)])
|
|
473
473
|
self.detect_ancilla_lq.append(lq_idx)
|
|
474
|
-
# Boundary repetition code
|
|
475
|
-
#
|
|
476
|
-
#
|
|
477
|
-
#
|
|
478
|
-
#
|
|
479
|
-
#
|
|
480
|
-
#
|
|
481
|
-
#
|
|
482
|
-
#
|
|
483
|
-
#
|
|
484
|
-
#
|
|
485
|
-
#
|
|
486
|
-
#
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
474
|
+
# Boundary repetition code (zero-ancilla, "authority" decoder).
|
|
475
|
+
#
|
|
476
|
+
# A boundary qubit's replicas ARE already a repetition code: 2-5
|
|
477
|
+
# copies of one logical qubit, one per simulator. Single-qubit gates
|
|
478
|
+
# act on every copy exactly, so the only place the copies can
|
|
479
|
+
# diverge is a coupling with a qubit on some other simulator. In
|
|
480
|
+
# that coupling, exactly the replica(s) sharing a simulator with the
|
|
481
|
+
# partner receive the REAL gate (and any real entanglement it
|
|
482
|
+
# creates); every other copy receives only the classical shadow.
|
|
483
|
+
# So the decoder has side information a hardware repetition code
|
|
484
|
+
# doesn't: it knows WHICH copy is fresh. That is the lesson of the
|
|
485
|
+
# Shor-9 layout experiments (ace_shor_9_one_side.py): a code works
|
|
486
|
+
# on ACE when the state lives in the one simulator that shares the
|
|
487
|
+
# couplings, and the far-side copies are what needs reconciling.
|
|
488
|
+
#
|
|
489
|
+
# With this option on, every multi-replica coupling records which
|
|
490
|
+
# replica slot(s) of each boundary participant were real-gated
|
|
491
|
+
# ("authority"). correct() then treats the authority copy as the
|
|
492
|
+
# decoder's ground truth -- flipping stale copies to match it when
|
|
493
|
+
# it is decisive, rotating them toward its Bloch direction when it
|
|
494
|
+
# is still separable, and never touching the authority copy itself
|
|
495
|
+
# -- instead of the fixed home-slot-first cascade (which is right
|
|
496
|
+
# only when the partner happened to share the home simulator).
|
|
497
|
+
# prob() reads the authority copy's own marginal. No qubits are
|
|
498
|
+
# allocated: qubit overhead is zero. The authority record clears
|
|
499
|
+
# whenever every replica is fresh again (a fully matched coupling,
|
|
500
|
+
# or a measurement).
|
|
501
|
+
self._authority = (
|
|
502
|
+
{k: set(v) for k, v in to_clone._authority.items()} if to_clone else {}
|
|
503
|
+
)
|
|
504
|
+
# Kept (always empty) for compatibility with code that inspected the
|
|
505
|
+
# old per-patch scratch ancillae of the previous on-demand design.
|
|
493
506
|
self.rep_code_ancilla_lq = []
|
|
494
|
-
if self.is_boundary_repetition_code:
|
|
495
|
-
for sim_id, phys_idx in enumerate(rep_code_ancilla):
|
|
496
|
-
lq_idx = len(self.qubits)
|
|
497
|
-
self.qubits.append([(sim_id, phys_idx)])
|
|
498
|
-
self.rep_code_ancilla_lq.append(lq_idx)
|
|
499
507
|
|
|
500
508
|
# capture calls (see _apply_coupling): those calls go through
|
|
501
509
|
# the ordinary _cpauli -> _apply_coupling path themselves, which
|
|
@@ -892,7 +900,10 @@ class QrackAceBackend:
|
|
|
892
900
|
if lq in self.lhv:
|
|
893
901
|
self.lhv[lq].h()
|
|
894
902
|
|
|
895
|
-
|
|
903
|
+
fresh = self._authority.get(lq) if self.is_boundary_repetition_code else None
|
|
904
|
+
if fresh:
|
|
905
|
+
self._correct_by_authority(lq, hq, fresh, skip_rotation)
|
|
906
|
+
elif len(hq) == 4:
|
|
896
907
|
# Corner-boundary qubit: 4 real replicas remain (home,
|
|
897
908
|
# adjacent-patch, and the 2 diagonal-patch shadows) now that
|
|
898
909
|
# the crossbar replica that used to sit at old-index-2 is
|
|
@@ -1592,6 +1603,52 @@ class QrackAceBackend:
|
|
|
1592
1603
|
|
|
1593
1604
|
return connected, boundary
|
|
1594
1605
|
|
|
1606
|
+
def _set_authority(self, lq, hq, partner_hq):
|
|
1607
|
+
# Record which replica slot(s) of boundary qubit lq just received a
|
|
1608
|
+
# REAL coupling gate (they share a simulator with the partner). See
|
|
1609
|
+
# the constructor for the decoder this feeds. Skipped for the
|
|
1610
|
+
# detection gadget's own internal captures, which must not move it.
|
|
1611
|
+
if (not self.is_boundary_repetition_code) or self._in_gadget_capture or (lq is None) or (len(hq) < 2):
|
|
1612
|
+
return
|
|
1613
|
+
partner_sims = {b[0] for b in partner_hq}
|
|
1614
|
+
fresh = {i for i, b in enumerate(hq) if b[0] in partner_sims}
|
|
1615
|
+
if not fresh:
|
|
1616
|
+
# Shadow-only coupling: no copy is fresher than before.
|
|
1617
|
+
return
|
|
1618
|
+
if len(fresh) == len(hq):
|
|
1619
|
+
# Every copy got the real gate: no copy is privileged.
|
|
1620
|
+
self._authority.pop(lq, None)
|
|
1621
|
+
else:
|
|
1622
|
+
self._authority[lq] = fresh
|
|
1623
|
+
|
|
1624
|
+
def _correct_by_authority(self, lq, hq, fresh, skip_rotation):
|
|
1625
|
+
# Decode boundary qubit lq's replica repetition code with the
|
|
1626
|
+
# fresh copy (or copies) as ground truth. See the constructor.
|
|
1627
|
+
auth = sorted(fresh)
|
|
1628
|
+
p_auth = sum(self.sim[hq[i][0]].prob(hq[i][1]) for i in auth) / len(auth)
|
|
1629
|
+
if abs(p_auth - 0.5) > self._epsilon:
|
|
1630
|
+
result = p_auth >= 0.5
|
|
1631
|
+
for q, b in enumerate(hq):
|
|
1632
|
+
if q in fresh:
|
|
1633
|
+
continue
|
|
1634
|
+
p = self.sim[b[0]].prob(b[1])
|
|
1635
|
+
if (1 - p if result else p) > (0.5 + self._epsilon):
|
|
1636
|
+
self.sim[b[0]].x(b[1])
|
|
1637
|
+
if skip_rotation:
|
|
1638
|
+
return
|
|
1639
|
+
a0, i0, r0 = self._get_bloch_angles(hq[auth[0]])
|
|
1640
|
+
if r0 > self._rot_epsilon:
|
|
1641
|
+
# The fresh copy is itself entangled with its partner: it has no
|
|
1642
|
+
# well-defined direction to copy, and the stale copies cannot
|
|
1643
|
+
# hold that entanglement anyway. prob() reads the fresh copy.
|
|
1644
|
+
return
|
|
1645
|
+
for q, b in enumerate(hq):
|
|
1646
|
+
if q in fresh:
|
|
1647
|
+
continue
|
|
1648
|
+
a, i, r = self._get_bloch_angles(b)
|
|
1649
|
+
if r <= self._rot_epsilon:
|
|
1650
|
+
self._rotate_to_bloch(b, a0 - a, i0 - i)
|
|
1651
|
+
|
|
1595
1652
|
def _apply_coupling(self, pauli, anti, qb1, hq1, qb2, hq2, lq1_lr, lq1=None, lq2=None):
|
|
1596
1653
|
shadow_targets = []
|
|
1597
1654
|
|
|
@@ -1601,6 +1658,8 @@ class QrackAceBackend:
|
|
|
1601
1658
|
gate_fn, shadow_fn = self._get_gate(pauli, anti, sim_id)
|
|
1602
1659
|
_, idx2 = hq2[i]
|
|
1603
1660
|
gate_fn([idx1], idx2)
|
|
1661
|
+
self._set_authority(lq1, hq1, hq2)
|
|
1662
|
+
self._set_authority(lq2, hq2, hq1)
|
|
1604
1663
|
return
|
|
1605
1664
|
|
|
1606
1665
|
# Logical-level error-detection gadget: an earlier version of this
|
|
@@ -1629,7 +1688,7 @@ class QrackAceBackend:
|
|
|
1629
1688
|
# a lq2-invariant check for that gate family, same reasoning as
|
|
1630
1689
|
# the single-replica CZ dual-check elsewhere.
|
|
1631
1690
|
anc = None
|
|
1632
|
-
if self.is_error_detection and (not self._in_gadget_capture) and ((len(hq1) > 1) or (len(hq2) > 1)):
|
|
1691
|
+
if (not self.is_boundary_repetition_code) and self.is_error_detection and (not self._in_gadget_capture) and ((len(hq1) > 1) or (len(hq2) > 1)):
|
|
1633
1692
|
anc_sim = hq1[0][0]
|
|
1634
1693
|
t_sims = {y[0] for y in hq2 if y[0] >= 0}
|
|
1635
1694
|
for x in hq1:
|
|
@@ -1702,6 +1761,9 @@ class QrackAceBackend:
|
|
|
1702
1761
|
shadow_fn(b1, b2)
|
|
1703
1762
|
shadow_targets.append(b2)
|
|
1704
1763
|
|
|
1764
|
+
self._set_authority(lq1, hq1, hq2)
|
|
1765
|
+
self._set_authority(lq2, hq2, hq1)
|
|
1766
|
+
|
|
1705
1767
|
if not self._in_gadget_capture:
|
|
1706
1768
|
if pauli != Pauli.PauliZ:
|
|
1707
1769
|
self.correct(lq2, False, pauli != Pauli.PauliX)
|
|
@@ -1754,55 +1816,18 @@ class QrackAceBackend:
|
|
|
1754
1816
|
lq1_lr = len(hq1) == 1
|
|
1755
1817
|
lq2_lr = len(hq2) == 1
|
|
1756
1818
|
|
|
1757
|
-
t2 = [lq2]
|
|
1758
|
-
anc, anc_sim = None, None
|
|
1759
|
-
if self.is_boundary_repetition_code and (not self._in_gadget_capture) and lq1_lr and (not lq2_lr):
|
|
1760
|
-
# Encode:
|
|
1761
|
-
anc_sim = hq1[0][0]
|
|
1762
|
-
t_sims = {y[0] for y in hq2 if y[0] >= 0}
|
|
1763
|
-
for x in hq1:
|
|
1764
|
-
if x[0] in t_sims:
|
|
1765
|
-
anc_sim = x[0]
|
|
1766
|
-
break
|
|
1767
|
-
anc = self.rep_code_ancilla_lq[anc_sim]
|
|
1768
|
-
self._in_gadget_capture = True
|
|
1769
|
-
self.cx(lq2, anc)
|
|
1770
|
-
self._in_gadget_capture = False
|
|
1771
|
-
t2.append(anc)
|
|
1772
|
-
|
|
1773
1819
|
qb1, _ = QrackAceBackend._get_qb_lhv_indices(hq1)
|
|
1774
1820
|
|
|
1775
1821
|
# Apply cross coupling on every real replica in hq1/h2 (the LHV
|
|
1776
1822
|
# proxy is coupled separately, just below, via _cpauli_lhv -- it
|
|
1777
|
-
# is not one of hq's indices).
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
qb2, _ = QrackAceBackend._get_qb_lhv_indices(h2)
|
|
1781
|
-
self._apply_coupling(pauli, anti, qb1, hq1, qb2, h2, lq1_lr, lq1, l2)
|
|
1823
|
+
# is not one of hq's indices).
|
|
1824
|
+
qb2, _ = QrackAceBackend._get_qb_lhv_indices(hq2)
|
|
1825
|
+
self._apply_coupling(pauli, anti, qb1, hq1, qb2, hq2, lq1_lr, lq1, lq2)
|
|
1782
1826
|
|
|
1783
1827
|
if lq2 in self.lhv:
|
|
1784
1828
|
ctrl_prob = self.sim[hq1[0][0]].prob(hq1[0][1])
|
|
1785
1829
|
_cpauli_lhv(ctrl_prob, self.lhv[lq2], pauli, anti)
|
|
1786
1830
|
|
|
1787
|
-
if anc is not None:
|
|
1788
|
-
# Decode:
|
|
1789
|
-
self._in_gadget_capture = True
|
|
1790
|
-
self.cx(lq2, anc)
|
|
1791
|
-
self._in_gadget_capture = False
|
|
1792
|
-
|
|
1793
|
-
# After we corrected any mismatch above, it's unlikely
|
|
1794
|
-
# that we can't post-select no-error on this ancilla.
|
|
1795
|
-
|
|
1796
|
-
anc_sim, anc_idx = self.qubits[anc][0]
|
|
1797
|
-
p = self.sim[anc_sim].prob(anc_idx)
|
|
1798
|
-
if self._ps_epsilon >= (1.0 - p):
|
|
1799
|
-
b = self.m(anc)
|
|
1800
|
-
else:
|
|
1801
|
-
b = self.force_m(anc, False)
|
|
1802
|
-
if b:
|
|
1803
|
-
self.x(anc)
|
|
1804
|
-
self.x(lq2)
|
|
1805
|
-
|
|
1806
1831
|
def cx(self, lq1, lq2):
|
|
1807
1832
|
self._cpauli(lq1, lq2, False, Pauli.PauliX)
|
|
1808
1833
|
|
|
@@ -2071,6 +2096,13 @@ class QrackAceBackend:
|
|
|
2071
2096
|
if lhv1 is not None:
|
|
2072
2097
|
self.lhv[lq2] = lhv1
|
|
2073
2098
|
|
|
2099
|
+
auth1 = self._authority.pop(lq1, None)
|
|
2100
|
+
auth2 = self._authority.pop(lq2, None)
|
|
2101
|
+
if auth2 is not None:
|
|
2102
|
+
self._authority[lq1] = auth2
|
|
2103
|
+
if auth1 is not None:
|
|
2104
|
+
self._authority[lq2] = auth1
|
|
2105
|
+
|
|
2074
2106
|
# Boundary repetition code needs no bookkeeping here, unlike
|
|
2075
2107
|
# self.qubits/self.lhv just above: it's on-demand now, not
|
|
2076
2108
|
# a permanent, per-logical-index dict of pre-allocated
|
|
@@ -2161,6 +2193,23 @@ class QrackAceBackend:
|
|
|
2161
2193
|
self.cz(lq1, lq2)
|
|
2162
2194
|
self.swap(lq1, lq2)
|
|
2163
2195
|
|
|
2196
|
+
def _ccx_decomp(self, c1, c2, t):
|
|
2197
|
+
self.h(t)
|
|
2198
|
+
self.cx(c2, t)
|
|
2199
|
+
self.adjt(t)
|
|
2200
|
+
self.cx(c1, t)
|
|
2201
|
+
self.t(t)
|
|
2202
|
+
self.cx(c2, t)
|
|
2203
|
+
self.adjt(t)
|
|
2204
|
+
self.cx(c1, t)
|
|
2205
|
+
self.t(t)
|
|
2206
|
+
self.h(t)
|
|
2207
|
+
self.t(c2)
|
|
2208
|
+
self.cx(c1, c2)
|
|
2209
|
+
self.t(c1)
|
|
2210
|
+
self.adjt(c2)
|
|
2211
|
+
self.cx(c1, c2)
|
|
2212
|
+
|
|
2164
2213
|
def ccx(self, c1, c2, t):
|
|
2165
2214
|
hq1 = self._unpack(c1)
|
|
2166
2215
|
hq2 = self._unpack(c2)
|
|
@@ -2170,6 +2219,11 @@ class QrackAceBackend:
|
|
|
2170
2219
|
self.mcx([c1, c2], t)
|
|
2171
2220
|
return
|
|
2172
2221
|
|
|
2222
|
+
if (len(hq1) > 1) or (len(hq2) > 1):
|
|
2223
|
+
self._ccx_decomp(c1, c2, t)
|
|
2224
|
+
|
|
2225
|
+
return
|
|
2226
|
+
|
|
2173
2227
|
qb1, _ = QrackAceBackend._get_qb_lhv_indices(hq1)
|
|
2174
2228
|
qb2, _ = QrackAceBackend._get_qb_lhv_indices(hq2)
|
|
2175
2229
|
qbt, _ = QrackAceBackend._get_qb_lhv_indices(hqt)
|
|
@@ -2194,26 +2248,12 @@ class QrackAceBackend:
|
|
|
2194
2248
|
witnesses.append(witness)
|
|
2195
2249
|
|
|
2196
2250
|
if needs_shadow:
|
|
2197
|
-
self.
|
|
2198
|
-
self.cx(c2, t)
|
|
2199
|
-
self.adjt(t)
|
|
2200
|
-
self.cx(c1, t)
|
|
2201
|
-
self.t(t)
|
|
2202
|
-
self.cx(c2, t)
|
|
2203
|
-
self.adjt(t)
|
|
2204
|
-
self.cx(c1, t)
|
|
2205
|
-
self.t(t)
|
|
2206
|
-
self.h(t)
|
|
2207
|
-
self.t(c2)
|
|
2208
|
-
self.cx(c1, c2)
|
|
2209
|
-
self.t(c1)
|
|
2210
|
-
self.adjt(c2)
|
|
2211
|
-
self.cx(c1, c2)
|
|
2251
|
+
self._ccx_decomp(c1, c2, t)
|
|
2212
2252
|
|
|
2213
2253
|
return
|
|
2214
2254
|
|
|
2215
2255
|
anc_and = None
|
|
2216
|
-
if self.
|
|
2256
|
+
if (not self.is_boundary_repetition_code) and self.is_error_detection and (not self._in_gadget_capture):
|
|
2217
2257
|
found = False
|
|
2218
2258
|
anc_sim = hq1[0][0]
|
|
2219
2259
|
t_sims = {y[0] for y in hqt if y[0] >= 0}
|
|
@@ -2229,6 +2269,7 @@ class QrackAceBackend:
|
|
|
2229
2269
|
break
|
|
2230
2270
|
if found:
|
|
2231
2271
|
break
|
|
2272
|
+
self._in_gadget_capture = True
|
|
2232
2273
|
anc_and = self.detect_ancilla_lq[anc_sim]
|
|
2233
2274
|
self.cx(t, anc_and)
|
|
2234
2275
|
c1_idx = next((r[1] for r in hq1 if r[0] == anc_sim), None)
|
|
@@ -2237,9 +2278,8 @@ class QrackAceBackend:
|
|
|
2237
2278
|
_, anc_and_idx = self.qubits[anc_and][0]
|
|
2238
2279
|
self.sim[anc_sim].mcx([c1_idx, c2_idx], anc_and_idx)
|
|
2239
2280
|
else:
|
|
2240
|
-
self._in_gadget_capture = True
|
|
2241
2281
|
self.ccx(c1, c2, anc_and)
|
|
2242
|
-
|
|
2282
|
+
self._in_gadget_capture = False
|
|
2243
2283
|
|
|
2244
2284
|
self.correct(c1)
|
|
2245
2285
|
self.correct(c2)
|
|
@@ -2250,6 +2290,7 @@ class QrackAceBackend:
|
|
|
2250
2290
|
self.correct(t)
|
|
2251
2291
|
|
|
2252
2292
|
if anc_and is not None:
|
|
2293
|
+
self._in_gadget_capture = True
|
|
2253
2294
|
self.cx(t, anc_and)
|
|
2254
2295
|
anc_sim, anc_idx = self.qubits[anc_and][0]
|
|
2255
2296
|
p = self.sim[anc_sim].prob(anc_idx)
|
|
@@ -2261,6 +2302,7 @@ class QrackAceBackend:
|
|
|
2261
2302
|
if b:
|
|
2262
2303
|
self.x(anc_and)
|
|
2263
2304
|
self.x(t)
|
|
2305
|
+
self._in_gadget_capture = False
|
|
2264
2306
|
|
|
2265
2307
|
def ccz(self, c1, c2, t):
|
|
2266
2308
|
self.h(t)
|
|
@@ -2290,6 +2332,12 @@ class QrackAceBackend:
|
|
|
2290
2332
|
# re-weighting any particular replica specially here would
|
|
2291
2333
|
# reintroduce the same center-dragging distortion the cascade in
|
|
2292
2334
|
# correct() was built to avoid.
|
|
2335
|
+
fresh = self._authority.get(lq) if self.is_boundary_repetition_code else None
|
|
2336
|
+
if fresh:
|
|
2337
|
+
# The fresh copy carries the real marginal (and any real
|
|
2338
|
+
# entanglement); the stale copies were just reconciled to it.
|
|
2339
|
+
return sum(self.sim[hq[i][0]].prob(hq[i][1]) for i in fresh) / len(fresh)
|
|
2340
|
+
|
|
2293
2341
|
p = [self.sim[b[0]].prob(b[1]) for b in hq]
|
|
2294
2342
|
n = len(p)
|
|
2295
2343
|
prms = math.sqrt(sum(x**2 for x in p) / n)
|
|
@@ -2323,6 +2371,9 @@ class QrackAceBackend:
|
|
|
2323
2371
|
if result:
|
|
2324
2372
|
lhv.x()
|
|
2325
2373
|
|
|
2374
|
+
# Every replica now agrees on a definite value: none is fresher.
|
|
2375
|
+
self._authority.pop(lq, None)
|
|
2376
|
+
|
|
2326
2377
|
return result
|
|
2327
2378
|
|
|
2328
2379
|
def force_m(self, lq, result):
|
|
@@ -2350,6 +2401,9 @@ class QrackAceBackend:
|
|
|
2350
2401
|
if result:
|
|
2351
2402
|
lhv.x()
|
|
2352
2403
|
|
|
2404
|
+
# Every replica now agrees on a definite value: none is fresher.
|
|
2405
|
+
self._authority.pop(lq, None)
|
|
2406
|
+
|
|
2353
2407
|
return result
|
|
2354
2408
|
|
|
2355
2409
|
def m_all(self):
|
|
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.29.2 → pyqrack_complex128-2.29.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.29.2 → pyqrack_complex128-2.29.4}/pyqrack/qrack_system/qrack_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack/stats/load_quantized_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/requires.txt
RENAMED
|
File without changes
|
{pyqrack_complex128-2.29.2 → pyqrack_complex128-2.29.4}/pyqrack_complex128.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|