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.
Files changed (30) hide show
  1. {pyqrack_cpu_complex128-2.1.1/pyqrack_cpu_complex128.egg-info → pyqrack_cpu_complex128-2.1.2}/PKG-INFO +1 -1
  2. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_ace_backend.py +76 -22
  3. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2/pyqrack_cpu_complex128.egg-info}/PKG-INFO +1 -1
  4. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/setup.py +1 -1
  5. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/LICENSE +0 -0
  6. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/MANIFEST.in +0 -0
  7. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/Makefile +0 -0
  8. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/README.md +0 -0
  9. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyproject.toml +0 -0
  10. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/__init__.py +0 -0
  11. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/neuron_activation_fn.py +0 -0
  12. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/pauli.py +0 -0
  13. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_circuit.py +0 -0
  14. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
  15. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_neuron.py +0 -0
  16. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_neuron_torch_layer.py +0 -0
  17. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_simulator.py +0 -0
  18. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_stabilizer.py +0 -0
  19. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_system/__init__.py +0 -0
  20. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/qrack_system/qrack_system.py +0 -0
  21. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/quimb_circuit_type.py +0 -0
  22. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/__init__.py +0 -0
  23. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/load_quantized_data.py +0 -0
  24. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack/stats/quantize_by_range.py +0 -0
  25. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/SOURCES.txt +0 -0
  26. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/dependency_links.txt +0 -0
  27. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/not-zip-safe +0 -0
  28. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/requires.txt +0 -0
  29. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/pyqrack_cpu_complex128.egg-info/top_level.txt +0 -0
  30. {pyqrack_cpu_complex128-2.1.1 → pyqrack_cpu_complex128-2.1.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqrack-cpu-complex128
3
- Version: 2.1.1
3
+ Version: 2.1.2
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -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.25, y=0.25):
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, col_b = a % self._row_length, b % self._row_length
1485
- row_a, row_b = a // self._row_length, b // self._row_length
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 # No noise on long-to-long
1491
-
1492
- if (col_a == col_b) or (row_a == row_b):
1493
- continue # No noise for same column
1494
-
1495
- if is_long_a or is_long_b:
1496
- y_cy = 1 - (1 - y) ** 2
1497
- y_swap = 1 - (1 - y) ** 3
1498
- noise_model.add_quantum_error(depolarizing_error(y, 2), "cx", [a, b])
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqrack-cpu-complex128
3
- Version: 2.1.1
3
+ Version: 2.1.2
4
4
  Summary: pyqrack - Pure Python vm6502q/qrack Wrapper
5
5
  Home-page: https://github.com/vm6502q/pyqrack
6
6
  Author: Daniel Strano
@@ -7,7 +7,7 @@ from setuptools import setup
7
7
  from setuptools.command.build_py import build_py
8
8
 
9
9
 
10
- VERSION = "2.1.1"
10
+ VERSION = "2.1.2"
11
11
 
12
12
  # Read long description from README.
13
13
  README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'README.md')