pyqrack-cpu 2.18.1__tar.gz → 2.18.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_cpu-2.18.1/pyqrack_cpu.egg-info → pyqrack_cpu-2.18.2}/PKG-INFO +1 -1
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_ace_backend.py +66 -42
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2/pyqrack_cpu.egg-info}/PKG-INFO +1 -1
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/setup.py +1 -1
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/LICENSE +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/MANIFEST.in +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/Makefile +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/README.md +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyproject.toml +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/__init__.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/pauli.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack_cpu.egg-info/SOURCES.txt +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack_cpu.egg-info/dependency_links.txt +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack_cpu.egg-info/not-zip-safe +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack_cpu.egg-info/requires.txt +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/pyqrack_cpu.egg-info/top_level.txt +0 -0
- {pyqrack_cpu-2.18.1 → pyqrack_cpu-2.18.2}/setup.cfg +0 -0
|
@@ -1456,42 +1456,25 @@ class QrackAceBackend:
|
|
|
1456
1456
|
b2 = hq2[q2]
|
|
1457
1457
|
if b1[0] == b2[0]:
|
|
1458
1458
|
if self.is_error_detection:
|
|
1459
|
-
#
|
|
1460
|
-
# post-
|
|
1461
|
-
#
|
|
1462
|
-
#
|
|
1463
|
-
#
|
|
1464
|
-
#
|
|
1465
|
-
#
|
|
1466
|
-
#
|
|
1467
|
-
#
|
|
1468
|
-
#
|
|
1469
|
-
#
|
|
1470
|
-
#
|
|
1471
|
-
#
|
|
1472
|
-
#
|
|
1473
|
-
#
|
|
1474
|
-
#
|
|
1475
|
-
#
|
|
1476
|
-
# --
|
|
1477
|
-
#
|
|
1478
|
-
# repeat, done in one step because the simulator
|
|
1479
|
-
# has the full state to project, not just samples
|
|
1480
|
-
# from it. The same ancilla is reused for every
|
|
1481
|
-
# gate touching this simulator: each round-trip is
|
|
1482
|
-
# self-contained and leaves the ancilla at |0>
|
|
1483
|
-
# again whenever nothing was detected, so there's
|
|
1484
|
-
# no cross-gate bookkeeping needed.
|
|
1485
|
-
#
|
|
1486
|
-
# Deliberately single-patch, not multi-patch: this
|
|
1487
|
-
# protects b1 exactly where the real gate touches
|
|
1488
|
-
# it. A multi-patch version (sandwiching every
|
|
1489
|
-
# replica of lq1 across every patch it lives in)
|
|
1490
|
-
# was tried and measured worse -- RCS XEB against
|
|
1491
|
-
# this architecture's own intrinsic approximation
|
|
1492
|
-
# error confirmed the single-patch version here is
|
|
1493
|
-
# the one that actually works well; the multi-patch
|
|
1494
|
-
# generalization added cost without benefit.
|
|
1459
|
+
# Single-patch, not multi-patch: force_m's
|
|
1460
|
+
# post-selection isn't local to the one
|
|
1461
|
+
# simulator it's physically called on -- the
|
|
1462
|
+
# projection it performs reflects the "lab
|
|
1463
|
+
# frame" ground truth for whatever it's checking,
|
|
1464
|
+
# not an independent per-patch fact. Since every
|
|
1465
|
+
# replica of a boundary qubit is meant to
|
|
1466
|
+
# represent the SAME logical value, checking that
|
|
1467
|
+
# invariant via any one patch that has a real
|
|
1468
|
+
# gate touching it already captures the full
|
|
1469
|
+
# syndrome -- separately re-checking lq1's other
|
|
1470
|
+
# replicas in their own patches doesn't add new
|
|
1471
|
+
# independent information, it just adds their
|
|
1472
|
+
# own extra gate exposure for no additional
|
|
1473
|
+
# benefit. So: XOR b1's value into ITS OWN
|
|
1474
|
+
# patch's ancilla immediately before the gate,
|
|
1475
|
+
# XOR it in again immediately after, force_m that
|
|
1476
|
+
# one ancilla -- b1 only, not every replica of
|
|
1477
|
+
# lq1.
|
|
1495
1478
|
#
|
|
1496
1479
|
# Also worth being explicit about: what this
|
|
1497
1480
|
# catches is NOT the same thing as the `noise=`
|
|
@@ -1505,17 +1488,46 @@ class QrackAceBackend:
|
|
|
1505
1488
|
# sandwiching CNOTs are then subject to that same
|
|
1506
1489
|
# injected noise too) -- see conversation record.
|
|
1507
1490
|
#
|
|
1508
|
-
# Scope:
|
|
1509
|
-
# (_cpauli / _apply_coupling)
|
|
1510
|
-
#
|
|
1511
|
-
#
|
|
1512
|
-
#
|
|
1513
|
-
#
|
|
1491
|
+
# Scope: still only the mcx/mcy/mcz path
|
|
1492
|
+
# (_cpauli / _apply_coupling); swap/iswap/etc.
|
|
1493
|
+
# get their own dedicated gadget (_detect_swap),
|
|
1494
|
+
# and the anti-controlled shadow variants get
|
|
1495
|
+
# theirs (_anti_shadow_wrap) -- see those.
|
|
1496
|
+
#
|
|
1497
|
+
# CZ specifically also checks b2, not just b1:
|
|
1498
|
+
# unlike CX/CY, where the target's Z-population
|
|
1499
|
+
# legitimately, intentionally changes (that IS
|
|
1500
|
+
# the entangling operation -- not an error), CZ
|
|
1501
|
+
# is diagonal in the computational basis and
|
|
1502
|
+
# NEVER changes either qubit's Z-population, only
|
|
1503
|
+
# a relative phase. So b2 is an equally valid
|
|
1504
|
+
# invariance check here, for this gate family
|
|
1505
|
+
# only. Combined as one XOR parity (b1^b2), same
|
|
1506
|
+
# pattern as the SWAP gadget: catches either
|
|
1507
|
+
# participant's first-order (O(p)) disturbance,
|
|
1508
|
+
# only misses the second-order (O(p^2)) case
|
|
1509
|
+
# where both are disturbed simultaneously in a
|
|
1510
|
+
# way that cancels in the combined parity.
|
|
1511
|
+
# (Considered and rejected checking b1 in BOTH
|
|
1512
|
+
# Z and X bases instead, to catch phase-type
|
|
1513
|
+
# errors on the control too -- doesn't work: CX/CY
|
|
1514
|
+
# genuinely, intentionally entangle control with
|
|
1515
|
+
# target, which legitimately degrades the
|
|
1516
|
+
# control's own X/Y-basis coherence as correct
|
|
1517
|
+
# gate behavior, not error. A detector for that
|
|
1518
|
+
# would flag every successful entangling gate and
|
|
1519
|
+
# destroy the entanglement the gate was supposed
|
|
1520
|
+
# to create.)
|
|
1521
|
+
check_b2_too = pauli == Pauli.PauliZ
|
|
1514
1522
|
anc = self._detect_ancilla[b1[0]]
|
|
1515
1523
|
sim = self.sim[b1[0]]
|
|
1516
1524
|
sim.mcx([b1[1]], anc)
|
|
1525
|
+
if check_b2_too:
|
|
1526
|
+
sim.mcx([b2[1]], anc)
|
|
1517
1527
|
gate_fn([b1[1]], b2[1])
|
|
1518
1528
|
sim.mcx([b1[1]], anc)
|
|
1529
|
+
if check_b2_too:
|
|
1530
|
+
sim.mcx([b2[1]], anc)
|
|
1519
1531
|
sim.force_m(anc, False)
|
|
1520
1532
|
else:
|
|
1521
1533
|
gate_fn([b1[1]], b2[1])
|
|
@@ -2431,11 +2443,23 @@ class QrackAceBackend:
|
|
|
2431
2443
|
# passing a smaller x: x scales every pair uniformly, and this
|
|
2432
2444
|
# doesn't apply uniformly, either across qubits (only ones with a
|
|
2433
2445
|
# real-gate opportunity qualify) or across gate types (see below).
|
|
2446
|
+
#
|
|
2447
|
+
# Both sides of a real (u=0) pair get added, not just the control:
|
|
2448
|
+
# CZ's own gadget check now covers its target too (CZ is diagonal
|
|
2449
|
+
# -- unlike CX/CY, it never changes either qubit's Z-population,
|
|
2450
|
+
# so the target is an equally valid invariance check there, see
|
|
2451
|
+
# _apply_coupling). The coupling map doesn't distinguish which
|
|
2452
|
+
# gate type a future circuit will actually use for a given pair,
|
|
2453
|
+
# so this necessarily overstates the CX/CY case slightly (where
|
|
2454
|
+
# only the control gets swept) -- an approximation on top of an
|
|
2455
|
+
# already-approximate placeholder, not a new source of precision
|
|
2456
|
+
# lost.
|
|
2434
2457
|
has_real_partner = set()
|
|
2435
2458
|
if self.is_error_detection:
|
|
2436
2459
|
for lq1, lq2 in coupling_map:
|
|
2437
2460
|
if _uncommon_sim_fraction(lq1, lq2) == 0:
|
|
2438
2461
|
has_real_partner.add(lq1)
|
|
2462
|
+
has_real_partner.add(lq2)
|
|
2439
2463
|
|
|
2440
2464
|
# This factor is a theory-derived placeholder, not an empirical
|
|
2441
2465
|
# fit -- deliberately, per instruction not to chase a regression
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|