pyqrack-cuda 1.44.12__tar.gz → 1.44.14__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.44.12/pyqrack_cuda.egg-info → pyqrack_cuda-1.44.14}/PKG-INFO +1 -1
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_ace_backend.py +68 -1
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14/pyqrack_cuda.egg-info}/PKG-INFO +1 -1
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/setup.py +1 -1
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/LICENSE +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/MANIFEST.in +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/Makefile +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/README.md +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyproject.toml +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/__init__.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/neuron_activation_fn.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/pauli.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_circuit.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_neuron.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_neuron_torch_layer.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_simulator.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_stabilizer.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_system/__init__.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/qrack_system/qrack_system.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/quimb_circuit_type.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/stats/__init__.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/stats/load_quantized_data.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack/stats/quantize_by_range.py +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack_cuda.egg-info/SOURCES.txt +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack_cuda.egg-info/dependency_links.txt +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack_cuda.egg-info/not-zip-safe +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack_cuda.egg-info/requires.txt +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/pyqrack_cuda.egg-info/top_level.txt +0 -0
- {pyqrack_cuda-1.44.12 → pyqrack_cuda-1.44.14}/setup.cfg +0 -0
@@ -39,7 +39,8 @@ class QrackAceBackend:
|
|
39
39
|
"""
|
40
40
|
|
41
41
|
def __init__(self, qubit_count=-1, alternating_codes=True, toClone=None):
|
42
|
-
self.sim = toClone.sim.clone() if toClone else QrackSimulator(3 * qubit_count
|
42
|
+
self.sim = toClone.sim.clone() if toClone else QrackSimulator(3 * qubit_count + 1)
|
43
|
+
self._ancilla = 3 * qubit_count
|
43
44
|
self._factor_width(qubit_count)
|
44
45
|
self.alternating_codes = alternating_codes
|
45
46
|
|
@@ -118,66 +119,129 @@ class QrackAceBackend:
|
|
118
119
|
self._cx_shadow(hq[1], hq[2])
|
119
120
|
self.sim.mcx([hq[0]], hq[1])
|
120
121
|
|
122
|
+
def _correct(self, lq):
|
123
|
+
# We can't use true syndrome-based error correction,
|
124
|
+
# because one of the qubits in the code is separated.
|
125
|
+
# However, we can get pretty close!
|
126
|
+
hq = self._unpack(lq)
|
127
|
+
shots = 1024
|
128
|
+
samples = self.sim.measure_shots(hq, shots)
|
129
|
+
syndrome = [0, 0, 0]
|
130
|
+
for sample in samples:
|
131
|
+
match sample:
|
132
|
+
case 1:
|
133
|
+
syndrome[0] += 1
|
134
|
+
case 2:
|
135
|
+
syndrome[1] += 1
|
136
|
+
case 4:
|
137
|
+
syndrome[2] += 1
|
138
|
+
case 6:
|
139
|
+
syndrome[0] += 1
|
140
|
+
case 5:
|
141
|
+
syndrome[1] += 1
|
142
|
+
case 3:
|
143
|
+
syndrome[2] += 1
|
144
|
+
|
145
|
+
row = (hq[0] // 3) // self.row_length
|
146
|
+
even_row = not (row & 1)
|
147
|
+
single_bit = 2 if (not self.alternating_codes or even_row) else 0
|
148
|
+
|
149
|
+
max_syndrome = max(syndrome)
|
150
|
+
error_bit = syndrome.index(max_syndrome)
|
151
|
+
if (2 * max_syndrome) >= shots:
|
152
|
+
# There is an error.
|
153
|
+
if error_bit == single_bit:
|
154
|
+
# The stand-alone bit carries the error.
|
155
|
+
self.sim.x(hq[error_bit])
|
156
|
+
else:
|
157
|
+
# The coherent bits carry the error.
|
158
|
+
# Form their syndrome.
|
159
|
+
self.sim.mcx([hq[1]], self._ancilla)
|
160
|
+
self.sim.mcx([hq[2]], self._ancilla)
|
161
|
+
# Force the syndrome pathological
|
162
|
+
self.sim.force_m(self._ancilla, True)
|
163
|
+
# Reset the ancilla.
|
164
|
+
self.sim.x(self._ancilla)
|
165
|
+
# Correct the bit flip.
|
166
|
+
self.sim.x(hq[error_bit])
|
167
|
+
elif error_bit != single_bit:
|
168
|
+
# There is no error.
|
169
|
+
# Form the syndrome of the coherent bits.
|
170
|
+
self.sim.mcx([hq[1]], self._ancilla)
|
171
|
+
self.sim.mcx([hq[2]], self._ancilla)
|
172
|
+
# Force the syndrome non-pathological.
|
173
|
+
self.sim.force_m(self._ancilla, False)
|
174
|
+
|
121
175
|
|
122
176
|
def u(self, th, ph, lm, lq):
|
123
177
|
hq = self._unpack(lq)
|
124
178
|
self._decode(hq)
|
125
179
|
self.sim.u(hq[0], th, ph, lm)
|
126
180
|
self._encode(hq)
|
181
|
+
self._correct(lq)
|
127
182
|
|
128
183
|
def r(self, p, th, lq):
|
129
184
|
hq = self._unpack(lq)
|
130
185
|
self._decode(hq)
|
131
186
|
self.sim.r(p, th, hq[0])
|
132
187
|
self._encode(hq)
|
188
|
+
self._correct(lq)
|
133
189
|
|
134
190
|
def s(self, lq):
|
135
191
|
hq = self._unpack(lq)
|
136
192
|
self._decode(hq)
|
137
193
|
self.sim.s(hq[0])
|
138
194
|
self._encode(hq)
|
195
|
+
self._correct(lq)
|
139
196
|
|
140
197
|
def adjs(self, lq):
|
141
198
|
hq = self._unpack(lq)
|
142
199
|
self._decode(hq)
|
143
200
|
self.sim.adjs(hq[0])
|
144
201
|
self._encode(hq)
|
202
|
+
self._correct(lq)
|
145
203
|
|
146
204
|
def x(self, lq):
|
147
205
|
hq = self._unpack(lq)
|
148
206
|
self._decode(hq)
|
149
207
|
self.sim.x(hq[0])
|
150
208
|
self._encode(hq)
|
209
|
+
self._correct(lq)
|
151
210
|
|
152
211
|
def y(self, lq):
|
153
212
|
hq = self._unpack(lq)
|
154
213
|
self._decode(hq)
|
155
214
|
self.sim.y(hq[0])
|
156
215
|
self._encode(hq)
|
216
|
+
self._correct(lq)
|
157
217
|
|
158
218
|
def z(self, lq):
|
159
219
|
hq = self._unpack(lq)
|
160
220
|
self._decode(hq)
|
161
221
|
self.sim.z(hq[0])
|
162
222
|
self._encode(hq)
|
223
|
+
self._correct(lq)
|
163
224
|
|
164
225
|
def h(self, lq):
|
165
226
|
hq = self._unpack(lq)
|
166
227
|
self._decode(hq)
|
167
228
|
self.sim.h(hq[0])
|
168
229
|
self._encode(hq)
|
230
|
+
self._correct(lq)
|
169
231
|
|
170
232
|
def t(self, lq):
|
171
233
|
hq = self._unpack(lq)
|
172
234
|
self._decode(hq)
|
173
235
|
self.sim.t(hq[0])
|
174
236
|
self._encode(hq)
|
237
|
+
self._correct(lq)
|
175
238
|
|
176
239
|
def adjt(self, lq):
|
177
240
|
hq = self._unpack(lq)
|
178
241
|
self._decode(hq)
|
179
242
|
self.sim.adjt(hq[0])
|
180
243
|
self._encode(hq)
|
244
|
+
self._correct(lq)
|
181
245
|
|
182
246
|
def _cpauli(self, lq1, lq2, anti, pauli):
|
183
247
|
gate = None
|
@@ -227,6 +291,9 @@ class QrackAceBackend:
|
|
227
291
|
gate([hq1[1]], hq2[1])
|
228
292
|
gate([hq1[2]], hq2[2])
|
229
293
|
|
294
|
+
self._correct(lq1)
|
295
|
+
self._correct(lq2)
|
296
|
+
|
230
297
|
|
231
298
|
def cx(self, lq1, lq2):
|
232
299
|
self._cpauli(lq1, lq2, False, Pauli.PauliX)
|
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
|
File without changes
|
File without changes
|
File without changes
|