pyqrack-complex128 2.1.1__tar.gz → 2.2.0__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.1.1 → pyqrack_complex128-2.2.0}/Makefile +1 -1
- {pyqrack_complex128-2.1.1/pyqrack_complex128.egg-info → pyqrack_complex128-2.2.0}/PKG-INFO +1 -1
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_ace_backend.py +76 -22
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_simulator.py +19 -6
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_system/qrack_system.py +2 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0/pyqrack_complex128.egg-info}/PKG-INFO +1 -1
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/setup.py +1 -1
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/LICENSE +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/MANIFEST.in +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/README.md +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyproject.toml +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/__init__.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/pauli.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/SOURCES.txt +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/dependency_links.txt +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/not-zip-safe +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/requires.txt +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/top_level.txt +0 -0
- {pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/setup.cfg +0 -0
|
@@ -30,7 +30,7 @@ build-deps:
|
|
|
30
30
|
rm -rf pyqrack/qrack_system/qrack_cl_precompile
|
|
31
31
|
ifneq ($(OS),Windows_NT)
|
|
32
32
|
ifeq ($(QRACK_PRESENT),)
|
|
33
|
-
git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout
|
|
33
|
+
git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout 4d603e03c8f8dc7ee60e0438042b53a1343443be; cd ..
|
|
34
34
|
endif
|
|
35
35
|
mkdir -p qrack/build
|
|
36
36
|
ifeq ($(UNAME_S),Linux)
|
|
@@ -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
|
|
@@ -554,8 +554,8 @@ class QrackSimulator:
|
|
|
554
554
|
Qrack.qrack_lib.MCAdjT(self.sid, len(c), QrackSimulator._ulonglong_byref(c), q)
|
|
555
555
|
self._throw_if_error()
|
|
556
556
|
|
|
557
|
-
def mcu(self, c, q, th, ph, la):
|
|
558
|
-
"""Multi-controlled
|
|
557
|
+
def mcu(self, c, q, th, ph, la, gm=0.0):
|
|
558
|
+
"""Multi-controlled arbitrary unitary
|
|
559
559
|
|
|
560
560
|
If all controlled qubits are `|1>` then the unitary gate described by
|
|
561
561
|
parameters is applied to the target qubit.
|
|
@@ -566,6 +566,7 @@ class QrackSimulator:
|
|
|
566
566
|
th: theta
|
|
567
567
|
ph: phi
|
|
568
568
|
la: lambda
|
|
569
|
+
gm: gamma
|
|
569
570
|
|
|
570
571
|
Raises:
|
|
571
572
|
RuntimeError: QrackSimulator raised an exception.
|
|
@@ -578,6 +579,7 @@ class QrackSimulator:
|
|
|
578
579
|
ctypes.c_double(th),
|
|
579
580
|
ctypes.c_double(ph),
|
|
580
581
|
ctypes.c_double(la),
|
|
582
|
+
ctypes.c_double(gm),
|
|
581
583
|
)
|
|
582
584
|
self._throw_if_error()
|
|
583
585
|
|
|
@@ -736,8 +738,8 @@ class QrackSimulator:
|
|
|
736
738
|
Qrack.qrack_lib.MACAdjT(self.sid, len(c), QrackSimulator._ulonglong_byref(c), q)
|
|
737
739
|
self._throw_if_error()
|
|
738
740
|
|
|
739
|
-
def macu(self, c, q, th, ph, la):
|
|
740
|
-
"""Anti multi-controlled
|
|
741
|
+
def macu(self, c, q, th, ph, la, gm=0.0):
|
|
742
|
+
"""Anti multi-controlled arbitrary unitary
|
|
741
743
|
|
|
742
744
|
If all controlled qubits are `|0>` then the unitary gate described by
|
|
743
745
|
parameters is applied to the target qubit.
|
|
@@ -748,6 +750,7 @@ class QrackSimulator:
|
|
|
748
750
|
th: theta
|
|
749
751
|
ph: phi
|
|
750
752
|
la: lambda
|
|
753
|
+
gm: gamma
|
|
751
754
|
|
|
752
755
|
Raises:
|
|
753
756
|
RuntimeError: QrackSimulator raised an exception.
|
|
@@ -760,11 +763,12 @@ class QrackSimulator:
|
|
|
760
763
|
ctypes.c_double(th),
|
|
761
764
|
ctypes.c_double(ph),
|
|
762
765
|
ctypes.c_double(la),
|
|
766
|
+
ctypes.c_double(gm),
|
|
763
767
|
)
|
|
764
768
|
self._throw_if_error()
|
|
765
769
|
|
|
766
770
|
def macmtrx(self, c, m, q):
|
|
767
|
-
"""Anti multi-controlled
|
|
771
|
+
"""Anti multi-controlled arbitrary operator
|
|
768
772
|
|
|
769
773
|
If all controlled qubits are `|0>` then the arbitrary operation by
|
|
770
774
|
parameters is applied to the target qubit.
|
|
@@ -4194,7 +4198,7 @@ class QrackSimulator:
|
|
|
4194
4198
|
float(operation.params[0]),
|
|
4195
4199
|
float(operation.params[1]),
|
|
4196
4200
|
)
|
|
4197
|
-
elif
|
|
4201
|
+
elif name == "cu3":
|
|
4198
4202
|
self._sim.mcu(
|
|
4199
4203
|
[q._index for q in operation.qubits[0:1]],
|
|
4200
4204
|
operation.qubits[1]._index,
|
|
@@ -4202,6 +4206,15 @@ class QrackSimulator:
|
|
|
4202
4206
|
float(operation.params[1]),
|
|
4203
4207
|
float(operation.params[2]),
|
|
4204
4208
|
)
|
|
4209
|
+
elif name == "cu":
|
|
4210
|
+
self._sim.mcu(
|
|
4211
|
+
[q._index for q in operation.qubits[0:1]],
|
|
4212
|
+
operation.qubits[1]._index,
|
|
4213
|
+
float(operation.params[0]),
|
|
4214
|
+
float(operation.params[1]),
|
|
4215
|
+
float(operation.params[2]),
|
|
4216
|
+
float(operation.params[3]),
|
|
4217
|
+
)
|
|
4205
4218
|
elif name == "cx":
|
|
4206
4219
|
self._sim.mcx([q._index for q in operation.qubits[0:1]], operation.qubits[1]._index)
|
|
4207
4220
|
elif name == "cy":
|
|
@@ -629,6 +629,7 @@ class QrackSystem:
|
|
|
629
629
|
c_double,
|
|
630
630
|
c_double,
|
|
631
631
|
c_double,
|
|
632
|
+
c_double,
|
|
632
633
|
]
|
|
633
634
|
|
|
634
635
|
self.qrack_lib.MCMtrx.restype = None
|
|
@@ -715,6 +716,7 @@ class QrackSystem:
|
|
|
715
716
|
c_double,
|
|
716
717
|
c_double,
|
|
717
718
|
c_double,
|
|
719
|
+
c_double,
|
|
718
720
|
]
|
|
719
721
|
|
|
720
722
|
self.qrack_lib.MACMtrx.restype = None
|
|
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.1.1 → pyqrack_complex128-2.2.0}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/requires.txt
RENAMED
|
File without changes
|
{pyqrack_complex128-2.1.1 → pyqrack_complex128-2.2.0}/pyqrack_complex128.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|