pyqrack-cpu-complex128 2.22.4__tar.gz → 2.24.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_cpu_complex128-2.22.4/pyqrack_cpu_complex128.egg-info → pyqrack_cpu_complex128-2.24.0}/PKG-INFO +1 -1
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_ace_backend.py +309 -15
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_simulator.py +3 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0/pyqrack_cpu_complex128.egg-info}/PKG-INFO +1 -1
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/setup.py +1 -1
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/LICENSE +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/MANIFEST.in +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/Makefile +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/README.md +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyproject.toml +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/__init__.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/pauli.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_near_clifford_qec_backend.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack_cpu_complex128.egg-info/SOURCES.txt +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack_cpu_complex128.egg-info/dependency_links.txt +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack_cpu_complex128.egg-info/not-zip-safe +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack_cpu_complex128.egg-info/requires.txt +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack_cpu_complex128.egg-info/top_level.txt +0 -0
- {pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/setup.cfg +0 -0
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_ace_backend.py
RENAMED
|
@@ -18,6 +18,17 @@ try:
|
|
|
18
18
|
from qiskit.circuit.quantumcircuit import QuantumCircuit
|
|
19
19
|
from qiskit.compiler import transpile
|
|
20
20
|
from qiskit.quantum_info.operators.symplectic.clifford import Clifford
|
|
21
|
+
from qiskit.transpiler import Target, InstructionProperties
|
|
22
|
+
from qiskit.circuit import Parameter
|
|
23
|
+
from qiskit.circuit.library import (
|
|
24
|
+
IGate, UGate, U3Gate, U2Gate, U1Gate,
|
|
25
|
+
XGate, YGate, ZGate, HGate,
|
|
26
|
+
RXGate, RYGate, RZGate,
|
|
27
|
+
SGate, SdgGate, TGate, TdgGate,
|
|
28
|
+
CXGate, CYGate, CZGate, SwapGate, iSwapGate,
|
|
29
|
+
CCXGate, CCZGate, CSwapGate,
|
|
30
|
+
Measure, Reset,
|
|
31
|
+
)
|
|
21
32
|
except ImportError:
|
|
22
33
|
_IS_QISKIT_AVAILABLE = False
|
|
23
34
|
|
|
@@ -803,7 +814,6 @@ class QrackAceBackend:
|
|
|
803
814
|
|
|
804
815
|
sim.mtrx([m00, m01, m10, m11], q)
|
|
805
816
|
|
|
806
|
-
@staticmethod
|
|
807
817
|
def _get_lhv_bloch_angles(sim):
|
|
808
818
|
z = sim.bloch[2]
|
|
809
819
|
x = sim.bloch[0]
|
|
@@ -812,7 +822,6 @@ class QrackAceBackend:
|
|
|
812
822
|
azimuth = math.atan2(y, x)
|
|
813
823
|
return azimuth, inclination
|
|
814
824
|
|
|
815
|
-
@staticmethod
|
|
816
825
|
def _rotate_lhv_to_bloch(sim, delta_azimuth, delta_inclination):
|
|
817
826
|
cosA = math.cos(delta_azimuth)
|
|
818
827
|
sinA = math.sin(delta_azimuth)
|
|
@@ -1741,7 +1750,6 @@ class QrackAceBackend:
|
|
|
1741
1750
|
# logical value moved, the same way a repetition code's
|
|
1742
1751
|
# decoded value doesn't change just because one physical
|
|
1743
1752
|
# bit needed fixing.
|
|
1744
|
-
is_flipped = False
|
|
1745
1753
|
n_flipped = sum(1 for b in bits if b)
|
|
1746
1754
|
if (n_flipped << 1) > len(ancs):
|
|
1747
1755
|
is_flipped = True
|
|
@@ -1971,46 +1979,174 @@ class QrackAceBackend:
|
|
|
1971
1979
|
self._cpauli(lq1, lq2, True, Pauli.PauliZ)
|
|
1972
1980
|
|
|
1973
1981
|
def mcx(self, lq1, lq2):
|
|
1974
|
-
if len(lq1)
|
|
1982
|
+
if len(lq1) == 1:
|
|
1983
|
+
self.cx(lq1[0], lq2)
|
|
1984
|
+
return
|
|
1985
|
+
|
|
1986
|
+
hq = self._unpack(lq2)
|
|
1987
|
+
if len(hq) > 1:
|
|
1975
1988
|
raise RuntimeError(
|
|
1976
1989
|
"QrackAceBackend.mcx() is provided for syntax convenience and only supports 1 control qubit!"
|
|
1977
1990
|
)
|
|
1978
|
-
|
|
1991
|
+
s = hq[0][0]
|
|
1992
|
+
t = hq[0][1]
|
|
1993
|
+
c = []
|
|
1994
|
+
for l in lq1:
|
|
1995
|
+
hq = self._unpack(l)
|
|
1996
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
1997
|
+
raise RuntimeError(
|
|
1998
|
+
"QrackAceBackend.mcx() is provided for syntax convenience and only supports 1 control qubit!"
|
|
1999
|
+
)
|
|
2000
|
+
c.append(hq[0][1])
|
|
2001
|
+
|
|
2002
|
+
# We happen to be able to accommodate this:
|
|
2003
|
+
self.sim[s].mcx(c, t)
|
|
1979
2004
|
|
|
1980
2005
|
def mcy(self, lq1, lq2):
|
|
1981
|
-
if len(lq1)
|
|
2006
|
+
if len(lq1) == 1:
|
|
2007
|
+
self.cy(lq1[0], lq2)
|
|
2008
|
+
return
|
|
2009
|
+
|
|
2010
|
+
hq = self._unpack(lq2)
|
|
2011
|
+
if len(hq) > 1:
|
|
1982
2012
|
raise RuntimeError(
|
|
1983
2013
|
"QrackAceBackend.mcy() is provided for syntax convenience and only supports 1 control qubit!"
|
|
1984
2014
|
)
|
|
1985
|
-
|
|
2015
|
+
s = hq[0][0]
|
|
2016
|
+
t = hq[0][1]
|
|
2017
|
+
c = []
|
|
2018
|
+
for l in lq1:
|
|
2019
|
+
hq = self._unpack(l)
|
|
2020
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2021
|
+
raise RuntimeError(
|
|
2022
|
+
"QrackAceBackend.mcy() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2023
|
+
)
|
|
2024
|
+
c.append(hq[0][1])
|
|
2025
|
+
|
|
2026
|
+
# We happen to be able to accommodate this:
|
|
2027
|
+
self.sim[s].mcy(c, t)
|
|
1986
2028
|
|
|
1987
2029
|
def mcz(self, lq1, lq2):
|
|
1988
|
-
if len(lq1)
|
|
2030
|
+
if len(lq1) == 1:
|
|
2031
|
+
self.cz(lq1[0], lq2)
|
|
2032
|
+
return
|
|
2033
|
+
|
|
2034
|
+
hq = self._unpack(lq2)
|
|
2035
|
+
if len(hq) > 1:
|
|
1989
2036
|
raise RuntimeError(
|
|
1990
2037
|
"QrackAceBackend.mcz() is provided for syntax convenience and only supports 1 control qubit!"
|
|
1991
2038
|
)
|
|
1992
|
-
|
|
2039
|
+
s = hq[0][0]
|
|
2040
|
+
t = hq[0][1]
|
|
2041
|
+
c = []
|
|
2042
|
+
for l in lq1:
|
|
2043
|
+
hq = self._unpack(l)
|
|
2044
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2045
|
+
raise RuntimeError(
|
|
2046
|
+
"QrackAceBackend.mcz() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2047
|
+
)
|
|
2048
|
+
c.append(hq[0][1])
|
|
2049
|
+
|
|
2050
|
+
# We happen to be able to accommodate this:
|
|
2051
|
+
self.sim[s].mcz(c, t)
|
|
1993
2052
|
|
|
1994
2053
|
def macx(self, lq1, lq2):
|
|
1995
|
-
if len(lq1)
|
|
2054
|
+
if len(lq1) == 1:
|
|
2055
|
+
self.acx(lq1[0], lq2)
|
|
2056
|
+
return
|
|
2057
|
+
|
|
2058
|
+
hq = self._unpack(lq2)
|
|
2059
|
+
if len(hq) > 1:
|
|
1996
2060
|
raise RuntimeError(
|
|
1997
2061
|
"QrackAceBackend.macx() is provided for syntax convenience and only supports 1 control qubit!"
|
|
1998
2062
|
)
|
|
1999
|
-
|
|
2063
|
+
s = hq[0][0]
|
|
2064
|
+
t = hq[0][1]
|
|
2065
|
+
c = []
|
|
2066
|
+
for l in lq1:
|
|
2067
|
+
hq = self._unpack(l)
|
|
2068
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2069
|
+
raise RuntimeError(
|
|
2070
|
+
"QrackAceBackend.macx() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2071
|
+
)
|
|
2072
|
+
c.append(hq[0][1])
|
|
2073
|
+
|
|
2074
|
+
# We happen to be able to accommodate this:
|
|
2075
|
+
self.sim[s].macx(c, t)
|
|
2000
2076
|
|
|
2001
2077
|
def macy(self, lq1, lq2):
|
|
2002
|
-
if len(lq1)
|
|
2078
|
+
if len(lq1) == 1:
|
|
2079
|
+
self.acy(lq1[0], lq2)
|
|
2080
|
+
return
|
|
2081
|
+
|
|
2082
|
+
hq = self._unpack(lq2)
|
|
2083
|
+
if len(hq) > 1:
|
|
2003
2084
|
raise RuntimeError(
|
|
2004
2085
|
"QrackAceBackend.macy() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2005
2086
|
)
|
|
2006
|
-
|
|
2087
|
+
s = hq[0][0]
|
|
2088
|
+
t = hq[0][1]
|
|
2089
|
+
c = []
|
|
2090
|
+
for l in lq1:
|
|
2091
|
+
hq = self._unpack(l)
|
|
2092
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2093
|
+
raise RuntimeError(
|
|
2094
|
+
"QrackAceBackend.macy() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2095
|
+
)
|
|
2096
|
+
c.append(hq[0][1])
|
|
2097
|
+
|
|
2098
|
+
# We happen to be able to accommodate this:
|
|
2099
|
+
self.sim[s].macy(c, t)
|
|
2007
2100
|
|
|
2008
2101
|
def macz(self, lq1, lq2):
|
|
2009
|
-
if len(lq1)
|
|
2102
|
+
if len(lq1) == 1:
|
|
2103
|
+
self.acz(lq1[0], lq2)
|
|
2104
|
+
return
|
|
2105
|
+
|
|
2106
|
+
hq = self._unpack(lq2)
|
|
2107
|
+
if len(hq) > 1:
|
|
2010
2108
|
raise RuntimeError(
|
|
2011
2109
|
"QrackAceBackend.macz() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2012
2110
|
)
|
|
2013
|
-
|
|
2111
|
+
s = hq[0][0]
|
|
2112
|
+
t = hq[0][1]
|
|
2113
|
+
c = []
|
|
2114
|
+
for l in lq1:
|
|
2115
|
+
hq = self._unpack(l)
|
|
2116
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2117
|
+
raise RuntimeError(
|
|
2118
|
+
"QrackAceBackend.macz() is provided for syntax convenience and only supports 1 control qubit!"
|
|
2119
|
+
)
|
|
2120
|
+
c.append(hq[0][1])
|
|
2121
|
+
|
|
2122
|
+
# We happen to be able to accommodate this:
|
|
2123
|
+
self.sim[s].macz(c, t)
|
|
2124
|
+
|
|
2125
|
+
def cswap(self, lq1, lq2, lq3):
|
|
2126
|
+
hq = self._unpack(lq2)
|
|
2127
|
+
if len(hq) > 1:
|
|
2128
|
+
raise RuntimeError(
|
|
2129
|
+
"QrackAceBackend.cswap() is provided for syntax convenience and only supports intra-patch!"
|
|
2130
|
+
)
|
|
2131
|
+
s = hq[0][0]
|
|
2132
|
+
t1 = hq[0][1]
|
|
2133
|
+
hq = self._unpack(lq3)
|
|
2134
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2135
|
+
raise RuntimeError(
|
|
2136
|
+
"QrackAceBackend.cswap() is provided for syntax convenience and only supports intra-patch!"
|
|
2137
|
+
)
|
|
2138
|
+
t2 = hq[0][1]
|
|
2139
|
+
c = []
|
|
2140
|
+
for l in lq1:
|
|
2141
|
+
hq = self._unpack(l)
|
|
2142
|
+
if (len(hq) > 1) or (s != hq[0][0]):
|
|
2143
|
+
raise RuntimeError(
|
|
2144
|
+
"QrackAceBackend.cswap() is provided for syntax convenience and only supports intra-patch!"
|
|
2145
|
+
)
|
|
2146
|
+
c.append(hq[0][1])
|
|
2147
|
+
|
|
2148
|
+
# We happen to be able to accommodate this:
|
|
2149
|
+
self.sim[s].cswap(c, t1, t2)
|
|
2014
2150
|
|
|
2015
2151
|
def swap(self, lq1, lq2):
|
|
2016
2152
|
hq1 = self._unpack(lq1)
|
|
@@ -2436,11 +2572,23 @@ class QrackAceBackend:
|
|
|
2436
2572
|
self._sim.cy(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
2437
2573
|
elif name == "cz":
|
|
2438
2574
|
self._sim.cz(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
2575
|
+
elif name == "ccx":
|
|
2576
|
+
self._sim.mcx([operation.qubits[0]._index, operation.qubits[1]._index], operation.qubits[2]._index)
|
|
2577
|
+
elif name == "ccz":
|
|
2578
|
+
self._sim.mcz([operation.qubits[0]._index, operation.qubits[1]._index], operation.qubits[2]._index)
|
|
2579
|
+
elif name == "mcx":
|
|
2580
|
+
self._sim.mcx([q._index for q in operation.qubits[:-1]], operation.qubits[-1]._index)
|
|
2581
|
+
elif name == "mcy":
|
|
2582
|
+
self._sim.mcy([q._index for q in operation.qubits[:-1]], operation.qubits[-1]._index)
|
|
2583
|
+
elif name == "mcz":
|
|
2584
|
+
self._sim.mcz([q._index for q in operation.qubits[:-1]], operation.qubits[-1]._index)
|
|
2439
2585
|
elif name == "dcx":
|
|
2440
2586
|
self._sim.mcx(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
2441
2587
|
self._sim.mcx(operation.qubits[1]._index, operation.qubits[0]._index)
|
|
2442
2588
|
elif name == "swap":
|
|
2443
2589
|
self._sim.swap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
2590
|
+
elif name == "cswap":
|
|
2591
|
+
self._sim.cswap([q._index for q in operation.qubits[:-2]], operation.qubits[-2]._index, operation.qubits[-1]._index)
|
|
2444
2592
|
elif name == "iswap":
|
|
2445
2593
|
self._sim.iswap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
2446
2594
|
elif name == "iswap_dg":
|
|
@@ -2680,7 +2828,10 @@ class QrackAceBackend:
|
|
|
2680
2828
|
"cx",
|
|
2681
2829
|
"cy",
|
|
2682
2830
|
"cz",
|
|
2831
|
+
"ccx",
|
|
2832
|
+
"ccz",
|
|
2683
2833
|
"swap",
|
|
2834
|
+
"cswap",
|
|
2684
2835
|
"iswap",
|
|
2685
2836
|
"reset",
|
|
2686
2837
|
"measure",
|
|
@@ -2723,6 +2874,149 @@ class QrackAceBackend:
|
|
|
2723
2874
|
|
|
2724
2875
|
return self._coupling_map
|
|
2725
2876
|
|
|
2877
|
+
# Moved here from AceQasmSimulator (qiskit-qrack-provider), so a
|
|
2878
|
+
# QrackAceBackend can be transpiled against directly with plain Qiskit,
|
|
2879
|
+
# without needing the separate Qiskit BackendV2 wrapper at all. The
|
|
2880
|
+
# Qiskit backend now calls this instead of duplicating the logic.
|
|
2881
|
+
#
|
|
2882
|
+
# One correction made in the move: the original 1-qubit "boundary
|
|
2883
|
+
# penalty hint" set was approximated from get_logical_coupling_map()
|
|
2884
|
+
# (any qubit appearing in ANY coupling pair) -- but that map includes
|
|
2885
|
+
# ordinary bulk-bulk pairs within the same patch too, so it actually
|
|
2886
|
+
# flagged nearly every qubit as "boundary." Here, with direct access to
|
|
2887
|
+
# self._unpack(), the real criterion (len(self._unpack(q)) > 1) is used
|
|
2888
|
+
# instead.
|
|
2889
|
+
def get_target(self, description=None, error_2q=0.5):
|
|
2890
|
+
"""Build a qiskit Target describing this backend's gate set and
|
|
2891
|
+
connectivity, so it can be used with qiskit.transpile() directly --
|
|
2892
|
+
with or without the separate Qiskit BackendV2 wrapper.
|
|
2893
|
+
|
|
2894
|
+
IMPORTANT, verified directly rather than assumed: qiskit's
|
|
2895
|
+
transpile() does NOT reliably enforce the qubit-tuple-level
|
|
2896
|
+
InstructionProperties restrictions declared here for 3+-qubit gates
|
|
2897
|
+
(ccx/ccz/cswap), at any optimization_level that doesn't outright
|
|
2898
|
+
crash. Confirmed: the default optimization_level raises
|
|
2899
|
+
TranspilerError("target contains multi-qubit operations") on ANY
|
|
2900
|
+
Target containing 3+-qubit gates, valid placement or not (Qiskit's
|
|
2901
|
+
default SabreLayout routing pass doesn't support them at all).
|
|
2902
|
+
optimization_level=0 or 1 avoid that crash, but ALSO transpiled a
|
|
2903
|
+
deliberately-invalid (boundary-qubit) ccx placement successfully in
|
|
2904
|
+
testing -- i.e., they don't validate 3-qubit placements against the
|
|
2905
|
+
target either, they just don't crash on them.
|
|
2906
|
+
The Target's 3-qubit entries are still meaningful as a description
|
|
2907
|
+
of what's actually valid (useful for introspection, or for a
|
|
2908
|
+
transpiler pass that does check placements properly), but they are
|
|
2909
|
+
NOT currently a transpile-time safety guarantee the way the 2-qubit
|
|
2910
|
+
coupling map is. The actual, reliable enforcement is the runtime
|
|
2911
|
+
RuntimeError in mcx()/mcy()/mcz()/cswap() themselves, which fire
|
|
2912
|
+
correctly regardless of what the transpiler allowed through.
|
|
2913
|
+
"""
|
|
2914
|
+
if not _IS_QISKIT_AVAILABLE:
|
|
2915
|
+
raise RuntimeError(
|
|
2916
|
+
"QrackAceBackend.get_target() requires Qiskit to be installed!"
|
|
2917
|
+
)
|
|
2918
|
+
|
|
2919
|
+
n = self.num_qubits()
|
|
2920
|
+
tgt = Target(num_qubits=n, description=description)
|
|
2921
|
+
|
|
2922
|
+
# Parameters for parameterised gates
|
|
2923
|
+
theta = Parameter("theta")
|
|
2924
|
+
phi = Parameter("phi")
|
|
2925
|
+
lam = Parameter("lam")
|
|
2926
|
+
|
|
2927
|
+
# --- single-qubit gates: all qubits ---
|
|
2928
|
+
boundary = {q for q in range(n) if len(self._unpack(q)) > 1}
|
|
2929
|
+
|
|
2930
|
+
def _1q_props():
|
|
2931
|
+
return {
|
|
2932
|
+
(q,): InstructionProperties()
|
|
2933
|
+
for q in range(n)
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2936
|
+
tgt.add_instruction(IGate(), _1q_props())
|
|
2937
|
+
tgt.add_instruction(UGate(theta, phi, lam), _1q_props())
|
|
2938
|
+
tgt.add_instruction(U3Gate(theta, phi, lam), _1q_props())
|
|
2939
|
+
tgt.add_instruction(U2Gate(phi, lam), _1q_props())
|
|
2940
|
+
tgt.add_instruction(U1Gate(lam), _1q_props())
|
|
2941
|
+
tgt.add_instruction(RXGate(theta), _1q_props())
|
|
2942
|
+
tgt.add_instruction(RYGate(theta), _1q_props())
|
|
2943
|
+
tgt.add_instruction(RZGate(theta), _1q_props())
|
|
2944
|
+
tgt.add_instruction(HGate(), _1q_props())
|
|
2945
|
+
tgt.add_instruction(XGate(), _1q_props())
|
|
2946
|
+
tgt.add_instruction(YGate(), _1q_props())
|
|
2947
|
+
tgt.add_instruction(ZGate(), _1q_props())
|
|
2948
|
+
tgt.add_instruction(SGate(), _1q_props())
|
|
2949
|
+
tgt.add_instruction(SdgGate(), _1q_props())
|
|
2950
|
+
tgt.add_instruction(TGate(), _1q_props())
|
|
2951
|
+
tgt.add_instruction(TdgGate(), _1q_props())
|
|
2952
|
+
|
|
2953
|
+
# --- two-qubit gates: coupled pairs (includes boundary-crossing
|
|
2954
|
+
# pairs -- those are supported, via the noisy-coupler mechanism) ---
|
|
2955
|
+
bulk = []
|
|
2956
|
+
for q in range(n):
|
|
2957
|
+
hq = self._unpack(q)
|
|
2958
|
+
if len(hq) == 1:
|
|
2959
|
+
bulk.append(q)
|
|
2960
|
+
coupling_map = self.get_logical_coupling_map()
|
|
2961
|
+
if coupling_map:
|
|
2962
|
+
pair_props = {
|
|
2963
|
+
(a, b): InstructionProperties() if (a in bulk) and (b in bulk) else InstructionProperties(error=error_2q) for a, b in coupling_map
|
|
2964
|
+
}
|
|
2965
|
+
else:
|
|
2966
|
+
pair_props = {
|
|
2967
|
+
(a, b): InstructionProperties()
|
|
2968
|
+
for a in range(n)
|
|
2969
|
+
for b in range(n)
|
|
2970
|
+
if a != b
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
tgt.add_instruction(CXGate(), pair_props)
|
|
2974
|
+
tgt.add_instruction(CYGate(), pair_props)
|
|
2975
|
+
tgt.add_instruction(CZGate(), pair_props)
|
|
2976
|
+
tgt.add_instruction(SwapGate(), pair_props)
|
|
2977
|
+
tgt.add_instruction(iSwapGate(), pair_props)
|
|
2978
|
+
|
|
2979
|
+
# --- 3-qubit gates: intra-patch, all-bulk triples only ---
|
|
2980
|
+
# ccx/ccz/cswap (and, by extension, mcx/mcy/mcz beyond a single
|
|
2981
|
+
# control) are only valid when every involved qubit is bulk and
|
|
2982
|
+
# shares the same patch -- see mcx()/cswap() above, which raise
|
|
2983
|
+
# otherwise.
|
|
2984
|
+
#
|
|
2985
|
+
# CCXGate/CCZGate and CSwapGate do NOT share a qubit-ordering
|
|
2986
|
+
# convention (verified directly against their gate definitions):
|
|
2987
|
+
# CCXGate puts its target on qubit index 2, with 0-1 as the two
|
|
2988
|
+
# (interchangeable) controls; CSwapGate puts its control on qubit
|
|
2989
|
+
# index 0, with 1-2 as the (interchangeable) swapped pair. They
|
|
2990
|
+
# need separately-ordered InstructionProperties dicts.
|
|
2991
|
+
bulk_by_patch = {}
|
|
2992
|
+
for q in range(n):
|
|
2993
|
+
hq = self._unpack(q)
|
|
2994
|
+
if len(hq) == 1:
|
|
2995
|
+
bulk_by_patch.setdefault(hq[0][0], []).append(q)
|
|
2996
|
+
|
|
2997
|
+
ccx_props = {}
|
|
2998
|
+
cswap_props = {}
|
|
2999
|
+
for qubits_here in bulk_by_patch.values():
|
|
3000
|
+
for pivot in qubits_here:
|
|
3001
|
+
others = [q for q in qubits_here if q != pivot]
|
|
3002
|
+
for i in range(len(others)):
|
|
3003
|
+
for j in range(len(others)):
|
|
3004
|
+
if i == j:
|
|
3005
|
+
continue
|
|
3006
|
+
ccx_props[(others[i], others[j], pivot)] = InstructionProperties()
|
|
3007
|
+
cswap_props[(pivot, others[i], others[j])] = InstructionProperties()
|
|
3008
|
+
if ccx_props:
|
|
3009
|
+
tgt.add_instruction(CCXGate(), ccx_props)
|
|
3010
|
+
tgt.add_instruction(CCZGate(), ccx_props)
|
|
3011
|
+
if cswap_props:
|
|
3012
|
+
tgt.add_instruction(CSwapGate(), cswap_props)
|
|
3013
|
+
|
|
3014
|
+
# --- measure / reset: all qubits ---
|
|
3015
|
+
tgt.add_instruction(Measure(), {(q,): InstructionProperties() for q in range(n)})
|
|
3016
|
+
tgt.add_instruction(Reset(), {(q,): InstructionProperties() for q in range(n)})
|
|
3017
|
+
|
|
3018
|
+
return tgt
|
|
3019
|
+
|
|
2726
3020
|
# Designed by Dan, Elara (ChatGPT), and (Anthropic) Claude:
|
|
2727
3021
|
def create_noise_model(self, x=0.5, y=0.5):
|
|
2728
3022
|
if not _IS_QISKIT_AER_AVAILABLE:
|
|
@@ -4311,6 +4311,8 @@ class QrackSimulator:
|
|
|
4311
4311
|
self._sim.mcz([q._index for q in operation.qubits[0:-1]], operation.qubits[-1]._index)
|
|
4312
4312
|
elif name == "swap":
|
|
4313
4313
|
self._sim.swap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
4314
|
+
elif name == "cswap":
|
|
4315
|
+
self._sim.cswap([q._index for q in operation.qubits[:-2]], operation.qubits[-2]._index, operation.qubits[-1]._index)
|
|
4314
4316
|
elif name == "iswap":
|
|
4315
4317
|
self._sim.iswap(operation.qubits[0]._index, operation.qubits[1]._index)
|
|
4316
4318
|
elif name == "iswap_dg":
|
|
@@ -4569,6 +4571,7 @@ class QrackSimulator:
|
|
|
4569
4571
|
"ccx",
|
|
4570
4572
|
"ccz",
|
|
4571
4573
|
"swap",
|
|
4574
|
+
"cswap",
|
|
4572
4575
|
"iswap",
|
|
4573
4576
|
"cswap",
|
|
4574
4577
|
"reset",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/neuron_activation_fn.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_neuron_torch_layer.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_system/__init__.py
RENAMED
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/qrack_system/qrack_system.py
RENAMED
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/quimb_circuit_type.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/stats/load_quantized_data.py
RENAMED
|
File without changes
|
{pyqrack_cpu_complex128-2.22.4 → pyqrack_cpu_complex128-2.24.0}/pyqrack/stats/quantize_by_range.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|