pyqrack-cpu-complex128 2.1.1__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_cpu_complex128-2.1.1/pyqrack_cpu_complex128.egg-info → pyqrack_cpu_complex128-2.1.2}/PKG-INFO +1 -1
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_ace_backend.py +76 -22
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2/pyqrack_cpu_complex128.egg-info}/PKG-INFO +1 -1
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/setup.py +1 -1
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/LICENSE +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/MANIFEST.in +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/Makefile +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/README.md +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyproject.toml +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/__init__.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/pauli.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/SOURCES.txt +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/dependency_links.txt +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/not-zip-safe +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/requires.txt +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/top_level.txt +0 -0
- {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/setup.cfg +0 -0
|
@@ -334,6 +334,50 @@ class QrackAceBackend:
|
|
|
334
334
|
def clone(self):
|
|
335
335
|
return QrackAceBackend(to_clone=self)
|
|
336
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
|
+
|
|
337
381
|
def num_qubits(self):
|
|
338
382
|
return self._row_length * self._col_length
|
|
339
383
|
|
|
@@ -1473,38 +1517,48 @@ class QrackAceBackend:
|
|
|
1473
1517
|
return self._coupling_map
|
|
1474
1518
|
|
|
1475
1519
|
# Designed by Dan, and implemented by Elara:
|
|
1476
|
-
def create_noise_model(self, x=0.
|
|
1520
|
+
def create_noise_model(self, x=0.125, y=0.25):
|
|
1477
1521
|
if not _IS_QISKIT_AER_AVAILABLE:
|
|
1478
1522
|
raise RuntimeError(
|
|
1479
1523
|
"Before trying to run_qiskit_circuit() with QrackAceBackend, you must install Qiskit Aer!"
|
|
1480
1524
|
)
|
|
1481
1525
|
noise_model = NoiseModel()
|
|
1482
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
|
|
1483
1547
|
for a, b in self.get_logical_coupling_map():
|
|
1484
|
-
col_a
|
|
1485
|
-
|
|
1548
|
+
col_a = a % self._row_length
|
|
1549
|
+
col_b = b % self._row_length
|
|
1486
1550
|
is_long_a = self._is_col_long_range[col_a]
|
|
1487
1551
|
is_long_b = self._is_col_long_range[col_b]
|
|
1488
1552
|
|
|
1489
1553
|
if is_long_a and is_long_b:
|
|
1490
|
-
continue
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
noise_model.add_quantum_error(depolarizing_error(
|
|
1499
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1500
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1501
|
-
noise_model.add_quantum_error(depolarizing_error(y_swap, 2), "swap", [a, b])
|
|
1502
|
-
else:
|
|
1503
|
-
y_cy = 1 - (1 - y) ** 2
|
|
1504
|
-
y_swap = 1 - (1 - y) ** 3
|
|
1505
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cx", [a, b])
|
|
1506
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cy", [a, b])
|
|
1507
|
-
noise_model.add_quantum_error(depolarizing_error(y_cy, 2), "cz", [a, b])
|
|
1508
|
-
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])
|
|
1509
1563
|
|
|
1510
1564
|
return noise_model
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/neuron_activation_fn.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_neuron_torch_layer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_system/__init__.py
RENAMED
|
File without changes
|
{pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_system/qrack_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/load_quantized_data.py
RENAMED
|
File without changes
|
{pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/quantize_by_range.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|