pyqrack 1.29.0__py3-none-win_amd64.whl → 1.72.5__py3-none-win_amd64.whl
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/__init__.py +13 -6
- pyqrack/neuron_activation_fn.py +2 -2
- pyqrack/pauli.py +1 -1
- pyqrack/qrack_ace_backend.py +1544 -0
- pyqrack/qrack_circuit.py +212 -100
- pyqrack/qrack_neuron.py +27 -9
- pyqrack/qrack_neuron_torch_layer.py +170 -0
- pyqrack/qrack_simulator.py +870 -310
- pyqrack/qrack_stabilizer.py +58 -0
- pyqrack/qrack_system/qrack_cl_precompile/qrack_cl_precompile.exe +0 -0
- pyqrack/qrack_system/qrack_lib/qrack_pinvoke.dll +0 -0
- pyqrack/qrack_system/qrack_system.py +228 -135
- pyqrack/quimb_circuit_type.py +1 -1
- pyqrack/stats/__init__.py +6 -0
- pyqrack/stats/load_quantized_data.py +35 -0
- pyqrack/stats/quantize_by_range.py +56 -0
- {pyqrack-1.29.0.dist-info → pyqrack-1.72.5.dist-info}/LICENSE +1 -1
- pyqrack-1.72.5.dist-info/METADATA +82 -0
- pyqrack-1.72.5.dist-info/RECORD +22 -0
- {pyqrack-1.29.0.dist-info → pyqrack-1.72.5.dist-info}/WHEEL +1 -1
- pyqrack/util/__init__.py +0 -8
- pyqrack/util/convert_qiskit_circuit_to_qasm_experiment.py +0 -61
- pyqrack-1.29.0.dist-info/METADATA +0 -61
- pyqrack-1.29.0.dist-info/RECORD +0 -17
- {pyqrack-1.29.0.dist-info → pyqrack-1.72.5.dist-info}/top_level.txt +0 -0
pyqrack/qrack_simulator.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# (C) Daniel Strano and the Qrack contributors 2017-
|
|
1
|
+
# (C) Daniel Strano and the Qrack contributors 2017-2025. All rights reserved.
|
|
2
2
|
#
|
|
3
3
|
# Use of this source code is governed by an MIT-style license that can be
|
|
4
4
|
# found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
@@ -6,21 +6,24 @@
|
|
|
6
6
|
import copy
|
|
7
7
|
import ctypes
|
|
8
8
|
import math
|
|
9
|
+
import os
|
|
9
10
|
import re
|
|
10
11
|
from .qrack_system import Qrack
|
|
11
12
|
from .pauli import Pauli
|
|
12
13
|
|
|
13
14
|
_IS_QISKIT_AVAILABLE = True
|
|
14
15
|
try:
|
|
15
|
-
from qiskit.circuit import QuantumRegister, Qubit
|
|
16
16
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
|
17
17
|
from qiskit.compiler import transpile
|
|
18
|
-
from qiskit.qobj.qasm_qobj import QasmQobjExperiment
|
|
19
18
|
from qiskit.quantum_info.operators.symplectic.clifford import Clifford
|
|
20
|
-
from .util import convert_qiskit_circuit_to_qasm_experiment
|
|
21
19
|
except ImportError:
|
|
22
20
|
_IS_QISKIT_AVAILABLE = False
|
|
23
21
|
|
|
22
|
+
try:
|
|
23
|
+
from qiskit import qasm3
|
|
24
|
+
except ImportError:
|
|
25
|
+
pass
|
|
26
|
+
|
|
24
27
|
_IS_NUMPY_AVAILABLE = True
|
|
25
28
|
try:
|
|
26
29
|
import numpy as np
|
|
@@ -29,10 +32,9 @@ except:
|
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
class QrackSimulator:
|
|
32
|
-
"""Interface for all the
|
|
35
|
+
"""Interface for all the Qrack functionality.
|
|
33
36
|
|
|
34
37
|
Attributes:
|
|
35
|
-
qubitCount(int): Number of qubits that are to be simulated.
|
|
36
38
|
sid(int): Corresponding simulator id.
|
|
37
39
|
"""
|
|
38
40
|
|
|
@@ -48,14 +50,18 @@ class QrackSimulator:
|
|
|
48
50
|
qubitCount=-1,
|
|
49
51
|
cloneSid=-1,
|
|
50
52
|
isTensorNetwork=True,
|
|
51
|
-
isSchmidtDecomposeMulti=
|
|
53
|
+
isSchmidtDecomposeMulti=False,
|
|
52
54
|
isSchmidtDecompose=True,
|
|
53
|
-
isStabilizerHybrid=
|
|
55
|
+
isStabilizerHybrid=False,
|
|
54
56
|
isBinaryDecisionTree=False,
|
|
55
57
|
isPaged=True,
|
|
56
58
|
isCpuGpuHybrid=True,
|
|
57
59
|
isOpenCL=True,
|
|
58
|
-
isHostPointer=
|
|
60
|
+
isHostPointer=(
|
|
61
|
+
True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False
|
|
62
|
+
),
|
|
63
|
+
isSparse=False,
|
|
64
|
+
noise=0,
|
|
59
65
|
pyzxCircuit=None,
|
|
60
66
|
qiskitCircuit=None,
|
|
61
67
|
):
|
|
@@ -74,6 +80,7 @@ class QrackSimulator:
|
|
|
74
80
|
)
|
|
75
81
|
|
|
76
82
|
self.is_tensor_network = isTensorNetwork
|
|
83
|
+
self.is_pure_stabilizer = False
|
|
77
84
|
|
|
78
85
|
if cloneSid > -1:
|
|
79
86
|
self.sid = Qrack.qrack_lib.init_clone(cloneSid)
|
|
@@ -89,14 +96,18 @@ class QrackSimulator:
|
|
|
89
96
|
isStabilizerHybrid,
|
|
90
97
|
isBinaryDecisionTree,
|
|
91
98
|
isPaged,
|
|
92
|
-
|
|
99
|
+
(noise > 0),
|
|
93
100
|
isCpuGpuHybrid,
|
|
94
101
|
isOpenCL,
|
|
95
102
|
isHostPointer,
|
|
103
|
+
isSparse
|
|
96
104
|
)
|
|
97
105
|
|
|
98
106
|
self._throw_if_error()
|
|
99
107
|
|
|
108
|
+
if noise > 0:
|
|
109
|
+
self.set_noise_parameter(noise)
|
|
110
|
+
|
|
100
111
|
if pyzxCircuit is not None:
|
|
101
112
|
self.run_pyzx_gates(pyzxCircuit.gates)
|
|
102
113
|
elif qiskitCircuit is not None:
|
|
@@ -113,6 +124,9 @@ class QrackSimulator:
|
|
|
113
124
|
def _ulonglong_byref(self, a):
|
|
114
125
|
return (ctypes.c_ulonglong * len(a))(*a)
|
|
115
126
|
|
|
127
|
+
def _longlong_byref(self, a):
|
|
128
|
+
return (ctypes.c_longlong * len(a))(*a)
|
|
129
|
+
|
|
116
130
|
def _double_byref(self, a):
|
|
117
131
|
return (ctypes.c_double * len(a))(*a)
|
|
118
132
|
|
|
@@ -172,9 +186,23 @@ class QrackSimulator:
|
|
|
172
186
|
self._throw_if_error()
|
|
173
187
|
|
|
174
188
|
def set_concurrency(self, p):
|
|
189
|
+
"""Set the CPU parallel thread count"""
|
|
175
190
|
Qrack.qrack_lib.set_concurrency(self.sid, p)
|
|
176
191
|
self._throw_if_error()
|
|
177
192
|
|
|
193
|
+
def set_device(self, d):
|
|
194
|
+
"""Set the GPU device ID"""
|
|
195
|
+
Qrack.qrack_lib.set_device(self.sid, d)
|
|
196
|
+
self._throw_if_error()
|
|
197
|
+
|
|
198
|
+
def set_device_list(self, d):
|
|
199
|
+
"""Set the GPU device ID"""
|
|
200
|
+
Qrack.qrack_lib.set_device_list(self.sid, len(d), self._longlong_byref(d))
|
|
201
|
+
self._throw_if_error()
|
|
202
|
+
|
|
203
|
+
def clone(self):
|
|
204
|
+
return QrackSimulator(cloneSid=self.sid)
|
|
205
|
+
|
|
178
206
|
# standard gates
|
|
179
207
|
|
|
180
208
|
## single-qubits gates
|
|
@@ -330,7 +358,9 @@ class QrackSimulator:
|
|
|
330
358
|
RuntimeError: QrackSimulator raised an exception.
|
|
331
359
|
"""
|
|
332
360
|
if len(m) < 4:
|
|
333
|
-
raise ValueError(
|
|
361
|
+
raise ValueError(
|
|
362
|
+
"2x2 matrix 'm' in QrackSimulator.mtrx() must contain at least 4 elements."
|
|
363
|
+
)
|
|
334
364
|
Qrack.qrack_lib.Mtrx(self.sid, self._complex_byref(m), q)
|
|
335
365
|
self._throw_if_error()
|
|
336
366
|
|
|
@@ -548,7 +578,9 @@ class QrackSimulator:
|
|
|
548
578
|
RuntimeError: QrackSimulator raised an exception.
|
|
549
579
|
"""
|
|
550
580
|
if len(m) < 4:
|
|
551
|
-
raise ValueError(
|
|
581
|
+
raise ValueError(
|
|
582
|
+
"2x2 matrix 'm' in QrackSimulator.mcmtrx() must contain at least 4 elements."
|
|
583
|
+
)
|
|
552
584
|
Qrack.qrack_lib.MCMtrx(
|
|
553
585
|
self.sid, len(c), self._ulonglong_byref(c), self._complex_byref(m), q
|
|
554
586
|
)
|
|
@@ -724,7 +756,9 @@ class QrackSimulator:
|
|
|
724
756
|
RuntimeError: QrackSimulator raised an exception.
|
|
725
757
|
"""
|
|
726
758
|
if len(m) < 4:
|
|
727
|
-
raise ValueError(
|
|
759
|
+
raise ValueError(
|
|
760
|
+
"2x2 matrix 'm' in QrackSimulator.macmtrx() must contain at least 4 elements."
|
|
761
|
+
)
|
|
728
762
|
Qrack.qrack_lib.MACMtrx(
|
|
729
763
|
self.sid, len(c), self._ulonglong_byref(c), self._complex_byref(m), q
|
|
730
764
|
)
|
|
@@ -747,7 +781,9 @@ class QrackSimulator:
|
|
|
747
781
|
RuntimeError: QrackSimulator raised an exception.
|
|
748
782
|
"""
|
|
749
783
|
if len(m) < 4:
|
|
750
|
-
raise ValueError(
|
|
784
|
+
raise ValueError(
|
|
785
|
+
"2x2 matrix 'm' in QrackSimulator.ucmtrx() must contain at least 4 elements."
|
|
786
|
+
)
|
|
751
787
|
Qrack.qrack_lib.UCMtrx(
|
|
752
788
|
self.sid, len(c), self._ulonglong_byref(c), self._complex_byref(m), q, p
|
|
753
789
|
)
|
|
@@ -769,7 +805,9 @@ class QrackSimulator:
|
|
|
769
805
|
RuntimeError: QrackSimulator raised an exception.
|
|
770
806
|
"""
|
|
771
807
|
if len(m) < ((1 << len(c)) * 4):
|
|
772
|
-
raise ValueError(
|
|
808
|
+
raise ValueError(
|
|
809
|
+
"Multiplex matrix 'm' in QrackSimulator.multiplex1_mtrx() must contain at least (4 * 2 ** len(c)) elements."
|
|
810
|
+
)
|
|
773
811
|
Qrack.qrack_lib.Multiplex1Mtrx(
|
|
774
812
|
self.sid, len(c), self._ulonglong_byref(c), q, self._complex_byref(m)
|
|
775
813
|
)
|
|
@@ -1017,9 +1055,16 @@ class QrackSimulator:
|
|
|
1017
1055
|
Returns:
|
|
1018
1056
|
Measurement result of all qubits.
|
|
1019
1057
|
"""
|
|
1020
|
-
|
|
1058
|
+
num_q = self.num_qubits()
|
|
1059
|
+
num_words = (num_q + 63) // 64
|
|
1060
|
+
_r = (ctypes.c_ulonglong * num_words)()
|
|
1061
|
+
Qrack.qrack_lib.MAllLong(self.sid, _r)
|
|
1021
1062
|
self._throw_if_error()
|
|
1022
|
-
|
|
1063
|
+
r = 0
|
|
1064
|
+
for w in range(num_words):
|
|
1065
|
+
r <<= 64
|
|
1066
|
+
r |= _r[w]
|
|
1067
|
+
return r
|
|
1023
1068
|
|
|
1024
1069
|
def measure_pauli(self, b, q):
|
|
1025
1070
|
"""Pauli Measurement gate
|
|
@@ -1239,7 +1284,13 @@ class QrackSimulator:
|
|
|
1239
1284
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot mul()! (Turn off just this option, in the constructor.)
|
|
1240
1285
|
"""
|
|
1241
1286
|
if self.is_tensor_network:
|
|
1242
|
-
raise RuntimeError(
|
|
1287
|
+
raise RuntimeError(
|
|
1288
|
+
"QrackSimulator with isTensorNetwork=True option cannot mul()! (Turn off just this option, in the constructor.)"
|
|
1289
|
+
)
|
|
1290
|
+
if self.is_pure_stabilizer:
|
|
1291
|
+
raise RuntimeError(
|
|
1292
|
+
"QrackStabilizer cannot mul()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1293
|
+
)
|
|
1243
1294
|
|
|
1244
1295
|
if len(q) != len(o):
|
|
1245
1296
|
raise RuntimeError("Lengths of list parameters are mismatched.")
|
|
@@ -1272,7 +1323,13 @@ class QrackSimulator:
|
|
|
1272
1323
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot div()! (Turn off just this option, in the constructor.)
|
|
1273
1324
|
"""
|
|
1274
1325
|
if self.is_tensor_network:
|
|
1275
|
-
raise RuntimeError(
|
|
1326
|
+
raise RuntimeError(
|
|
1327
|
+
"QrackSimulator with isTensorNetwork=True option cannot div()! (Turn off just this option, in the constructor.)"
|
|
1328
|
+
)
|
|
1329
|
+
if self.is_pure_stabilizer:
|
|
1330
|
+
raise RuntimeError(
|
|
1331
|
+
"QrackStabilizer cannot div()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1332
|
+
)
|
|
1276
1333
|
|
|
1277
1334
|
if len(q) != len(o):
|
|
1278
1335
|
raise RuntimeError("Lengths of list parameters are mismatched.")
|
|
@@ -1363,7 +1420,13 @@ class QrackSimulator:
|
|
|
1363
1420
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot pown()! (Turn off just this option, in the constructor.)
|
|
1364
1421
|
"""
|
|
1365
1422
|
if self.is_tensor_network:
|
|
1366
|
-
raise RuntimeError(
|
|
1423
|
+
raise RuntimeError(
|
|
1424
|
+
"QrackSimulator with isTensorNetwork=True option cannot pown()! (Turn off just this option, in the constructor.)"
|
|
1425
|
+
)
|
|
1426
|
+
if self.is_pure_stabilizer:
|
|
1427
|
+
raise RuntimeError(
|
|
1428
|
+
"QrackStabilizer cannot pown()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1429
|
+
)
|
|
1367
1430
|
|
|
1368
1431
|
if len(q) != len(o):
|
|
1369
1432
|
raise RuntimeError("Lengths of list parameters are mismatched.")
|
|
@@ -1450,7 +1513,13 @@ class QrackSimulator:
|
|
|
1450
1513
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot mcmul()! (Turn off just this option, in the constructor.)
|
|
1451
1514
|
"""
|
|
1452
1515
|
if self.is_tensor_network:
|
|
1453
|
-
raise RuntimeError(
|
|
1516
|
+
raise RuntimeError(
|
|
1517
|
+
"QrackSimulator with isTensorNetwork=True option cannot mcmul()! (Turn off just this option, in the constructor.)"
|
|
1518
|
+
)
|
|
1519
|
+
if self.is_pure_stabilizer:
|
|
1520
|
+
raise RuntimeError(
|
|
1521
|
+
"QrackStabilizer cannot mcmul()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1522
|
+
)
|
|
1454
1523
|
|
|
1455
1524
|
if len(q) != len(o):
|
|
1456
1525
|
raise RuntimeError("Lengths of list parameters are mismatched.")
|
|
@@ -1486,7 +1555,13 @@ class QrackSimulator:
|
|
|
1486
1555
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot mcdiv()! (Turn off just this option, in the constructor.)
|
|
1487
1556
|
"""
|
|
1488
1557
|
if self.is_tensor_network:
|
|
1489
|
-
raise RuntimeError(
|
|
1558
|
+
raise RuntimeError(
|
|
1559
|
+
"QrackSimulator with isTensorNetwork=True option cannot mcdiv()! (Turn off just this option, in the constructor.)"
|
|
1560
|
+
)
|
|
1561
|
+
if self.is_pure_stabilizer:
|
|
1562
|
+
raise RuntimeError(
|
|
1563
|
+
"QrackStabilizer cannot mcdiv()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1564
|
+
)
|
|
1490
1565
|
|
|
1491
1566
|
if len(q) != len(o):
|
|
1492
1567
|
raise RuntimeError("Lengths of list parameters are mismatched.")
|
|
@@ -1588,7 +1663,13 @@ class QrackSimulator:
|
|
|
1588
1663
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot mcpown()! (Turn off just this option, in the constructor.)
|
|
1589
1664
|
"""
|
|
1590
1665
|
if self.is_tensor_network:
|
|
1591
|
-
raise RuntimeError(
|
|
1666
|
+
raise RuntimeError(
|
|
1667
|
+
"QrackSimulator with isTensorNetwork=True option cannot mcpown()! (Turn off just this option, in the constructor.)"
|
|
1668
|
+
)
|
|
1669
|
+
if self.is_pure_stabilizer:
|
|
1670
|
+
raise RuntimeError(
|
|
1671
|
+
"QrackStabilizer cannot mcpown()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1672
|
+
)
|
|
1592
1673
|
|
|
1593
1674
|
if len(q) != len(o):
|
|
1594
1675
|
raise RuntimeError("Lengths of list parameters are mismatched.")
|
|
@@ -1623,7 +1704,13 @@ class QrackSimulator:
|
|
|
1623
1704
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot lda()! (Turn off just this option, in the constructor.)
|
|
1624
1705
|
"""
|
|
1625
1706
|
if self.is_tensor_network:
|
|
1626
|
-
raise RuntimeError(
|
|
1707
|
+
raise RuntimeError(
|
|
1708
|
+
"QrackSimulator with isTensorNetwork=True option cannot lda()! (Turn off just this option, in the constructor.)"
|
|
1709
|
+
)
|
|
1710
|
+
if self.is_pure_stabilizer:
|
|
1711
|
+
raise RuntimeError(
|
|
1712
|
+
"QrackStabilizer cannot lda()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1713
|
+
)
|
|
1627
1714
|
|
|
1628
1715
|
Qrack.qrack_lib.LDA(
|
|
1629
1716
|
self.sid,
|
|
@@ -1651,7 +1738,13 @@ class QrackSimulator:
|
|
|
1651
1738
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot adc()! (Turn off just this option, in the constructor.)
|
|
1652
1739
|
"""
|
|
1653
1740
|
if self.is_tensor_network:
|
|
1654
|
-
raise RuntimeError(
|
|
1741
|
+
raise RuntimeError(
|
|
1742
|
+
"QrackSimulator with isTensorNetwork=True option cannot adc()! (Turn off just this option, in the constructor.)"
|
|
1743
|
+
)
|
|
1744
|
+
if self.is_pure_stabilizer:
|
|
1745
|
+
raise RuntimeError(
|
|
1746
|
+
"QrackStabilizer cannot adc()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1747
|
+
)
|
|
1655
1748
|
|
|
1656
1749
|
Qrack.qrack_lib.ADC(
|
|
1657
1750
|
self.sid,
|
|
@@ -1680,7 +1773,13 @@ class QrackSimulator:
|
|
|
1680
1773
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot sbc()! (Turn off just this option, in the constructor.)
|
|
1681
1774
|
"""
|
|
1682
1775
|
if self.is_tensor_network:
|
|
1683
|
-
raise RuntimeError(
|
|
1776
|
+
raise RuntimeError(
|
|
1777
|
+
"QrackSimulator with isTensorNetwork=True option cannot sbc()! (Turn off just this option, in the constructor.)"
|
|
1778
|
+
)
|
|
1779
|
+
if self.is_pure_stabilizer:
|
|
1780
|
+
raise RuntimeError(
|
|
1781
|
+
"QrackStabilizer cannot sbc()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1782
|
+
)
|
|
1684
1783
|
|
|
1685
1784
|
Qrack.qrack_lib.SBC(
|
|
1686
1785
|
self.sid,
|
|
@@ -1710,7 +1809,13 @@ class QrackSimulator:
|
|
|
1710
1809
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot hash()! (Turn off just this option, in the constructor.)
|
|
1711
1810
|
"""
|
|
1712
1811
|
if self.is_tensor_network:
|
|
1713
|
-
raise RuntimeError(
|
|
1812
|
+
raise RuntimeError(
|
|
1813
|
+
"QrackSimulator with isTensorNetwork=True option cannot hash()! (Turn off just this option, in the constructor.)"
|
|
1814
|
+
)
|
|
1815
|
+
if self.is_pure_stabilizer:
|
|
1816
|
+
raise RuntimeError(
|
|
1817
|
+
"QrackStabilizer cannot hash()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
1818
|
+
)
|
|
1714
1819
|
|
|
1715
1820
|
Qrack.qrack_lib.Hash(
|
|
1716
1821
|
self.sid, len(q), self._ulonglong_byref(q), self._to_ubyte(len(q), t)
|
|
@@ -2019,7 +2124,9 @@ class QrackSimulator:
|
|
|
2019
2124
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot compose()! (Turn off just this option, in the constructor.)
|
|
2020
2125
|
"""
|
|
2021
2126
|
if self.is_tensor_network:
|
|
2022
|
-
raise RuntimeError(
|
|
2127
|
+
raise RuntimeError(
|
|
2128
|
+
"QrackSimulator with isTensorNetwork=True option cannot compose()! (Turn off just this option, in the constructor.)"
|
|
2129
|
+
)
|
|
2023
2130
|
|
|
2024
2131
|
Qrack.qrack_lib.Compose(self.sid, other.sid, self._ulonglong_byref(q))
|
|
2025
2132
|
self._throw_if_error()
|
|
@@ -2027,9 +2134,7 @@ class QrackSimulator:
|
|
|
2027
2134
|
def decompose(self, q):
|
|
2028
2135
|
"""Decompose system
|
|
2029
2136
|
|
|
2030
|
-
|
|
2031
|
-
Warning: The qubit subsystem state must be separable, or the behavior
|
|
2032
|
-
of this method is undefined.
|
|
2137
|
+
Factorize a set of contiguous bits with minimal fidelity loss.
|
|
2033
2138
|
|
|
2034
2139
|
Args:
|
|
2035
2140
|
q: qubit id
|
|
@@ -2039,10 +2144,12 @@ class QrackSimulator:
|
|
|
2039
2144
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot decompose()! (Turn off just this option, in the constructor.)
|
|
2040
2145
|
|
|
2041
2146
|
Returns:
|
|
2042
|
-
|
|
2147
|
+
Decomposed subsystem simulator.
|
|
2043
2148
|
"""
|
|
2044
2149
|
if self.is_tensor_network:
|
|
2045
|
-
raise RuntimeError(
|
|
2150
|
+
raise RuntimeError(
|
|
2151
|
+
"QrackSimulator with isTensorNetwork=True option cannot decompose()! (Turn off just this option, in the constructor.)"
|
|
2152
|
+
)
|
|
2046
2153
|
|
|
2047
2154
|
other = QrackSimulator()
|
|
2048
2155
|
Qrack.qrack_lib.destroy(other.sid)
|
|
@@ -2054,10 +2161,8 @@ class QrackSimulator:
|
|
|
2054
2161
|
def dispose(self, q):
|
|
2055
2162
|
"""Dispose qubits
|
|
2056
2163
|
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
Warning: The qubit subsystem state must be separable, or the behavior
|
|
2060
|
-
of this method is undefined.
|
|
2164
|
+
Factorize a set of contiguous bits with minimal fidelity loss,
|
|
2165
|
+
and discard the separable bits.
|
|
2061
2166
|
|
|
2062
2167
|
Args:
|
|
2063
2168
|
q: qubit
|
|
@@ -2065,12 +2170,11 @@ class QrackSimulator:
|
|
|
2065
2170
|
Raises:
|
|
2066
2171
|
RuntimeError: QrackSimulator raised an exception.
|
|
2067
2172
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot dispose()! (Turn off just this option, in the constructor.)
|
|
2068
|
-
|
|
2069
|
-
Returns:
|
|
2070
|
-
State of the systems.
|
|
2071
2173
|
"""
|
|
2072
2174
|
if self.is_tensor_network:
|
|
2073
|
-
raise RuntimeError(
|
|
2175
|
+
raise RuntimeError(
|
|
2176
|
+
"QrackSimulator with isTensorNetwork=True option cannot dispose()! (Turn off just this option, in the constructor.)"
|
|
2177
|
+
)
|
|
2074
2178
|
|
|
2075
2179
|
l = len(q)
|
|
2076
2180
|
Qrack.qrack_lib.Dispose(self.sid, l, self._ulonglong_byref(q))
|
|
@@ -2133,8 +2237,8 @@ class QrackSimulator:
|
|
|
2133
2237
|
def in_ket(self, ket):
|
|
2134
2238
|
"""Set state vector
|
|
2135
2239
|
|
|
2136
|
-
Set state vector for the selected simulator ID.
|
|
2137
|
-
Warning: State vector is not always the internal representation leading
|
|
2240
|
+
Set state vector for the selected simulator ID.
|
|
2241
|
+
Warning: State vector is not always the internal representation leading
|
|
2138
2242
|
to sub-optimal performance of the method.
|
|
2139
2243
|
|
|
2140
2244
|
Args:
|
|
@@ -2147,10 +2251,10 @@ class QrackSimulator:
|
|
|
2147
2251
|
self._throw_if_error()
|
|
2148
2252
|
|
|
2149
2253
|
def out_ket(self):
|
|
2150
|
-
"""
|
|
2254
|
+
"""Get state vector
|
|
2151
2255
|
|
|
2152
2256
|
Returns the raw state vector of the simulator.
|
|
2153
|
-
Warning: State vector is not always the internal representation leading
|
|
2257
|
+
Warning: State vector is not always the internal representation leading
|
|
2154
2258
|
to sub-optimal performance of the method.
|
|
2155
2259
|
|
|
2156
2260
|
Raises:
|
|
@@ -2165,6 +2269,90 @@ class QrackSimulator:
|
|
|
2165
2269
|
self._throw_if_error()
|
|
2166
2270
|
return [complex(r, i) for r, i in self._pairwise(ket)]
|
|
2167
2271
|
|
|
2272
|
+
def out_probs(self):
|
|
2273
|
+
"""Get basis dimension probabilities
|
|
2274
|
+
|
|
2275
|
+
Returns the probabilities of each basis dimension in the state vector
|
|
2276
|
+
of the simulator.
|
|
2277
|
+
|
|
2278
|
+
Raises:
|
|
2279
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
2280
|
+
|
|
2281
|
+
Returns:
|
|
2282
|
+
list representing the basis dimension probabilities.
|
|
2283
|
+
"""
|
|
2284
|
+
prob_count = 1 << self.num_qubits()
|
|
2285
|
+
probs = self._real1_byref([0.0] * prob_count)
|
|
2286
|
+
Qrack.qrack_lib.OutProbs(self.sid, probs)
|
|
2287
|
+
self._throw_if_error()
|
|
2288
|
+
return list(probs)
|
|
2289
|
+
|
|
2290
|
+
def out_rdm(self, q):
|
|
2291
|
+
"""Get reduced density matrix
|
|
2292
|
+
|
|
2293
|
+
Returns the raw reduced density matrix of the simulator, for the qubit list.
|
|
2294
|
+
Warning: State vector or is not always the internal representation leading
|
|
2295
|
+
to sub-optimal performance of the method.
|
|
2296
|
+
|
|
2297
|
+
Raises:
|
|
2298
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
2299
|
+
|
|
2300
|
+
Returns:
|
|
2301
|
+
flat list structure representing the reduced density matrix.
|
|
2302
|
+
"""
|
|
2303
|
+
amp_count = 1 << len(q)
|
|
2304
|
+
sqr_amp_count = amp_count * amp_count
|
|
2305
|
+
flat_rdm = self._qrack_complex_byref([complex(0, 0)] * sqr_amp_count)
|
|
2306
|
+
Qrack.qrack_lib.OutReducedDensityMatrix(self.sid, len(q), self._ulonglong_byref(q), flat_rdm)
|
|
2307
|
+
self._throw_if_error()
|
|
2308
|
+
return [complex(r, i) for r, i in self._pairwise(flat_rdm)]
|
|
2309
|
+
|
|
2310
|
+
def highest_prob_perm(self):
|
|
2311
|
+
"""Get the permutation (bit string) with the highest probability
|
|
2312
|
+
|
|
2313
|
+
Returns the single highest-probability bit string in the Hilbert space
|
|
2314
|
+
|
|
2315
|
+
Raises:
|
|
2316
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
2317
|
+
|
|
2318
|
+
Returns:
|
|
2319
|
+
Highest probability dimension index
|
|
2320
|
+
"""
|
|
2321
|
+
num_q = self.num_qubits()
|
|
2322
|
+
num_words = (num_q + 63) // 64
|
|
2323
|
+
_r = (ctypes.c_ulonglong * num_words)()
|
|
2324
|
+
Qrack.qrack_lib.HighestProbAll(self.sid, _r)
|
|
2325
|
+
self._throw_if_error()
|
|
2326
|
+
r = 0
|
|
2327
|
+
for w in range(num_words):
|
|
2328
|
+
r <<= 64
|
|
2329
|
+
r |= _r[w]
|
|
2330
|
+
return r
|
|
2331
|
+
|
|
2332
|
+
def highest_n_prob_perm(self, n):
|
|
2333
|
+
"""Get the top n permutations (bit strings) with the highest probability
|
|
2334
|
+
|
|
2335
|
+
Returns the top n highest-probability bit strings in the Hilbert space
|
|
2336
|
+
|
|
2337
|
+
Raises:
|
|
2338
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
2339
|
+
|
|
2340
|
+
Returns:
|
|
2341
|
+
Top n highest probability dimension indices
|
|
2342
|
+
"""
|
|
2343
|
+
num_q = self.num_qubits()
|
|
2344
|
+
num_words = (num_q + 63) // 64
|
|
2345
|
+
_r = (ctypes.c_ulonglong * (num_words * n))()
|
|
2346
|
+
Qrack.qrack_lib.HighestProbAllN(self.sid, n, _r)
|
|
2347
|
+
self._throw_if_error()
|
|
2348
|
+
r = [0] * n
|
|
2349
|
+
for i in range(n):
|
|
2350
|
+
r[i] = 0
|
|
2351
|
+
for w in range(num_words):
|
|
2352
|
+
r[i] <<= 64
|
|
2353
|
+
r[i] |= _r[(i * num_words) + w]
|
|
2354
|
+
return r
|
|
2355
|
+
|
|
2168
2356
|
def prob_all(self, q):
|
|
2169
2357
|
"""Probabilities of all subset permutations
|
|
2170
2358
|
|
|
@@ -2241,11 +2429,13 @@ class QrackSimulator:
|
|
|
2241
2429
|
|
|
2242
2430
|
if len(q) != len(c):
|
|
2243
2431
|
raise RuntimeError("prob_perm argument lengths do not match.")
|
|
2244
|
-
result = Qrack.qrack_lib.PermutationProb(
|
|
2432
|
+
result = Qrack.qrack_lib.PermutationProb(
|
|
2433
|
+
self.sid, len(q), self._ulonglong_byref(q), self._bool_byref(c)
|
|
2434
|
+
)
|
|
2245
2435
|
self._throw_if_error()
|
|
2246
2436
|
return result
|
|
2247
2437
|
|
|
2248
|
-
def prob_perm_rdm(self, q, c, r
|
|
2438
|
+
def prob_perm_rdm(self, q, c, r=True):
|
|
2249
2439
|
"""Probability of permutation, (tracing out the reduced
|
|
2250
2440
|
density matrix without stabilizer ancillary qubits)
|
|
2251
2441
|
|
|
@@ -2267,7 +2457,9 @@ class QrackSimulator:
|
|
|
2267
2457
|
|
|
2268
2458
|
if len(q) != len(c):
|
|
2269
2459
|
raise RuntimeError("prob_perm argument lengths do not match.")
|
|
2270
|
-
result = Qrack.qrack_lib.PermutationProbRdm(
|
|
2460
|
+
result = Qrack.qrack_lib.PermutationProbRdm(
|
|
2461
|
+
self.sid, len(q), self._ulonglong_byref(q), self._bool_byref(c), r
|
|
2462
|
+
)
|
|
2271
2463
|
self._throw_if_error()
|
|
2272
2464
|
return result
|
|
2273
2465
|
|
|
@@ -2292,7 +2484,7 @@ class QrackSimulator:
|
|
|
2292
2484
|
self._throw_if_error()
|
|
2293
2485
|
return result
|
|
2294
2486
|
|
|
2295
|
-
def permutation_expectation_rdm(self, q, r
|
|
2487
|
+
def permutation_expectation_rdm(self, q, r=True):
|
|
2296
2488
|
"""Permutation expectation value, (tracing out the reduced
|
|
2297
2489
|
density matrix without stabilizer ancillary qubits)
|
|
2298
2490
|
|
|
@@ -2341,7 +2533,7 @@ class QrackSimulator:
|
|
|
2341
2533
|
self._throw_if_error()
|
|
2342
2534
|
return result
|
|
2343
2535
|
|
|
2344
|
-
def factorized_expectation_rdm(self, q, c, r
|
|
2536
|
+
def factorized_expectation_rdm(self, q, c, r=True):
|
|
2345
2537
|
"""Factorized expectation value, (tracing out the reduced
|
|
2346
2538
|
density matrix without stabilizer ancillary qubits)
|
|
2347
2539
|
|
|
@@ -2361,7 +2553,9 @@ class QrackSimulator:
|
|
|
2361
2553
|
Expectation value
|
|
2362
2554
|
"""
|
|
2363
2555
|
if (len(q) << 1) != len(c):
|
|
2364
|
-
raise RuntimeError(
|
|
2556
|
+
raise RuntimeError(
|
|
2557
|
+
"factorized_expectation_rdm argument lengths do not match."
|
|
2558
|
+
)
|
|
2365
2559
|
m = max([(x.bit_length() + 63) // 64 for x in c])
|
|
2366
2560
|
result = Qrack.qrack_lib.FactorizedExpectationRdm(
|
|
2367
2561
|
self.sid, len(q), self._ulonglong_byref(q), m, self._to_ulonglong(m, c), r
|
|
@@ -2387,14 +2581,16 @@ class QrackSimulator:
|
|
|
2387
2581
|
Expectation value
|
|
2388
2582
|
"""
|
|
2389
2583
|
if (len(q) << 1) != len(c):
|
|
2390
|
-
raise RuntimeError(
|
|
2584
|
+
raise RuntimeError(
|
|
2585
|
+
"factorized_expectation_rdm argument lengths do not match."
|
|
2586
|
+
)
|
|
2391
2587
|
result = Qrack.qrack_lib.FactorizedExpectationFp(
|
|
2392
2588
|
self.sid, len(q), self._ulonglong_byref(q), self._real1_byref(c)
|
|
2393
2589
|
)
|
|
2394
2590
|
self._throw_if_error()
|
|
2395
2591
|
return result
|
|
2396
2592
|
|
|
2397
|
-
def factorized_expectation_fp_rdm(self, q, c, r
|
|
2593
|
+
def factorized_expectation_fp_rdm(self, q, c, r=True):
|
|
2398
2594
|
"""Factorized expectation value, (tracing out the reduced
|
|
2399
2595
|
density matrix without stabilizer ancillary qubits)
|
|
2400
2596
|
|
|
@@ -2414,7 +2610,9 @@ class QrackSimulator:
|
|
|
2414
2610
|
Expectation value
|
|
2415
2611
|
"""
|
|
2416
2612
|
if (len(q) << 1) != len(c):
|
|
2417
|
-
raise RuntimeError(
|
|
2613
|
+
raise RuntimeError(
|
|
2614
|
+
"factorized_expectation_fp_rdm argument lengths do not match."
|
|
2615
|
+
)
|
|
2418
2616
|
result = Qrack.qrack_lib.FactorizedExpectationFpRdm(
|
|
2419
2617
|
self.sid, len(q), self._ulonglong_byref(q), self._real1_byref(c), r
|
|
2420
2618
|
)
|
|
@@ -2486,11 +2684,19 @@ class QrackSimulator:
|
|
|
2486
2684
|
Expectation value
|
|
2487
2685
|
"""
|
|
2488
2686
|
if (3 * len(q)) != len(b):
|
|
2489
|
-
raise RuntimeError(
|
|
2687
|
+
raise RuntimeError(
|
|
2688
|
+
"unitary_expectation_eigenval qubit and basis argument lengths do not match."
|
|
2689
|
+
)
|
|
2490
2690
|
if (len(q) << 1) != len(e):
|
|
2491
|
-
raise RuntimeError(
|
|
2691
|
+
raise RuntimeError(
|
|
2692
|
+
"unitary_expectation_eigenval qubit and eigenvalue argument lengths do not match."
|
|
2693
|
+
)
|
|
2492
2694
|
result = Qrack.qrack_lib.UnitaryExpectationEigenVal(
|
|
2493
|
-
self.sid,
|
|
2695
|
+
self.sid,
|
|
2696
|
+
len(q),
|
|
2697
|
+
self._ulonglong_byref(q),
|
|
2698
|
+
self._real1_byref(b),
|
|
2699
|
+
self._real1_byref(e),
|
|
2494
2700
|
)
|
|
2495
2701
|
self._throw_if_error()
|
|
2496
2702
|
return result
|
|
@@ -2512,11 +2718,19 @@ class QrackSimulator:
|
|
|
2512
2718
|
Expectation value
|
|
2513
2719
|
"""
|
|
2514
2720
|
if (len(q) << 2) != len(b):
|
|
2515
|
-
raise RuntimeError(
|
|
2721
|
+
raise RuntimeError(
|
|
2722
|
+
"matrix_expectation_eigenval qubit and basis argument lengths do not match."
|
|
2723
|
+
)
|
|
2516
2724
|
if (len(q) << 1) != len(e):
|
|
2517
|
-
raise RuntimeError(
|
|
2725
|
+
raise RuntimeError(
|
|
2726
|
+
"matrix_expectation_eigenval qubit and eigenvalue argument lengths do not match."
|
|
2727
|
+
)
|
|
2518
2728
|
result = Qrack.qrack_lib.MatrixExpectationEigenVal(
|
|
2519
|
-
self.sid,
|
|
2729
|
+
self.sid,
|
|
2730
|
+
len(q),
|
|
2731
|
+
self._ulonglong_byref(q),
|
|
2732
|
+
self._complex_byref(b),
|
|
2733
|
+
self._real1_byref(e),
|
|
2520
2734
|
)
|
|
2521
2735
|
self._throw_if_error()
|
|
2522
2736
|
return result
|
|
@@ -2565,7 +2779,7 @@ class QrackSimulator:
|
|
|
2565
2779
|
self._throw_if_error()
|
|
2566
2780
|
return result
|
|
2567
2781
|
|
|
2568
|
-
def variance_rdm(self, q, r
|
|
2782
|
+
def variance_rdm(self, q, r=True):
|
|
2569
2783
|
"""Permutation variance, (tracing out the reduced
|
|
2570
2784
|
density matrix without stabilizer ancillary qubits)
|
|
2571
2785
|
|
|
@@ -2614,7 +2828,7 @@ class QrackSimulator:
|
|
|
2614
2828
|
self._throw_if_error()
|
|
2615
2829
|
return result
|
|
2616
2830
|
|
|
2617
|
-
def factorized_variance_rdm(self, q, c, r
|
|
2831
|
+
def factorized_variance_rdm(self, q, c, r=True):
|
|
2618
2832
|
"""Factorized variance, (tracing out the reduced
|
|
2619
2833
|
density matrix without stabilizer ancillary qubits)
|
|
2620
2834
|
|
|
@@ -2667,7 +2881,7 @@ class QrackSimulator:
|
|
|
2667
2881
|
self._throw_if_error()
|
|
2668
2882
|
return result
|
|
2669
2883
|
|
|
2670
|
-
def factorized_variance_fp_rdm(self, q, c, r
|
|
2884
|
+
def factorized_variance_fp_rdm(self, q, c, r=True):
|
|
2671
2885
|
"""Factorized variance, (tracing out the reduced
|
|
2672
2886
|
density matrix without stabilizer ancillary qubits)
|
|
2673
2887
|
|
|
@@ -2687,7 +2901,9 @@ class QrackSimulator:
|
|
|
2687
2901
|
variance
|
|
2688
2902
|
"""
|
|
2689
2903
|
if (len(q) << 1) != len(c):
|
|
2690
|
-
raise RuntimeError(
|
|
2904
|
+
raise RuntimeError(
|
|
2905
|
+
"factorized_variance_fp_rdm argument lengths do not match."
|
|
2906
|
+
)
|
|
2691
2907
|
result = Qrack.qrack_lib.FactorizedVarianceFpRdm(
|
|
2692
2908
|
self.sid, len(q), self._ulonglong_byref(q), self._real1_byref(c), r
|
|
2693
2909
|
)
|
|
@@ -2759,11 +2975,19 @@ class QrackSimulator:
|
|
|
2759
2975
|
variance
|
|
2760
2976
|
"""
|
|
2761
2977
|
if (3 * len(q)) != len(b):
|
|
2762
|
-
raise RuntimeError(
|
|
2978
|
+
raise RuntimeError(
|
|
2979
|
+
"unitary_variance_eigenval qubit and basis argument lengths do not match."
|
|
2980
|
+
)
|
|
2763
2981
|
if (len(q) << 1) != len(e):
|
|
2764
|
-
raise RuntimeError(
|
|
2982
|
+
raise RuntimeError(
|
|
2983
|
+
"unitary_variance_eigenval qubit and eigenvalue argument lengths do not match."
|
|
2984
|
+
)
|
|
2765
2985
|
result = Qrack.qrack_lib.UnitaryVarianceEigenVal(
|
|
2766
|
-
self.sid,
|
|
2986
|
+
self.sid,
|
|
2987
|
+
len(q),
|
|
2988
|
+
self._ulonglong_byref(q),
|
|
2989
|
+
self._real1_byref(b),
|
|
2990
|
+
self._real1_byref(e),
|
|
2767
2991
|
)
|
|
2768
2992
|
self._throw_if_error()
|
|
2769
2993
|
return result
|
|
@@ -2785,11 +3009,19 @@ class QrackSimulator:
|
|
|
2785
3009
|
variance
|
|
2786
3010
|
"""
|
|
2787
3011
|
if (len(q) << 2) != len(b):
|
|
2788
|
-
raise RuntimeError(
|
|
3012
|
+
raise RuntimeError(
|
|
3013
|
+
"matrix_variance_eigenval qubit and basis argument lengths do not match."
|
|
3014
|
+
)
|
|
2789
3015
|
if (len(q) << 1) != len(e):
|
|
2790
|
-
raise RuntimeError(
|
|
3016
|
+
raise RuntimeError(
|
|
3017
|
+
"matrix_variance_eigenval qubit and eigenvalue argument lengths do not match."
|
|
3018
|
+
)
|
|
2791
3019
|
result = Qrack.qrack_lib.MatrixVarianceEigenVal(
|
|
2792
|
-
self.sid,
|
|
3020
|
+
self.sid,
|
|
3021
|
+
len(q),
|
|
3022
|
+
self._ulonglong_byref(q),
|
|
3023
|
+
self._complex_byref(b),
|
|
3024
|
+
self._real1_byref(e),
|
|
2793
3025
|
)
|
|
2794
3026
|
self._throw_if_error()
|
|
2795
3027
|
return result
|
|
@@ -2858,7 +3090,13 @@ class QrackSimulator:
|
|
|
2858
3090
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot phase_parity()! (Turn off just this option, in the constructor.)
|
|
2859
3091
|
"""
|
|
2860
3092
|
if self.is_tensor_network:
|
|
2861
|
-
raise RuntimeError(
|
|
3093
|
+
raise RuntimeError(
|
|
3094
|
+
"QrackSimulator with isTensorNetwork=True option cannot phase_parity()! (Turn off just this option, in the constructor.)"
|
|
3095
|
+
)
|
|
3096
|
+
if self.is_pure_stabilizer:
|
|
3097
|
+
raise RuntimeError(
|
|
3098
|
+
"QrackStabilizer cannot phase_parity()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
3099
|
+
)
|
|
2862
3100
|
|
|
2863
3101
|
Qrack.qrack_lib.PhaseParity(
|
|
2864
3102
|
self.sid, ctypes.c_double(la), len(q), self._ulonglong_byref(q)
|
|
@@ -2879,11 +3117,15 @@ class QrackSimulator:
|
|
|
2879
3117
|
RuntimeError: QrackSimulator with isTensorNetwork=True option cannot phase_root_n()! (Turn off just this option, in the constructor.)
|
|
2880
3118
|
"""
|
|
2881
3119
|
if self.is_tensor_network:
|
|
2882
|
-
raise RuntimeError(
|
|
3120
|
+
raise RuntimeError(
|
|
3121
|
+
"QrackSimulator with isTensorNetwork=True option cannot phase_root_n()! (Turn off just this option, in the constructor.)"
|
|
3122
|
+
)
|
|
3123
|
+
if self.is_pure_stabilizer:
|
|
3124
|
+
raise RuntimeError(
|
|
3125
|
+
"QrackStabilizer cannot phase_root_n()! (Create a QrackSimulator instead, also with isTensorNetwork=False.)"
|
|
3126
|
+
)
|
|
2883
3127
|
|
|
2884
|
-
Qrack.qrack_lib.PhaseRootN(
|
|
2885
|
-
self.sid, n, len(q), self._ulonglong_byref(q)
|
|
2886
|
-
)
|
|
3128
|
+
Qrack.qrack_lib.PhaseRootN(self.sid, n, len(q), self._ulonglong_byref(q))
|
|
2887
3129
|
self._throw_if_error()
|
|
2888
3130
|
|
|
2889
3131
|
def try_separate_1qb(self, qi1):
|
|
@@ -2945,6 +3187,20 @@ class QrackSimulator:
|
|
|
2945
3187
|
self._throw_if_error()
|
|
2946
3188
|
return result
|
|
2947
3189
|
|
|
3190
|
+
def separate(self, qs):
|
|
3191
|
+
"""Force manual multi-qubits seperation
|
|
3192
|
+
|
|
3193
|
+
Force separation as per `try_separate_tolerance`.
|
|
3194
|
+
|
|
3195
|
+
Args:
|
|
3196
|
+
qs: list of qubits to be decomposed
|
|
3197
|
+
|
|
3198
|
+
Raises:
|
|
3199
|
+
Runtimeerror: QrackSimulator raised an exception.
|
|
3200
|
+
"""
|
|
3201
|
+
result = Qrack.qrack_lib.Separate(self.sid, len(qs), self._ulonglong_byref(qs))
|
|
3202
|
+
self._throw_if_error()
|
|
3203
|
+
|
|
2948
3204
|
def get_unitary_fidelity(self):
|
|
2949
3205
|
"""Get fidelity estimate
|
|
2950
3206
|
|
|
@@ -3051,6 +3307,35 @@ class QrackSimulator:
|
|
|
3051
3307
|
Qrack.qrack_lib.SetTInjection(self.sid, iti)
|
|
3052
3308
|
self._throw_if_error()
|
|
3053
3309
|
|
|
3310
|
+
def set_noise_parameter(self, np):
|
|
3311
|
+
"""Set noise parameter option
|
|
3312
|
+
|
|
3313
|
+
If noisy simulation is on, then this set the depolarization
|
|
3314
|
+
parameter per qubit per gate. (Default is 0.01.)
|
|
3315
|
+
|
|
3316
|
+
Args:
|
|
3317
|
+
np: depolarizing noise parameter
|
|
3318
|
+
|
|
3319
|
+
Raises:
|
|
3320
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
3321
|
+
"""
|
|
3322
|
+
Qrack.qrack_lib.SetNoiseParameter(self.sid, np)
|
|
3323
|
+
self._throw_if_error()
|
|
3324
|
+
|
|
3325
|
+
def normalize(self):
|
|
3326
|
+
"""Normalize the state
|
|
3327
|
+
|
|
3328
|
+
This should never be necessary to use unless
|
|
3329
|
+
decompose() is "abused." ("Abusing" decompose()
|
|
3330
|
+
might lead to efficient entanglement-breaking
|
|
3331
|
+
channels, though.)
|
|
3332
|
+
|
|
3333
|
+
Raises:
|
|
3334
|
+
RuntimeError: QrackSimulator raised an exception.
|
|
3335
|
+
"""
|
|
3336
|
+
Qrack.qrack_lib.Normalize(self.sid)
|
|
3337
|
+
self._throw_if_error()
|
|
3338
|
+
|
|
3054
3339
|
def out_to_file(self, filename):
|
|
3055
3340
|
"""Output state to file (stabilizer only!)
|
|
3056
3341
|
|
|
@@ -3059,10 +3344,18 @@ class QrackSimulator:
|
|
|
3059
3344
|
Args:
|
|
3060
3345
|
filename: Name of file
|
|
3061
3346
|
"""
|
|
3062
|
-
Qrack.qrack_lib.qstabilizer_out_to_file(self.sid, filename.encode(
|
|
3347
|
+
Qrack.qrack_lib.qstabilizer_out_to_file(self.sid, filename.encode("utf-8"))
|
|
3063
3348
|
self._throw_if_error()
|
|
3064
3349
|
|
|
3065
|
-
def in_from_file(
|
|
3350
|
+
def in_from_file(
|
|
3351
|
+
filename,
|
|
3352
|
+
is_binary_decision_tree=False,
|
|
3353
|
+
is_paged=True,
|
|
3354
|
+
is_cpu_gpu_hybrid=False,
|
|
3355
|
+
is_opencl=True,
|
|
3356
|
+
is_host_pointer=False,
|
|
3357
|
+
is_noisy=False,
|
|
3358
|
+
):
|
|
3066
3359
|
"""Input state from file (stabilizer only!)
|
|
3067
3360
|
|
|
3068
3361
|
Reads in a hybrid stabilizer state from file.
|
|
@@ -3083,9 +3376,10 @@ class QrackSimulator:
|
|
|
3083
3376
|
isPaged=is_paged,
|
|
3084
3377
|
isCpuGpuHybrid=is_cpu_gpu_hybrid,
|
|
3085
3378
|
isOpenCL=is_opencl,
|
|
3086
|
-
isHostPointer=is_host_pointer
|
|
3379
|
+
isHostPointer=is_host_pointer,
|
|
3380
|
+
isNoisy=is_noisy,
|
|
3087
3381
|
)
|
|
3088
|
-
Qrack.qrack_lib.qstabilizer_in_from_file(out.sid, filename.encode(
|
|
3382
|
+
Qrack.qrack_lib.qstabilizer_in_from_file(out.sid, filename.encode("utf-8"))
|
|
3089
3383
|
out._throw_if_error()
|
|
3090
3384
|
|
|
3091
3385
|
return out
|
|
@@ -3110,7 +3404,7 @@ class QrackSimulator:
|
|
|
3110
3404
|
)
|
|
3111
3405
|
|
|
3112
3406
|
lines = []
|
|
3113
|
-
with open(filename,
|
|
3407
|
+
with open(filename, "r") as file:
|
|
3114
3408
|
lines = file.readlines()
|
|
3115
3409
|
|
|
3116
3410
|
logical_qubits = int(lines[0])
|
|
@@ -3118,9 +3412,7 @@ class QrackSimulator:
|
|
|
3118
3412
|
|
|
3119
3413
|
stabilizer_count = int(lines[2])
|
|
3120
3414
|
|
|
3121
|
-
|
|
3122
|
-
circ_qubits = [Qubit(reg, i) for i in range(stabilizer_qubits)]
|
|
3123
|
-
clifford_circ = QuantumCircuit(reg)
|
|
3415
|
+
clifford_circ = None
|
|
3124
3416
|
line_number = 3
|
|
3125
3417
|
for i in range(stabilizer_count):
|
|
3126
3418
|
shard_map_size = int(lines[line_number])
|
|
@@ -3132,14 +3424,10 @@ class QrackSimulator:
|
|
|
3132
3424
|
line_number += 1
|
|
3133
3425
|
shard_map[int(line[0])] = int(line[1])
|
|
3134
3426
|
|
|
3135
|
-
sub_reg = []
|
|
3136
|
-
for index, _ in sorted(shard_map.items(), key=lambda x: x[1]):
|
|
3137
|
-
sub_reg.append(circ_qubits[index])
|
|
3138
|
-
|
|
3139
3427
|
line_number += 1
|
|
3140
3428
|
tableau = []
|
|
3141
3429
|
row_count = shard_map_size << 1
|
|
3142
|
-
for line in lines[line_number:(line_number + row_count)]:
|
|
3430
|
+
for line in lines[line_number : (line_number + row_count)]:
|
|
3143
3431
|
bits = line.split()
|
|
3144
3432
|
if len(bits) != (row_count + 1):
|
|
3145
3433
|
raise QrackException("Invalid Qrack hybrid stabilizer file!")
|
|
@@ -3148,31 +3436,23 @@ class QrackSimulator:
|
|
|
3148
3436
|
row.append(bool(int(bits[b])))
|
|
3149
3437
|
row.append(bool((int(bits[-1]) >> 1) & 1))
|
|
3150
3438
|
tableau.append(row)
|
|
3151
|
-
line_number +=
|
|
3439
|
+
line_number += shard_map_size << 1
|
|
3152
3440
|
tableau = np.array(tableau, bool)
|
|
3153
3441
|
|
|
3154
3442
|
clifford = Clifford(tableau, validate=False, copy=False)
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
for instr in circ.data:
|
|
3158
|
-
qubits = instr.qubits
|
|
3159
|
-
n_qubits = []
|
|
3160
|
-
for qubit in qubits:
|
|
3161
|
-
n_qubits.append(sub_reg[circ.find_bit(qubit)[0]])
|
|
3162
|
-
instr.qubits = tuple(n_qubits)
|
|
3163
|
-
clifford_circ.data.append(instr)
|
|
3164
|
-
del circ
|
|
3443
|
+
clifford_circ = clifford.to_circuit()
|
|
3444
|
+
clifford_circ = QrackSimulator._reorder_qubits(clifford_circ, shard_map)
|
|
3165
3445
|
|
|
3166
3446
|
non_clifford_gates = []
|
|
3167
3447
|
g = 0
|
|
3168
3448
|
for line in lines[line_number:]:
|
|
3169
3449
|
i = 0
|
|
3170
3450
|
tokens = line.split()
|
|
3171
|
-
op = np.zeros((2,2), dtype=complex)
|
|
3451
|
+
op = np.zeros((2, 2), dtype=complex)
|
|
3172
3452
|
row = []
|
|
3173
3453
|
for _ in range(2):
|
|
3174
|
-
amp = tokens[i].replace("(","").replace(")","").split(
|
|
3175
|
-
row.append(float(amp[0]) + float(amp[1])*1j)
|
|
3454
|
+
amp = tokens[i].replace("(", "").replace(")", "").split(",")
|
|
3455
|
+
row.append(float(amp[0]) + float(amp[1]) * 1j)
|
|
3176
3456
|
i = i + 1
|
|
3177
3457
|
l = math.sqrt(np.real(row[0] * np.conj(row[0]) + row[1] * np.conj(row[1])))
|
|
3178
3458
|
op[0][0] = row[0] / l
|
|
@@ -3185,8 +3465,8 @@ class QrackSimulator:
|
|
|
3185
3465
|
|
|
3186
3466
|
row = []
|
|
3187
3467
|
for _ in range(2):
|
|
3188
|
-
amp = tokens[i].replace("(","").replace(")","").split(
|
|
3189
|
-
row.append(float(amp[0]) + float(amp[1])*1j)
|
|
3468
|
+
amp = tokens[i].replace("(", "").replace(")", "").split(",")
|
|
3469
|
+
row.append(float(amp[0]) + float(amp[1]) * 1j)
|
|
3190
3470
|
i = i + 1
|
|
3191
3471
|
l = math.sqrt(np.real(row[0] * np.conj(row[0]) + row[1] * np.conj(row[1])))
|
|
3192
3472
|
op[1][0] = row[0] / l
|
|
@@ -3205,9 +3485,27 @@ class QrackSimulator:
|
|
|
3205
3485
|
non_clifford_gates.append(op)
|
|
3206
3486
|
g = g + 1
|
|
3207
3487
|
|
|
3208
|
-
basis_gates = [
|
|
3488
|
+
basis_gates = [
|
|
3489
|
+
"rz",
|
|
3490
|
+
"h",
|
|
3491
|
+
"x",
|
|
3492
|
+
"y",
|
|
3493
|
+
"z",
|
|
3494
|
+
"sx",
|
|
3495
|
+
"sxdg",
|
|
3496
|
+
"s",
|
|
3497
|
+
"sdg",
|
|
3498
|
+
"t",
|
|
3499
|
+
"tdg",
|
|
3500
|
+
"cx",
|
|
3501
|
+
"cy",
|
|
3502
|
+
"cz",
|
|
3503
|
+
"swap",
|
|
3504
|
+
]
|
|
3209
3505
|
try:
|
|
3210
|
-
circ = transpile(
|
|
3506
|
+
circ = transpile(
|
|
3507
|
+
clifford_circ, basis_gates=basis_gates, optimization_level=2
|
|
3508
|
+
)
|
|
3211
3509
|
except:
|
|
3212
3510
|
circ = clifford_circ
|
|
3213
3511
|
|
|
@@ -3222,6 +3520,35 @@ class QrackSimulator:
|
|
|
3222
3520
|
|
|
3223
3521
|
return circ
|
|
3224
3522
|
|
|
3523
|
+
def _reorder_qubits(circuit, mapping):
|
|
3524
|
+
"""
|
|
3525
|
+
Reorders qubits in the circuit according to the given mapping using SWAP gates.
|
|
3526
|
+
(Thanks to "Elara," an OpenAI GPT, for this implementation)
|
|
3527
|
+
|
|
3528
|
+
Parameters:
|
|
3529
|
+
- circuit (QuantumCircuit): The circuit to modify.
|
|
3530
|
+
- mapping (dict): Dictionary mapping internal qubit indices to logical qubit indices.
|
|
3531
|
+
|
|
3532
|
+
Returns:
|
|
3533
|
+
- QuantumCircuit: The modified circuit with qubits reordered.
|
|
3534
|
+
"""
|
|
3535
|
+
swaps = []
|
|
3536
|
+
|
|
3537
|
+
# Determine swaps to fix the order
|
|
3538
|
+
for logical_index in sorted(mapping):
|
|
3539
|
+
internal_index = mapping[logical_index]
|
|
3540
|
+
if logical_index != internal_index:
|
|
3541
|
+
swaps.append((logical_index, internal_index))
|
|
3542
|
+
# Update the reverse mapping for subsequent swaps
|
|
3543
|
+
mapping[logical_index] = logical_index
|
|
3544
|
+
mapping[internal_index] = internal_index
|
|
3545
|
+
|
|
3546
|
+
# Apply the swaps to the circuit
|
|
3547
|
+
for qubit1, qubit2 in swaps:
|
|
3548
|
+
circuit.swap(qubit1, qubit2)
|
|
3549
|
+
|
|
3550
|
+
return circuit
|
|
3551
|
+
|
|
3225
3552
|
def file_to_optimized_qiskit_circuit(filename):
|
|
3226
3553
|
"""Convert an output state file to a Qiskit circuit
|
|
3227
3554
|
|
|
@@ -3239,7 +3566,7 @@ class QrackSimulator:
|
|
|
3239
3566
|
QrackCircuit, you must install Qiskit, numpy, and math!
|
|
3240
3567
|
"""
|
|
3241
3568
|
circ = QrackSimulator.file_to_qiskit_circuit(filename)
|
|
3242
|
-
|
|
3569
|
+
|
|
3243
3570
|
width = 0
|
|
3244
3571
|
with open(filename, "r", encoding="utf-8") as file:
|
|
3245
3572
|
width = int(file.readline())
|
|
@@ -3248,7 +3575,7 @@ class QrackSimulator:
|
|
|
3248
3575
|
sqrt_ni = np.sqrt(-1j)
|
|
3249
3576
|
sqrt1_2 = 1 / math.sqrt(2)
|
|
3250
3577
|
ident = np.eye(2, dtype=np.complex128)
|
|
3251
|
-
# passable_gates = ["unitary", "rz", "h", "x", "y", "z", "sx", "sxdg", "
|
|
3578
|
+
# passable_gates = ["unitary", "rz", "h", "x", "y", "z", "sx", "sxdg", "s", "sdg", "t", "tdg"]
|
|
3252
3579
|
|
|
3253
3580
|
passed_swaps = []
|
|
3254
3581
|
for i in range(0, circ.width()):
|
|
@@ -3259,40 +3586,104 @@ class QrackSimulator:
|
|
|
3259
3586
|
op = circ.data[j].operation
|
|
3260
3587
|
qubits = circ.data[j].qubits
|
|
3261
3588
|
if len(qubits) > 2:
|
|
3262
|
-
raise RuntimeError(
|
|
3589
|
+
raise RuntimeError(
|
|
3590
|
+
"Something went wrong while optimizing circuit! (Found a gate with 3 or more qubits)"
|
|
3591
|
+
)
|
|
3263
3592
|
q1 = circ.find_bit(qubits[0])[0]
|
|
3264
3593
|
if (len(qubits) < 2) and (q1 == i):
|
|
3265
3594
|
if op.name == "unitary":
|
|
3266
3595
|
non_clifford = np.matmul(op.params[0], non_clifford)
|
|
3267
3596
|
elif op.name == "rz":
|
|
3268
3597
|
lm = float(op.params[0])
|
|
3269
|
-
non_clifford = np.matmul(
|
|
3598
|
+
non_clifford = np.matmul(
|
|
3599
|
+
[[np.exp(-1j * lm / 2), 0], [0, np.exp(1j * lm / 2)]],
|
|
3600
|
+
non_clifford,
|
|
3601
|
+
)
|
|
3270
3602
|
elif op.name == "h":
|
|
3271
|
-
non_clifford = np.matmul(
|
|
3603
|
+
non_clifford = np.matmul(
|
|
3604
|
+
np.array(
|
|
3605
|
+
[[sqrt1_2, sqrt1_2], [sqrt1_2, -sqrt1_2]], np.complex128
|
|
3606
|
+
),
|
|
3607
|
+
non_clifford,
|
|
3608
|
+
)
|
|
3272
3609
|
elif op.name == "x":
|
|
3273
|
-
non_clifford = np.matmul(
|
|
3610
|
+
non_clifford = np.matmul(
|
|
3611
|
+
np.array([[0, 1], [1, 0]], np.complex128), non_clifford
|
|
3612
|
+
)
|
|
3274
3613
|
elif op.name == "y":
|
|
3275
|
-
non_clifford = np.matmul(
|
|
3614
|
+
non_clifford = np.matmul(
|
|
3615
|
+
np.array([[0, -1j], [1j, 0]], np.complex128), non_clifford
|
|
3616
|
+
)
|
|
3276
3617
|
elif op.name == "z":
|
|
3277
|
-
non_clifford = np.matmul(
|
|
3618
|
+
non_clifford = np.matmul(
|
|
3619
|
+
np.array([[1, 0], [0, -1]], np.complex128), non_clifford
|
|
3620
|
+
)
|
|
3278
3621
|
elif op.name == "sx":
|
|
3279
|
-
non_clifford = np.matmul(
|
|
3622
|
+
non_clifford = np.matmul(
|
|
3623
|
+
np.array(
|
|
3624
|
+
[
|
|
3625
|
+
[(1 + 1j) / 2, (1 - 1j) / 2],
|
|
3626
|
+
[(1 - 1j) / 2, (1 + 1j) / 2],
|
|
3627
|
+
],
|
|
3628
|
+
np.complex128,
|
|
3629
|
+
),
|
|
3630
|
+
non_clifford,
|
|
3631
|
+
)
|
|
3280
3632
|
elif op.name == "sxdg":
|
|
3281
|
-
non_clifford = np.matmul(
|
|
3633
|
+
non_clifford = np.matmul(
|
|
3634
|
+
np.array(
|
|
3635
|
+
[
|
|
3636
|
+
[(1 - 1j) / 2, (1 + 1j) / 2],
|
|
3637
|
+
[(1 + 1j) / 2, (1 - 1j) / 2],
|
|
3638
|
+
],
|
|
3639
|
+
np.complex128,
|
|
3640
|
+
),
|
|
3641
|
+
non_clifford,
|
|
3642
|
+
)
|
|
3282
3643
|
elif op.name == "sy":
|
|
3283
|
-
non_clifford = np.matmul(
|
|
3644
|
+
non_clifford = np.matmul(
|
|
3645
|
+
np.array(
|
|
3646
|
+
[
|
|
3647
|
+
[(1 + 1j) / 2, -(1 + 1j) / 2],
|
|
3648
|
+
[(1 + 1j) / 2, (1 + 1j) / 2],
|
|
3649
|
+
],
|
|
3650
|
+
np.complex128,
|
|
3651
|
+
),
|
|
3652
|
+
non_clifford,
|
|
3653
|
+
)
|
|
3284
3654
|
elif op.name == "sydg":
|
|
3285
|
-
non_clifford = np.matmul(
|
|
3655
|
+
non_clifford = np.matmul(
|
|
3656
|
+
np.array(
|
|
3657
|
+
[
|
|
3658
|
+
[(1 - 1j) / 2, (1 - 1j) / 2],
|
|
3659
|
+
[(-1 + 1j) / 2, (1 - 1j) / 2],
|
|
3660
|
+
],
|
|
3661
|
+
np.complex128,
|
|
3662
|
+
),
|
|
3663
|
+
non_clifford,
|
|
3664
|
+
)
|
|
3286
3665
|
elif op.name == "s":
|
|
3287
|
-
non_clifford = np.matmul(
|
|
3666
|
+
non_clifford = np.matmul(
|
|
3667
|
+
np.array([[1, 0], [0, 1j]], np.complex128), non_clifford
|
|
3668
|
+
)
|
|
3288
3669
|
elif op.name == "sdg":
|
|
3289
|
-
non_clifford = np.matmul(
|
|
3670
|
+
non_clifford = np.matmul(
|
|
3671
|
+
np.array([[1, 0], [0, -1j]], np.complex128), non_clifford
|
|
3672
|
+
)
|
|
3290
3673
|
elif op.name == "t":
|
|
3291
|
-
non_clifford = np.matmul(
|
|
3674
|
+
non_clifford = np.matmul(
|
|
3675
|
+
np.array([[1, 0], [0, sqrt_pi]], np.complex128),
|
|
3676
|
+
non_clifford,
|
|
3677
|
+
)
|
|
3292
3678
|
elif op.name == "tdg":
|
|
3293
|
-
non_clifford = np.matmul(
|
|
3679
|
+
non_clifford = np.matmul(
|
|
3680
|
+
np.array([[1, 0], [0, sqrt_ni]], np.complex128),
|
|
3681
|
+
non_clifford,
|
|
3682
|
+
)
|
|
3294
3683
|
else:
|
|
3295
|
-
raise RuntimeError(
|
|
3684
|
+
raise RuntimeError(
|
|
3685
|
+
"Something went wrong while optimizing circuit! (Dropped a single-qubit gate.)"
|
|
3686
|
+
)
|
|
3296
3687
|
|
|
3297
3688
|
del circ.data[j]
|
|
3298
3689
|
continue
|
|
@@ -3308,7 +3699,7 @@ class QrackSimulator:
|
|
|
3308
3699
|
continue
|
|
3309
3700
|
|
|
3310
3701
|
if op.name == "swap":
|
|
3311
|
-
i =
|
|
3702
|
+
i = q2 if i == q1 else q1
|
|
3312
3703
|
|
|
3313
3704
|
if circ.data[j] in passed_swaps:
|
|
3314
3705
|
passed_swaps.remove(circ.data[j])
|
|
@@ -3318,26 +3709,30 @@ class QrackSimulator:
|
|
|
3318
3709
|
passed_swaps.append(circ.data[j])
|
|
3319
3710
|
|
|
3320
3711
|
j += 1
|
|
3321
|
-
continue
|
|
3712
|
+
continue
|
|
3322
3713
|
|
|
3323
|
-
if (q1 == i) and (
|
|
3324
|
-
|
|
3714
|
+
if (q1 == i) and (
|
|
3715
|
+
(op.name == "cx") or (op.name == "cy") or (op.name == "cz")
|
|
3716
|
+
):
|
|
3717
|
+
if np.isclose(np.abs(non_clifford[0][1]), 0) and np.isclose(
|
|
3718
|
+
np.abs(non_clifford[1][0]), 0
|
|
3719
|
+
):
|
|
3325
3720
|
# If we're not buffering anything but phase, the blocking gate has no effect, and we're safe to continue.
|
|
3326
3721
|
del circ.data[j]
|
|
3327
3722
|
continue
|
|
3328
3723
|
|
|
3329
|
-
if
|
|
3724
|
+
if np.isclose(np.abs(non_clifford[0][0]), 0) and np.isclose(
|
|
3725
|
+
np.abs(non_clifford[1][1]), 0
|
|
3726
|
+
):
|
|
3330
3727
|
# If we're buffering full negation (plus phase), the control qubit can be dropped.
|
|
3331
|
-
c = QuantumCircuit(
|
|
3728
|
+
c = QuantumCircuit(circ.qubits)
|
|
3332
3729
|
if op.name == "cx":
|
|
3333
|
-
c.x(
|
|
3730
|
+
c.x(qubits[1])
|
|
3334
3731
|
elif op.name == "cy":
|
|
3335
|
-
c.y(
|
|
3732
|
+
c.y(qubits[1])
|
|
3336
3733
|
else:
|
|
3337
|
-
c.z(
|
|
3338
|
-
|
|
3339
|
-
instr.qubits = (qubits[1],)
|
|
3340
|
-
circ.data[j] = copy.deepcopy(instr)
|
|
3734
|
+
c.z(qubits[1])
|
|
3735
|
+
circ.data[j] = copy.deepcopy(c.data[0])
|
|
3341
3736
|
|
|
3342
3737
|
j += 1
|
|
3343
3738
|
continue
|
|
@@ -3348,11 +3743,9 @@ class QrackSimulator:
|
|
|
3348
3743
|
break
|
|
3349
3744
|
|
|
3350
3745
|
# We're blocked, so we insert our buffer at this place in the circuit definition.
|
|
3351
|
-
c = QuantumCircuit(
|
|
3352
|
-
c.unitary(non_clifford, 0)
|
|
3353
|
-
|
|
3354
|
-
instr.qubits = (qubits[0],)
|
|
3355
|
-
circ.data.insert(j, copy.deepcopy(instr))
|
|
3746
|
+
c = QuantumCircuit(circ.qubits)
|
|
3747
|
+
c.unitary(non_clifford, qubits[0])
|
|
3748
|
+
circ.data.insert(j, copy.deepcopy(c.data[0]))
|
|
3356
3749
|
|
|
3357
3750
|
non_clifford = np.copy(ident)
|
|
3358
3751
|
break
|
|
@@ -3370,40 +3763,104 @@ class QrackSimulator:
|
|
|
3370
3763
|
op = circ.data[j].operation
|
|
3371
3764
|
qubits = circ.data[j].qubits
|
|
3372
3765
|
if len(qubits) > 2:
|
|
3373
|
-
raise RuntimeError(
|
|
3766
|
+
raise RuntimeError(
|
|
3767
|
+
"Something went wrong while optimizing circuit! (Found a gate with 3 or more qubits.)"
|
|
3768
|
+
)
|
|
3374
3769
|
q1 = circ.find_bit(qubits[0])[0]
|
|
3375
3770
|
if (len(qubits) < 2) and (q1 == i):
|
|
3376
3771
|
if op.name == "unitary":
|
|
3377
3772
|
non_clifford = np.matmul(non_clifford, op.params[0])
|
|
3378
3773
|
elif op.name == "rz":
|
|
3379
3774
|
lm = float(op.params[0])
|
|
3380
|
-
non_clifford = np.matmul(
|
|
3775
|
+
non_clifford = np.matmul(
|
|
3776
|
+
non_clifford,
|
|
3777
|
+
[[np.exp(-1j * lm / 2), 0], [0, np.exp(1j * lm / 2)]],
|
|
3778
|
+
)
|
|
3381
3779
|
elif op.name == "h":
|
|
3382
|
-
non_clifford = np.matmul(
|
|
3780
|
+
non_clifford = np.matmul(
|
|
3781
|
+
non_clifford,
|
|
3782
|
+
np.array(
|
|
3783
|
+
[[sqrt1_2, sqrt1_2], [sqrt1_2, -sqrt1_2]], np.complex128
|
|
3784
|
+
),
|
|
3785
|
+
)
|
|
3383
3786
|
elif op.name == "x":
|
|
3384
|
-
non_clifford = np.matmul(
|
|
3787
|
+
non_clifford = np.matmul(
|
|
3788
|
+
non_clifford, np.array([[0, 1], [1, 0]], np.complex128)
|
|
3789
|
+
)
|
|
3385
3790
|
elif op.name == "y":
|
|
3386
|
-
non_clifford = np.matmul(
|
|
3791
|
+
non_clifford = np.matmul(
|
|
3792
|
+
non_clifford, np.array([[0, -1j], [1j, 0]], np.complex128)
|
|
3793
|
+
)
|
|
3387
3794
|
elif op.name == "z":
|
|
3388
|
-
non_clifford = np.matmul(
|
|
3795
|
+
non_clifford = np.matmul(
|
|
3796
|
+
non_clifford, np.array([[1, 0], [0, -1]], np.complex128)
|
|
3797
|
+
)
|
|
3389
3798
|
elif op.name == "sx":
|
|
3390
|
-
non_clifford = np.matmul(
|
|
3799
|
+
non_clifford = np.matmul(
|
|
3800
|
+
non_clifford,
|
|
3801
|
+
np.array(
|
|
3802
|
+
[
|
|
3803
|
+
[(1 + 1j) / 2, (1 - 1j) / 2],
|
|
3804
|
+
[(1 - 1j) / 2, (1 + 1j) / 2],
|
|
3805
|
+
],
|
|
3806
|
+
np.complex128,
|
|
3807
|
+
),
|
|
3808
|
+
)
|
|
3391
3809
|
elif op.name == "sxdg":
|
|
3392
|
-
non_clifford = np.matmul(
|
|
3810
|
+
non_clifford = np.matmul(
|
|
3811
|
+
non_clifford,
|
|
3812
|
+
np.array(
|
|
3813
|
+
[
|
|
3814
|
+
[(1 - 1j) / 2, (1 + 1j) / 2],
|
|
3815
|
+
[(1 + 1j) / 2, (1 - 1j) / 2],
|
|
3816
|
+
],
|
|
3817
|
+
np.complex128,
|
|
3818
|
+
),
|
|
3819
|
+
)
|
|
3393
3820
|
elif op.name == "sy":
|
|
3394
|
-
non_clifford = np.matmul(
|
|
3821
|
+
non_clifford = np.matmul(
|
|
3822
|
+
non_clifford,
|
|
3823
|
+
np.array(
|
|
3824
|
+
[
|
|
3825
|
+
[(1 + 1j) / 2, -(1 + 1j) / 2],
|
|
3826
|
+
[(1 + 1j) / 2, (1 + 1j) / 2],
|
|
3827
|
+
],
|
|
3828
|
+
np.complex128,
|
|
3829
|
+
),
|
|
3830
|
+
)
|
|
3395
3831
|
elif op.name == "sydg":
|
|
3396
|
-
non_clifford = np.matmul(
|
|
3832
|
+
non_clifford = np.matmul(
|
|
3833
|
+
non_clifford,
|
|
3834
|
+
np.array(
|
|
3835
|
+
[
|
|
3836
|
+
[(1 - 1j) / 2, (1 - 1j) / 2],
|
|
3837
|
+
[(-1 + 1j) / 2, (1 - 1j) / 2],
|
|
3838
|
+
],
|
|
3839
|
+
np.complex128,
|
|
3840
|
+
),
|
|
3841
|
+
)
|
|
3397
3842
|
elif op.name == "s":
|
|
3398
|
-
non_clifford = np.matmul(
|
|
3843
|
+
non_clifford = np.matmul(
|
|
3844
|
+
non_clifford, np.array([[1, 0], [0, 1j]], np.complex128)
|
|
3845
|
+
)
|
|
3399
3846
|
elif op.name == "sdg":
|
|
3400
|
-
non_clifford = np.matmul(
|
|
3847
|
+
non_clifford = np.matmul(
|
|
3848
|
+
non_clifford, np.array([[1, 0], [0, -1j]], np.complex128)
|
|
3849
|
+
)
|
|
3401
3850
|
elif op.name == "t":
|
|
3402
|
-
non_clifford = np.matmul(
|
|
3851
|
+
non_clifford = np.matmul(
|
|
3852
|
+
non_clifford,
|
|
3853
|
+
np.array([[1, 0], [0, sqrt_pi]], np.complex128),
|
|
3854
|
+
)
|
|
3403
3855
|
elif op.name == "tdg":
|
|
3404
|
-
non_clifford = np.matmul(
|
|
3856
|
+
non_clifford = np.matmul(
|
|
3857
|
+
non_clifford,
|
|
3858
|
+
np.array([[1, 0], [0, sqrt_ni]], np.complex128),
|
|
3859
|
+
)
|
|
3405
3860
|
else:
|
|
3406
|
-
raise RuntimeError(
|
|
3861
|
+
raise RuntimeError(
|
|
3862
|
+
"Something went wrong while optimizing circuit! (Dropped a single-qubit gate.)"
|
|
3863
|
+
)
|
|
3407
3864
|
|
|
3408
3865
|
del circ.data[j]
|
|
3409
3866
|
j -= 1
|
|
@@ -3420,7 +3877,7 @@ class QrackSimulator:
|
|
|
3420
3877
|
continue
|
|
3421
3878
|
|
|
3422
3879
|
if (op.name == "swap") and (q1 >= width) and (q2 >= width):
|
|
3423
|
-
i =
|
|
3880
|
+
i = q2 if i == q1 else q1
|
|
3424
3881
|
if circ.data[j] in passed_swaps:
|
|
3425
3882
|
passed_swaps.remove(circ.data[j])
|
|
3426
3883
|
del circ.data[j]
|
|
@@ -3430,7 +3887,14 @@ class QrackSimulator:
|
|
|
3430
3887
|
j -= 1
|
|
3431
3888
|
continue
|
|
3432
3889
|
|
|
3433
|
-
if (
|
|
3890
|
+
if (
|
|
3891
|
+
(q1 == i)
|
|
3892
|
+
and ((op.name == "cx") or (op.name == "cy") or (op.name == "cz"))
|
|
3893
|
+
and (
|
|
3894
|
+
np.isclose(np.abs(non_clifford[0][1]), 0)
|
|
3895
|
+
and np.isclose(np.abs(non_clifford[1][0]), 0)
|
|
3896
|
+
)
|
|
3897
|
+
):
|
|
3434
3898
|
# If we're not buffering anything but phase, this commutes with control, and we're safe to continue.
|
|
3435
3899
|
j -= 1
|
|
3436
3900
|
continue
|
|
@@ -3439,21 +3903,18 @@ class QrackSimulator:
|
|
|
3439
3903
|
orig_instr = circ.data[j]
|
|
3440
3904
|
del circ.data[j]
|
|
3441
3905
|
|
|
3442
|
-
h = QuantumCircuit(1)
|
|
3443
|
-
h.h(0)
|
|
3444
|
-
instr = h.data[0]
|
|
3445
|
-
|
|
3446
3906
|
# We're replacing CNOT with CNOT in the opposite direction plus four H gates
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3907
|
+
rep = QuantumCircuit(circ.qubits)
|
|
3908
|
+
rep.h(qubits[0])
|
|
3909
|
+
circ.data.insert(j, copy.deepcopy(rep.data[0]))
|
|
3910
|
+
rep.h(qubits[1])
|
|
3911
|
+
circ.data.insert(j, copy.deepcopy(rep.data[1]))
|
|
3912
|
+
rep.cx(qubits[1], qubits[0])
|
|
3913
|
+
circ.data.insert(j, copy.deepcopy(rep.data[2]))
|
|
3914
|
+
rep.h(qubits[0])
|
|
3915
|
+
circ.data.insert(j, copy.deepcopy(rep.data[3]))
|
|
3916
|
+
rep.h(qubits[1])
|
|
3917
|
+
circ.data.insert(j, copy.deepcopy(rep.data[4]))
|
|
3457
3918
|
|
|
3458
3919
|
j += 4
|
|
3459
3920
|
continue
|
|
@@ -3464,38 +3925,62 @@ class QrackSimulator:
|
|
|
3464
3925
|
break
|
|
3465
3926
|
|
|
3466
3927
|
# We're blocked, so we insert our buffer at this place in the circuit definition.
|
|
3467
|
-
c = QuantumCircuit(
|
|
3468
|
-
c.unitary(non_clifford, 0)
|
|
3469
|
-
|
|
3470
|
-
instr.qubits = (qubits[0],)
|
|
3471
|
-
circ.data.insert(j + 1, copy.deepcopy(instr))
|
|
3928
|
+
c = QuantumCircuit(circ.qubits)
|
|
3929
|
+
c.unitary(non_clifford, qubits[0])
|
|
3930
|
+
circ.data.insert(j + 1, copy.deepcopy(c.data[0]))
|
|
3472
3931
|
|
|
3473
3932
|
break
|
|
3474
3933
|
|
|
3475
3934
|
# Re-injection branch (apply gadget to target)
|
|
3476
|
-
to_inject = np.matmul(
|
|
3935
|
+
to_inject = np.matmul(
|
|
3936
|
+
non_clifford, np.array([[sqrt1_2, sqrt1_2], [sqrt1_2, -sqrt1_2]])
|
|
3937
|
+
)
|
|
3477
3938
|
if np.allclose(to_inject, ident):
|
|
3478
3939
|
# No buffer content to write to circuit definition
|
|
3479
3940
|
del circ.data[j]
|
|
3480
3941
|
j -= 1
|
|
3481
3942
|
continue
|
|
3482
3943
|
|
|
3483
|
-
c = QuantumCircuit(
|
|
3484
|
-
c.unitary(to_inject, 0)
|
|
3485
|
-
|
|
3486
|
-
instr.qubits = (qubits[0],)
|
|
3487
|
-
circ.data[j] = copy.deepcopy(instr)
|
|
3944
|
+
c = QuantumCircuit(circ.qubits)
|
|
3945
|
+
c.unitary(to_inject, qubits[0])
|
|
3946
|
+
circ.data.insert(j, copy.deepcopy(c.data[0]))
|
|
3488
3947
|
j -= 1
|
|
3489
3948
|
|
|
3490
|
-
basis_gates=[
|
|
3949
|
+
basis_gates = [
|
|
3950
|
+
"u",
|
|
3951
|
+
"rz",
|
|
3952
|
+
"h",
|
|
3953
|
+
"x",
|
|
3954
|
+
"y",
|
|
3955
|
+
"z",
|
|
3956
|
+
"sx",
|
|
3957
|
+
"sxdg",
|
|
3958
|
+
"s",
|
|
3959
|
+
"sdg",
|
|
3960
|
+
"t",
|
|
3961
|
+
"tdg",
|
|
3962
|
+
"cx",
|
|
3963
|
+
"cy",
|
|
3964
|
+
"cz",
|
|
3965
|
+
"swap",
|
|
3966
|
+
]
|
|
3491
3967
|
circ = transpile(circ, basis_gates=basis_gates, optimization_level=2)
|
|
3492
3968
|
|
|
3493
|
-
#Eliminate unused ancillae
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3969
|
+
# Eliminate unused ancillae
|
|
3970
|
+
try:
|
|
3971
|
+
qasm = qasm3.dumps(circ)
|
|
3972
|
+
except:
|
|
3973
|
+
qasm = circ.qasm()
|
|
3974
|
+
qasm = qasm.replace(
|
|
3975
|
+
"qreg q[" + str(circ.width()) + "];", "qreg q[" + str(width) + "];"
|
|
3976
|
+
)
|
|
3977
|
+
highest_index = max(
|
|
3978
|
+
[int(x) for x in re.findall(r"\[(.*?)\]", qasm) if x.isdigit()]
|
|
3979
|
+
)
|
|
3497
3980
|
if highest_index != width:
|
|
3498
|
-
qasm = qasm.replace(
|
|
3981
|
+
qasm = qasm.replace(
|
|
3982
|
+
"qreg q[" + str(width) + "];", "qreg q[" + str(highest_index) + "];"
|
|
3983
|
+
)
|
|
3499
3984
|
|
|
3500
3985
|
orig_circ = circ
|
|
3501
3986
|
try:
|
|
@@ -3561,11 +4046,11 @@ class QrackSimulator:
|
|
|
3561
4046
|
def _apply_op(self, operation):
|
|
3562
4047
|
name = operation.name
|
|
3563
4048
|
|
|
3564
|
-
if (name ==
|
|
4049
|
+
if (name == "id") or (name == "barrier"):
|
|
3565
4050
|
# Skip measurement logic
|
|
3566
4051
|
return
|
|
3567
4052
|
|
|
3568
|
-
conditional = getattr(operation,
|
|
4053
|
+
conditional = getattr(operation, "conditional", None)
|
|
3569
4054
|
if isinstance(conditional, int):
|
|
3570
4055
|
conditional_bit_set = (self._classical_register >> conditional) & 1
|
|
3571
4056
|
if not conditional_bit_set:
|
|
@@ -3580,154 +4065,191 @@ class QrackSimulator:
|
|
|
3580
4065
|
if value != int(conditional.val, 16):
|
|
3581
4066
|
return
|
|
3582
4067
|
|
|
3583
|
-
if (name ==
|
|
3584
|
-
self._sim.u(operation.qubits[0], 0, 0, float(operation.params[0]))
|
|
3585
|
-
elif name ==
|
|
4068
|
+
if (name == "u1") or (name == "p"):
|
|
4069
|
+
self._sim.u(operation.qubits[0]._index, 0, 0, float(operation.params[0]))
|
|
4070
|
+
elif name == "u2":
|
|
3586
4071
|
self._sim.u(
|
|
3587
|
-
operation.qubits[0],
|
|
4072
|
+
operation.qubits[0]._index,
|
|
3588
4073
|
math.pi / 2,
|
|
3589
4074
|
float(operation.params[0]),
|
|
3590
4075
|
float(operation.params[1]),
|
|
3591
4076
|
)
|
|
3592
|
-
elif (name ==
|
|
4077
|
+
elif (name == "u3") or (name == "u"):
|
|
3593
4078
|
self._sim.u(
|
|
3594
|
-
operation.qubits[0],
|
|
4079
|
+
operation.qubits[0]._index,
|
|
3595
4080
|
float(operation.params[0]),
|
|
3596
4081
|
float(operation.params[1]),
|
|
3597
4082
|
float(operation.params[2]),
|
|
3598
4083
|
)
|
|
3599
|
-
elif (name ==
|
|
3600
|
-
self._sim.mtrx(operation.params[0].flatten(), operation.qubits[0])
|
|
3601
|
-
elif name ==
|
|
4084
|
+
elif (name == "unitary") and (len(operation.qubits) == 1):
|
|
4085
|
+
self._sim.mtrx(operation.params[0].flatten(), operation.qubits[0]._index)
|
|
4086
|
+
elif name == "r":
|
|
3602
4087
|
self._sim.u(
|
|
3603
|
-
operation.qubits[0],
|
|
4088
|
+
operation.qubits[0]._index,
|
|
3604
4089
|
float(operation.params[0]),
|
|
3605
4090
|
float(operation.params[1]) - math.pi / 2,
|
|
3606
4091
|
(-1 * float(operation.params[1])) + math.pi / 2,
|
|
3607
4092
|
)
|
|
3608
|
-
elif name ==
|
|
3609
|
-
self._sim.r(
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
elif name ==
|
|
3613
|
-
self._sim.r(
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
elif name ==
|
|
3617
|
-
self._sim.
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
elif name ==
|
|
3621
|
-
self._sim.
|
|
3622
|
-
elif name ==
|
|
3623
|
-
self._sim.
|
|
3624
|
-
elif name ==
|
|
3625
|
-
self._sim.
|
|
3626
|
-
elif name ==
|
|
4093
|
+
elif name == "rx":
|
|
4094
|
+
self._sim.r(
|
|
4095
|
+
Pauli.PauliX, float(operation.params[0]), operation.qubits[0]._index
|
|
4096
|
+
)
|
|
4097
|
+
elif name == "ry":
|
|
4098
|
+
self._sim.r(
|
|
4099
|
+
Pauli.PauliY, float(operation.params[0]), operation.qubits[0]._index
|
|
4100
|
+
)
|
|
4101
|
+
elif name == "rz":
|
|
4102
|
+
self._sim.r(
|
|
4103
|
+
Pauli.PauliZ, float(operation.params[0]), operation.qubits[0]._index
|
|
4104
|
+
)
|
|
4105
|
+
elif name == "h":
|
|
4106
|
+
self._sim.h(operation.qubits[0]._index)
|
|
4107
|
+
elif name == "x":
|
|
4108
|
+
self._sim.x(operation.qubits[0]._index)
|
|
4109
|
+
elif name == "y":
|
|
4110
|
+
self._sim.y(operation.qubits[0]._index)
|
|
4111
|
+
elif name == "z":
|
|
4112
|
+
self._sim.z(operation.qubits[0]._index)
|
|
4113
|
+
elif name == "s":
|
|
4114
|
+
self._sim.s(operation.qubits[0]._index)
|
|
4115
|
+
elif name == "sdg":
|
|
4116
|
+
self._sim.adjs(operation.qubits[0]._index)
|
|
4117
|
+
elif name == "sx":
|
|
3627
4118
|
self._sim.mtrx(
|
|
3628
4119
|
[(1 + 1j) / 2, (1 - 1j) / 2, (1 - 1j) / 2, (1 + 1j) / 2],
|
|
3629
|
-
operation.qubits[0],
|
|
4120
|
+
operation.qubits[0]._index,
|
|
3630
4121
|
)
|
|
3631
|
-
elif name ==
|
|
4122
|
+
elif name == "sxdg":
|
|
3632
4123
|
self._sim.mtrx(
|
|
3633
4124
|
[(1 - 1j) / 2, (1 + 1j) / 2, (1 + 1j) / 2, (1 - 1j) / 2],
|
|
3634
|
-
operation.qubits[0],
|
|
4125
|
+
operation.qubits[0]._index,
|
|
3635
4126
|
)
|
|
3636
|
-
elif name ==
|
|
3637
|
-
self._sim.t(operation.qubits[0])
|
|
3638
|
-
elif name ==
|
|
3639
|
-
self._sim.adjt(operation.qubits[0])
|
|
3640
|
-
elif name ==
|
|
4127
|
+
elif name == "t":
|
|
4128
|
+
self._sim.t(operation.qubits[0]._index)
|
|
4129
|
+
elif name == "tdg":
|
|
4130
|
+
self._sim.adjt(operation.qubits[0]._index)
|
|
4131
|
+
elif name == "cu1":
|
|
3641
4132
|
self._sim.mcu(
|
|
3642
|
-
operation.qubits[0:1]
|
|
4133
|
+
[q._index for q in operation.qubits[0:1]],
|
|
4134
|
+
operation.qubits[1]._index,
|
|
4135
|
+
0,
|
|
4136
|
+
0,
|
|
4137
|
+
float(operation.params[0]),
|
|
3643
4138
|
)
|
|
3644
|
-
elif name ==
|
|
4139
|
+
elif name == "cu2":
|
|
3645
4140
|
self._sim.mcu(
|
|
3646
|
-
operation.qubits[0:1],
|
|
3647
|
-
operation.qubits[1],
|
|
4141
|
+
[q._index for q in operation.qubits[0:1]],
|
|
4142
|
+
operation.qubits[1]._index,
|
|
3648
4143
|
math.pi / 2,
|
|
3649
4144
|
float(operation.params[0]),
|
|
3650
4145
|
float(operation.params[1]),
|
|
3651
4146
|
)
|
|
3652
|
-
elif (name ==
|
|
4147
|
+
elif (name == "cu3") or (name == "cu"):
|
|
3653
4148
|
self._sim.mcu(
|
|
3654
|
-
operation.qubits[0:1],
|
|
3655
|
-
operation.qubits[1],
|
|
4149
|
+
[q._index for q in operation.qubits[0:1]],
|
|
4150
|
+
operation.qubits[1]._index,
|
|
3656
4151
|
float(operation.params[0]),
|
|
3657
4152
|
float(operation.params[1]),
|
|
3658
4153
|
float(operation.params[2]),
|
|
3659
4154
|
)
|
|
3660
|
-
elif name ==
|
|
3661
|
-
self._sim.mcx(
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
elif name ==
|
|
3665
|
-
self._sim.
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
elif name ==
|
|
4155
|
+
elif name == "cx":
|
|
4156
|
+
self._sim.mcx(
|
|
4157
|
+
[q._index for q in operation.qubits[0:1]], operation.qubits[1]._index
|
|
4158
|
+
)
|
|
4159
|
+
elif name == "cy":
|
|
4160
|
+
self._sim.mcy(
|
|
4161
|
+
[q._index for q in operation.qubits[0:1]], operation.qubits[1]._index
|
|
4162
|
+
)
|
|
4163
|
+
elif name == "cz":
|
|
4164
|
+
self._sim.mcz(
|
|
4165
|
+
[q._index for q in operation.qubits[0:1]], operation.qubits[1]._index
|
|
4166
|
+
)
|
|
4167
|
+
elif name == "ch":
|
|
4168
|
+
self._sim.mch(
|
|
4169
|
+
[q._index for q in operation.qubits[0:1]], operation.qubits[1]._index
|
|
4170
|
+
)
|
|
4171
|
+
elif name == "cp":
|
|
3669
4172
|
self._sim.mcmtrx(
|
|
3670
|
-
operation.qubits[0:1],
|
|
4173
|
+
[q._index for q in operation.qubits[0:1]],
|
|
3671
4174
|
[
|
|
3672
4175
|
1,
|
|
3673
4176
|
0,
|
|
3674
4177
|
0,
|
|
3675
|
-
math.cos(float(operation.params[0]))
|
|
4178
|
+
math.cos(float(operation.params[0]))
|
|
4179
|
+
+ 1j * math.sin(float(operation.params[0])),
|
|
3676
4180
|
],
|
|
3677
|
-
operation.qubits[1],
|
|
4181
|
+
operation.qubits[1]._index,
|
|
3678
4182
|
)
|
|
3679
|
-
elif name ==
|
|
4183
|
+
elif name == "csx":
|
|
3680
4184
|
self._sim.mcmtrx(
|
|
3681
|
-
operation.qubits[0:1],
|
|
4185
|
+
[q._index for q in operation.qubits[0:1]],
|
|
3682
4186
|
[(1 + 1j) / 2, (1 - 1j) / 2, (1 - 1j) / 2, (1 + 1j) / 2],
|
|
3683
|
-
operation.qubits[1],
|
|
4187
|
+
operation.qubits[1]._index,
|
|
3684
4188
|
)
|
|
3685
|
-
elif name ==
|
|
4189
|
+
elif name == "csxdg":
|
|
3686
4190
|
self._sim.mcmtrx(
|
|
3687
|
-
operation.qubits[0:1],
|
|
4191
|
+
[q._index for q in operation.qubits[0:1]],
|
|
3688
4192
|
[(1 - 1j) / 2, (1 + 1j) / 2, (1 + 1j) / 2, (1 - 1j) / 2],
|
|
3689
|
-
operation.qubits[1],
|
|
3690
|
-
)
|
|
3691
|
-
elif name ==
|
|
3692
|
-
self._sim.mcx(
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
self._sim.mcx(operation.qubits[
|
|
3696
|
-
elif name ==
|
|
3697
|
-
self._sim.
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
elif name ==
|
|
3701
|
-
self._sim.
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
elif name ==
|
|
3705
|
-
self._sim.mcz(
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
elif name ==
|
|
3709
|
-
self._sim.
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
elif name ==
|
|
4193
|
+
operation.qubits[1]._index,
|
|
4194
|
+
)
|
|
4195
|
+
elif name == "dcx":
|
|
4196
|
+
self._sim.mcx(
|
|
4197
|
+
[q._index for q in operation.qubits[0:1]], operation.qubits[1]._index
|
|
4198
|
+
)
|
|
4199
|
+
self._sim.mcx(operation.qubits[1:2]._index, operation.qubits[0]._index)
|
|
4200
|
+
elif name == "ccx":
|
|
4201
|
+
self._sim.mcx(
|
|
4202
|
+
[q._index for q in operation.qubits[0:2]], operation.qubits[2]._index
|
|
4203
|
+
)
|
|
4204
|
+
elif name == "ccy":
|
|
4205
|
+
self._sim.mcy(
|
|
4206
|
+
[q._index for q in operation.qubits[0:2]], operation.qubits[2]._index
|
|
4207
|
+
)
|
|
4208
|
+
elif name == "ccz":
|
|
4209
|
+
self._sim.mcz(
|
|
4210
|
+
[q._index for q in operation.qubits[0:2]], operation.qubits[2]._index
|
|
4211
|
+
)
|
|
4212
|
+
elif name == "mcx":
|
|
4213
|
+
self._sim.mcx(
|
|
4214
|
+
[q._index for q in operation.qubits[0:-1]], operation.qubits[-1]._index
|
|
4215
|
+
)
|
|
4216
|
+
elif name == "mcy":
|
|
4217
|
+
self._sim.mcy(
|
|
4218
|
+
[q._index for q in operation.qubits[0:-1]], operation.qubits[-1]._index
|
|
4219
|
+
)
|
|
4220
|
+
elif name == "mcz":
|
|
4221
|
+
self._sim.mcz(
|
|
4222
|
+
[q._index for q in operation.qubits[0:-1]], operation.qubits[-1]._index
|
|
4223
|
+
)
|
|
4224
|
+
elif name == "swap":
|
|
4225
|
+
self._sim.swap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
4226
|
+
elif name == "iswap":
|
|
4227
|
+
self._sim.iswap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
4228
|
+
elif name == "iswap_dg":
|
|
4229
|
+
self._sim.adjiswap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
4230
|
+
elif name == "cswap":
|
|
3713
4231
|
self._sim.cswap(
|
|
3714
|
-
operation.qubits[0:1]
|
|
4232
|
+
[q._index for q in operation.qubits[0:1]],
|
|
4233
|
+
operation.qubits[1]._index,
|
|
4234
|
+
operation.qubits[2]._index,
|
|
3715
4235
|
)
|
|
3716
|
-
elif name ==
|
|
4236
|
+
elif name == "mcswap":
|
|
3717
4237
|
self._sim.cswap(
|
|
3718
|
-
|
|
4238
|
+
[q._index for q in operation.qubits[:-2]],
|
|
4239
|
+
operation.qubits[-2]._index,
|
|
4240
|
+
operation.qubits[-1]._index,
|
|
3719
4241
|
)
|
|
3720
|
-
elif name ==
|
|
4242
|
+
elif name == "reset":
|
|
3721
4243
|
qubits = operation.qubits
|
|
3722
4244
|
for qubit in qubits:
|
|
3723
|
-
if self._sim.m(qubit):
|
|
3724
|
-
self._sim.x(qubit)
|
|
3725
|
-
elif name ==
|
|
4245
|
+
if self._sim.m(qubit._index):
|
|
4246
|
+
self._sim.x(qubit._index)
|
|
4247
|
+
elif name == "measure":
|
|
3726
4248
|
qubits = operation.qubits
|
|
3727
|
-
clbits = operation.
|
|
4249
|
+
clbits = operation.clbits
|
|
3728
4250
|
cregbits = (
|
|
3729
4251
|
operation.register
|
|
3730
|
-
if hasattr(operation,
|
|
4252
|
+
if hasattr(operation, "register")
|
|
3731
4253
|
else len(operation.qubits) * [-1]
|
|
3732
4254
|
)
|
|
3733
4255
|
|
|
@@ -3737,7 +4259,7 @@ class QrackSimulator:
|
|
|
3737
4259
|
|
|
3738
4260
|
if not self._sample_measure:
|
|
3739
4261
|
for index in range(len(qubits)):
|
|
3740
|
-
qubit_outcome = self._sim.m(qubits[index])
|
|
4262
|
+
qubit_outcome = self._sim.m(qubits[index]._index)
|
|
3741
4263
|
|
|
3742
4264
|
clbit = clbits[index]
|
|
3743
4265
|
clmask = 1 << clbit
|
|
@@ -3754,30 +4276,30 @@ class QrackSimulator:
|
|
|
3754
4276
|
self._classical_register & (~regbit)
|
|
3755
4277
|
) | (qubit_outcome << cregbit)
|
|
3756
4278
|
|
|
3757
|
-
elif name ==
|
|
4279
|
+
elif name == "bfunc":
|
|
3758
4280
|
mask = int(operation.mask, 16)
|
|
3759
4281
|
relation = operation.relation
|
|
3760
4282
|
val = int(operation.val, 16)
|
|
3761
4283
|
|
|
3762
4284
|
cregbit = operation.register
|
|
3763
|
-
cmembit = operation.memory if hasattr(operation,
|
|
4285
|
+
cmembit = operation.memory if hasattr(operation, "memory") else None
|
|
3764
4286
|
|
|
3765
4287
|
compared = (self._classical_register & mask) - val
|
|
3766
4288
|
|
|
3767
|
-
if relation ==
|
|
4289
|
+
if relation == "==":
|
|
3768
4290
|
outcome = compared == 0
|
|
3769
|
-
elif relation ==
|
|
4291
|
+
elif relation == "!=":
|
|
3770
4292
|
outcome = compared != 0
|
|
3771
|
-
elif relation ==
|
|
4293
|
+
elif relation == "<":
|
|
3772
4294
|
outcome = compared < 0
|
|
3773
|
-
elif relation ==
|
|
4295
|
+
elif relation == "<=":
|
|
3774
4296
|
outcome = compared <= 0
|
|
3775
|
-
elif relation ==
|
|
4297
|
+
elif relation == ">":
|
|
3776
4298
|
outcome = compared > 0
|
|
3777
|
-
elif relation ==
|
|
4299
|
+
elif relation == ">=":
|
|
3778
4300
|
outcome = compared >= 0
|
|
3779
4301
|
else:
|
|
3780
|
-
raise QrackError(
|
|
4302
|
+
raise QrackError("Invalid boolean function relation.")
|
|
3781
4303
|
|
|
3782
4304
|
# Store outcome in register and optionally memory slot
|
|
3783
4305
|
regbit = 1 << cregbit
|
|
@@ -3811,28 +4333,30 @@ class QrackSimulator:
|
|
|
3811
4333
|
measure_clbit = [clbit for clbit in sample_clbits]
|
|
3812
4334
|
|
|
3813
4335
|
# Sample and convert to bit-strings
|
|
3814
|
-
data = []
|
|
3815
4336
|
if num_samples == 1:
|
|
3816
4337
|
sample = self._sim.m_all()
|
|
3817
4338
|
result = 0
|
|
3818
4339
|
for index in range(len(measure_qubit)):
|
|
3819
|
-
qubit = measure_qubit[index]
|
|
4340
|
+
qubit = measure_qubit[index]._index
|
|
3820
4341
|
qubit_outcome = (sample >> qubit) & 1
|
|
3821
4342
|
result |= qubit_outcome << index
|
|
3822
4343
|
measure_results = [result]
|
|
3823
4344
|
else:
|
|
3824
|
-
measure_results = self._sim.measure_shots(
|
|
4345
|
+
measure_results = self._sim.measure_shots(
|
|
4346
|
+
[q._index for q in measure_qubit], num_samples
|
|
4347
|
+
)
|
|
3825
4348
|
|
|
4349
|
+
data = []
|
|
3826
4350
|
for sample in measure_results:
|
|
3827
4351
|
for index in range(len(measure_qubit)):
|
|
3828
4352
|
qubit_outcome = (sample >> index) & 1
|
|
3829
|
-
clbit = measure_clbit[index]
|
|
4353
|
+
clbit = measure_clbit[index]._index
|
|
3830
4354
|
clmask = 1 << clbit
|
|
3831
4355
|
self._classical_memory = (self._classical_memory & (~clmask)) | (
|
|
3832
4356
|
qubit_outcome << clbit
|
|
3833
4357
|
)
|
|
3834
4358
|
|
|
3835
|
-
data.append(
|
|
4359
|
+
data.append(bin(self._classical_memory)[2:].zfill(self.num_qubits()))
|
|
3836
4360
|
|
|
3837
4361
|
return data
|
|
3838
4362
|
|
|
@@ -3842,12 +4366,9 @@ class QrackSimulator:
|
|
|
3842
4366
|
"Before trying to run_qiskit_circuit() with QrackSimulator, you must install Qiskit!"
|
|
3843
4367
|
)
|
|
3844
4368
|
|
|
3845
|
-
if isinstance(experiment, QuantumCircuit):
|
|
3846
|
-
experiment = convert_qiskit_circuit_to_qasm_experiment(experiment)
|
|
3847
|
-
|
|
3848
4369
|
instructions = []
|
|
3849
|
-
if isinstance(experiment,
|
|
3850
|
-
instructions = experiment.
|
|
4370
|
+
if isinstance(experiment, QuantumCircuit):
|
|
4371
|
+
instructions = experiment.data
|
|
3851
4372
|
else:
|
|
3852
4373
|
raise RuntimeError('Unrecognized "run_input" argument specified for run().')
|
|
3853
4374
|
|
|
@@ -3857,7 +4378,6 @@ class QrackSimulator:
|
|
|
3857
4378
|
self._sample_cregbits = []
|
|
3858
4379
|
self._sample_measure = True
|
|
3859
4380
|
_data = []
|
|
3860
|
-
shotsPerLoop = self._shots
|
|
3861
4381
|
shotLoopMax = 1
|
|
3862
4382
|
|
|
3863
4383
|
is_initializing = True
|
|
@@ -3866,21 +4386,21 @@ class QrackSimulator:
|
|
|
3866
4386
|
for opcount in range(len(instructions)):
|
|
3867
4387
|
operation = instructions[opcount]
|
|
3868
4388
|
|
|
3869
|
-
if operation.name ==
|
|
4389
|
+
if operation.name == "id" or operation.name == "barrier":
|
|
3870
4390
|
continue
|
|
3871
4391
|
|
|
3872
4392
|
if is_initializing and (
|
|
3873
|
-
(operation.name ==
|
|
4393
|
+
(operation.name == "measure") or (operation.name == "reset")
|
|
3874
4394
|
):
|
|
3875
4395
|
continue
|
|
3876
4396
|
|
|
3877
4397
|
is_initializing = False
|
|
3878
4398
|
|
|
3879
|
-
if (operation.name ==
|
|
4399
|
+
if (operation.name == "measure") or (operation.name == "reset"):
|
|
3880
4400
|
if boundary_start == -1:
|
|
3881
4401
|
boundary_start = opcount
|
|
3882
4402
|
|
|
3883
|
-
if (boundary_start != -1) and (operation.name !=
|
|
4403
|
+
if (boundary_start != -1) and (operation.name != "measure"):
|
|
3884
4404
|
shotsPerLoop = 1
|
|
3885
4405
|
shotLoopMax = self._shots
|
|
3886
4406
|
self._sample_measure = False
|
|
@@ -3923,7 +4443,7 @@ class QrackSimulator:
|
|
|
3923
4443
|
self._apply_op(operation)
|
|
3924
4444
|
|
|
3925
4445
|
if not self._sample_measure and (len(self._sample_qubits) > 0):
|
|
3926
|
-
_data += [
|
|
4446
|
+
_data += [bin(self._classical_memory)[2:].zfill(self.num_qubits())]
|
|
3927
4447
|
self._sample_qubits = []
|
|
3928
4448
|
self._sample_clbits = []
|
|
3929
4449
|
self._sample_cregbits = []
|
|
@@ -3936,3 +4456,43 @@ class QrackSimulator:
|
|
|
3936
4456
|
del self._sim
|
|
3937
4457
|
|
|
3938
4458
|
return _data
|
|
4459
|
+
|
|
4460
|
+
def get_qiskit_basis_gates():
|
|
4461
|
+
return [
|
|
4462
|
+
"id",
|
|
4463
|
+
"u",
|
|
4464
|
+
"u1",
|
|
4465
|
+
"u2",
|
|
4466
|
+
"u3",
|
|
4467
|
+
"r",
|
|
4468
|
+
"rx",
|
|
4469
|
+
"ry",
|
|
4470
|
+
"rz",
|
|
4471
|
+
"h",
|
|
4472
|
+
"x",
|
|
4473
|
+
"y",
|
|
4474
|
+
"z",
|
|
4475
|
+
"s",
|
|
4476
|
+
"sdg",
|
|
4477
|
+
"sx",
|
|
4478
|
+
"sxdg",
|
|
4479
|
+
"p",
|
|
4480
|
+
"t",
|
|
4481
|
+
"tdg",
|
|
4482
|
+
"cu",
|
|
4483
|
+
"cu1",
|
|
4484
|
+
"cu3",
|
|
4485
|
+
"cx",
|
|
4486
|
+
"cy",
|
|
4487
|
+
"cz",
|
|
4488
|
+
"ch",
|
|
4489
|
+
"cp",
|
|
4490
|
+
"csx",
|
|
4491
|
+
"ccx",
|
|
4492
|
+
"ccz",
|
|
4493
|
+
"swap",
|
|
4494
|
+
"iswap",
|
|
4495
|
+
"cswap",
|
|
4496
|
+
"reset",
|
|
4497
|
+
"measure",
|
|
4498
|
+
]
|