pyqrack-cuda 1.43.0__tar.gz → 1.44.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_cuda-1.43.0 → pyqrack_cuda-1.44.0}/Makefile +1 -1
- {pyqrack_cuda-1.43.0/pyqrack_cuda.egg-info → pyqrack_cuda-1.44.0}/PKG-INFO +1 -1
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/__init__.py +1 -0
- pyqrack_cuda-1.44.0/pyqrack/qrack_ace_backend.py +261 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack_cuda.egg-info/SOURCES.txt +1 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/setup.py +1 -1
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/LICENSE +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/MANIFEST.in +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/README.md +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyproject.toml +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/pauli.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack_cuda.egg-info/requires.txt +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/pyqrack_cuda.egg-info/top_level.txt +0 -0
- {pyqrack_cuda-1.43.0 → pyqrack_cuda-1.44.0}/setup.cfg +0 -0
@@ -18,7 +18,7 @@ help:
|
|
18
18
|
build-deps:
|
19
19
|
ifneq ($(OS),Windows_NT)
|
20
20
|
ifeq ($(QRACK_PRESENT),)
|
21
|
-
git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout
|
21
|
+
git clone https://github.com/unitaryfund/qrack.git; cd qrack; git checkout 63806a65a9ebf64e57e4a44bcc68237d2947568a; cd ..
|
22
22
|
endif
|
23
23
|
mkdir -p qrack/build
|
24
24
|
ifeq ($(UNAME_S),Linux)
|
@@ -6,6 +6,7 @@
|
|
6
6
|
from .pauli import Pauli
|
7
7
|
from .neuron_activation_fn import NeuronActivationFn
|
8
8
|
from .quimb_circuit_type import QuimbCircuitType
|
9
|
+
from .qrack_ace_backend import QrackAceBackend
|
9
10
|
from .qrack_circuit import QrackCircuit
|
10
11
|
from .qrack_neuron import QrackNeuron
|
11
12
|
from .qrack_neuron_torch_layer import QrackTorchNeuron, QrackNeuronFunction, QrackNeuronTorchLayer
|
@@ -0,0 +1,261 @@
|
|
1
|
+
# (C) Daniel Strano and the Qrack contributors 2017-2025. All rights reserved.
|
2
|
+
#
|
3
|
+
# Use of this source code is governed by an MIT-style license that can be
|
4
|
+
# found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
5
|
+
import math
|
6
|
+
import random
|
7
|
+
import sys
|
8
|
+
import time
|
9
|
+
|
10
|
+
from .qrack_simulator import QrackSimulator
|
11
|
+
from .pauli import Pauli
|
12
|
+
|
13
|
+
|
14
|
+
class QrackAceBackend:
|
15
|
+
"""A back end for elided quantum error correction
|
16
|
+
|
17
|
+
This back end uses elided repetition code on a nearest-neighbor topology to emulate
|
18
|
+
a utility-scale superconducting chip quantum computer in very little memory.
|
19
|
+
|
20
|
+
The backend was originally designed assuming a 2D qubit grid like 2019 Sycamore.
|
21
|
+
However, it quickly became apparent that users can basically design their own
|
22
|
+
connectivity topologies, without breaking the concept. (Not all will work equally well.)
|
23
|
+
|
24
|
+
Attributes:
|
25
|
+
sim(QrackSimulator): Corresponding simulator.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
qubit_count=-1,
|
31
|
+
):
|
32
|
+
self.sim = QrackSimulator(3 * qubit_count)
|
33
|
+
|
34
|
+
|
35
|
+
def _ct_pair_prob(self, q1, q2):
|
36
|
+
p1 = self.sim.prob(q1)
|
37
|
+
p2 = self.sim.prob(q2)
|
38
|
+
|
39
|
+
if p1 < p2:
|
40
|
+
return p2, q1
|
41
|
+
|
42
|
+
return p1, q2
|
43
|
+
|
44
|
+
|
45
|
+
def _cz_shadow(self, q1, q2):
|
46
|
+
prob_max, t = self._ct_pair_prob(q1, q2)
|
47
|
+
if prob_max > 0.5:
|
48
|
+
self.sim.z(t)
|
49
|
+
|
50
|
+
|
51
|
+
def _anti_cz_shadow(self, q1, q2):
|
52
|
+
self.sim.x(q1)
|
53
|
+
self._cz_shadow(q1, q2)
|
54
|
+
self.sim.x(q1)
|
55
|
+
|
56
|
+
|
57
|
+
def _cx_shadow(self, c, t):
|
58
|
+
self.sim.h(t)
|
59
|
+
self._cz_shadow(c, t)
|
60
|
+
self.sim.h(t)
|
61
|
+
|
62
|
+
|
63
|
+
def _anti_cx_shadow(self, c, t):
|
64
|
+
self.sim.x(t)
|
65
|
+
self._cx_shadow(c, t)
|
66
|
+
self.sim.x(t)
|
67
|
+
|
68
|
+
|
69
|
+
def _cy_shadow(self, c, t):
|
70
|
+
self.sim.adjs(t)
|
71
|
+
self._cx_shadow(c, t)
|
72
|
+
self.sim.s(t)
|
73
|
+
|
74
|
+
|
75
|
+
def _anti_cy_shadow(self, c, t):
|
76
|
+
self.sim.x(t)
|
77
|
+
self._cy_shadow(c, t)
|
78
|
+
self.sim.x(t)
|
79
|
+
|
80
|
+
|
81
|
+
def _unpack(self, lq, reverse = False):
|
82
|
+
return [3 * lq + 2, 3 * lq + 1, 3 * lq] if reverse else [3 * lq, 3 * lq + 1, 3 * lq + 2]
|
83
|
+
|
84
|
+
|
85
|
+
def _encode(self, hq, reverse = False):
|
86
|
+
if reverse:
|
87
|
+
self._cx_shadow(hq[0], hq[1])
|
88
|
+
self.sim.mcx([hq[1]], hq[2])
|
89
|
+
else:
|
90
|
+
self.sim.mcx([hq[0]], hq[1])
|
91
|
+
self._cx_shadow(hq[1], hq[2])
|
92
|
+
|
93
|
+
|
94
|
+
def _decode(self, hq, reverse = False):
|
95
|
+
if reverse:
|
96
|
+
self.sim.mcx([hq[1]], hq[2])
|
97
|
+
self._cx_shadow(hq[0], hq[1])
|
98
|
+
else:
|
99
|
+
self._cx_shadow(hq[1], hq[2])
|
100
|
+
self.sim.mcx([hq[0]], hq[1])
|
101
|
+
|
102
|
+
|
103
|
+
def u(self, th, ph, lm, lq):
|
104
|
+
hq = self._unpack(lq)
|
105
|
+
self._decode(hq)
|
106
|
+
self.sim.u(hq[0], th, ph, lm)
|
107
|
+
self._encode(hq)
|
108
|
+
|
109
|
+
|
110
|
+
def s(self, lq):
|
111
|
+
hq = self._unpack(lq)
|
112
|
+
self._decode(hq)
|
113
|
+
self.sim.s(hq[0])
|
114
|
+
self._encode(hq)
|
115
|
+
|
116
|
+
|
117
|
+
def adjs(self, lq):
|
118
|
+
hq = self._unpack(lq)
|
119
|
+
self._decode(hq)
|
120
|
+
self.sim.adjs(hq[0])
|
121
|
+
self._encode(hq)
|
122
|
+
|
123
|
+
|
124
|
+
def x(self, lq):
|
125
|
+
hq = self._unpack(lq)
|
126
|
+
self._decode(hq)
|
127
|
+
self.sim.x(hq[0])
|
128
|
+
self._encode(hq)
|
129
|
+
|
130
|
+
|
131
|
+
def y(self, lq):
|
132
|
+
hq = self._unpack(lq)
|
133
|
+
self._decode(hq)
|
134
|
+
self.sim.y(hq[0])
|
135
|
+
self._encode(hq)
|
136
|
+
|
137
|
+
|
138
|
+
def z(self, lq):
|
139
|
+
hq = self._unpack(lq)
|
140
|
+
self._decode(hq)
|
141
|
+
self.sim.z(hq[0])
|
142
|
+
self._encode(hq)
|
143
|
+
|
144
|
+
|
145
|
+
def h(self, lq):
|
146
|
+
hq = self._unpack(lq)
|
147
|
+
self._decode(hq)
|
148
|
+
self.sim.h(hq[0])
|
149
|
+
self._encode(hq)
|
150
|
+
|
151
|
+
|
152
|
+
def t(self, lq):
|
153
|
+
hq = self._unpack(lq)
|
154
|
+
self._decode(hq)
|
155
|
+
self.sim.t(hq[0])
|
156
|
+
self._encode(hq)
|
157
|
+
|
158
|
+
|
159
|
+
def adjt(self, lq):
|
160
|
+
hq = self._unpack(lq)
|
161
|
+
self._decode(hq)
|
162
|
+
self.sim.adjt(hq[0])
|
163
|
+
self._encode(hq)
|
164
|
+
|
165
|
+
|
166
|
+
def _cpauli(self, lq1, lq2, anti, pauli):
|
167
|
+
gate = None
|
168
|
+
if pauli == Pauli.PauliX:
|
169
|
+
gate = self.sim.macx if anti else self.sim.mcx
|
170
|
+
elif pauli == Pauli.PauliY:
|
171
|
+
gate = self.sim.macy if anti else self.sim.mcy
|
172
|
+
elif pauli == Pauli.PauliZ:
|
173
|
+
gate = self.sim.macz if anti else self.sim.mcz
|
174
|
+
else:
|
175
|
+
return
|
176
|
+
|
177
|
+
if (lq2 == (lq1 + 1)) or (lq1 == (lq2 + 1)):
|
178
|
+
hq1 = self._unpack(lq1, True)
|
179
|
+
hq2 = self._unpack(lq2, False)
|
180
|
+
self._decode(hq1, True)
|
181
|
+
self._decode(hq2, False)
|
182
|
+
gate([hq1[0]], hq2[0])
|
183
|
+
self._encode(hq2, False)
|
184
|
+
self._encode(hq1, True)
|
185
|
+
else:
|
186
|
+
hq1 = self._unpack(lq1)
|
187
|
+
hq2 = self._unpack(lq2)
|
188
|
+
gate([hq1[0]], hq2[0])
|
189
|
+
gate([hq1[1]], hq2[1])
|
190
|
+
gate([hq1[2]], hq2[2])
|
191
|
+
|
192
|
+
|
193
|
+
def cx(self, lq1, lq2):
|
194
|
+
self._cpauli(lq1, lq2, False, Pauli.PauliX)
|
195
|
+
|
196
|
+
|
197
|
+
def cy(self, lq1, lq2):
|
198
|
+
self._cpauli(lq1, lq2, False, Pauli.PauliY)
|
199
|
+
|
200
|
+
|
201
|
+
def cz(self, lq1, lq2):
|
202
|
+
self._cpauli(lq1, lq2, False, Pauli.PauliZ)
|
203
|
+
|
204
|
+
|
205
|
+
def acx(self, lq1, lq2):
|
206
|
+
self._cpauli(lq1, lq2, True, Pauli.PauliX)
|
207
|
+
|
208
|
+
|
209
|
+
def acy(self, lq1, lq2):
|
210
|
+
self._cpauli(lq1, lq2, True, Pauli.PauliY)
|
211
|
+
|
212
|
+
|
213
|
+
def acz(self, lq1, lq2):
|
214
|
+
self._cpauli(lq1, lq2, True, Pauli.PauliZ)
|
215
|
+
|
216
|
+
|
217
|
+
def swap(self, lq1, lq2):
|
218
|
+
self.cx(lq1, lq2)
|
219
|
+
self.cx(lq2, lq1)
|
220
|
+
self.cx(lq1, lq2)
|
221
|
+
|
222
|
+
|
223
|
+
def iswap(self, lq1, lq2):
|
224
|
+
self.swap(lq1, lq2)
|
225
|
+
self.cz(lq1, lq2)
|
226
|
+
self.s(lq1)
|
227
|
+
self.s(lq2)
|
228
|
+
|
229
|
+
|
230
|
+
def adjiswap(self, lq1, lq2):
|
231
|
+
self.adjs(lq2)
|
232
|
+
self.adjs(lq1)
|
233
|
+
self.cz(lq1, lq2)
|
234
|
+
self.swap(lq1, lq2)
|
235
|
+
|
236
|
+
|
237
|
+
def m(self, lq):
|
238
|
+
hq = self._unpack(lq)
|
239
|
+
syndrome = 0
|
240
|
+
bits = []
|
241
|
+
for q in hq:
|
242
|
+
bits.append(self.sim.m(q))
|
243
|
+
if bits[-1]:
|
244
|
+
syndrome += 1
|
245
|
+
result = True if (syndrome > 1) else False
|
246
|
+
for i in range(len(hq)):
|
247
|
+
if bits[i] != result:
|
248
|
+
self.sim.x(hq[i])
|
249
|
+
|
250
|
+
return result
|
251
|
+
|
252
|
+
|
253
|
+
def m_all(self):
|
254
|
+
result = 0
|
255
|
+
for lq in range(self.sim.num_qubits() // 3):
|
256
|
+
result <<= 1
|
257
|
+
if self.m(lq):
|
258
|
+
result |= 1
|
259
|
+
|
260
|
+
return result
|
261
|
+
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|