microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
logo

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

samples/notebooks/carbon_error_correction/decoder.py

347lines · modecode

1import qsharp
2
3table = {
4 frozenset(): "IIIIIIIIIIII",
5 frozenset({3, 8, 9}): "XIIIIIIIIIII",
6 frozenset({0, 3, 6, 7, 8, 9}): "YIIIIIIIIIII",
7 frozenset({0, 6, 7}): "ZIIIIIIIIIII",
8 frozenset({3}): "IXIIIIIIIIII",
9 frozenset({0, 3, 6}): "IYIIIIIIIIII",
10 frozenset({0, 6}): "IZIIIIIIIIII",
11 frozenset({3, 8}): "IIXIIIIIIIII",
12 frozenset({0, 3, 8}): "IIYIIIIIIIII",
13 frozenset({0}): "IIZIIIIIIIII",
14 frozenset({3, 9}): "IIIXIIIIIIII",
15 frozenset({0, 3, 7, 9}): "IIIYIIIIIIII",
16 frozenset({0, 7}): "IIIZIIIIIIII",
17 frozenset({4, 9}): "IIIIXIIIIIII",
18 frozenset({1, 4, 7, 9}): "IIIIYIIIIIII",
19 frozenset({1, 7}): "IIIIZIIIIIII",
20 frozenset({4}): "IIIIIXIIIIII",
21 frozenset({1, 4, 6, 7}): "IIIIIYIIIIII",
22 frozenset({1, 6, 7}): "IIIIIZIIIIII",
23 frozenset({4, 8, 9}): "IIIIIIXIIIII",
24 frozenset({1, 4, 8, 9}): "IIIIIIYIIIII",
25 frozenset({1}): "IIIIIIZIIIII",
26 frozenset({4, 8}): "IIIIIIIXIIII",
27 frozenset({1, 4, 6, 8}): "IIIIIIIYIIII",
28 frozenset({1, 6}): "IIIIIIIZIIII",
29 frozenset({5, 8}): "IIIIIIIIXIII",
30 frozenset({2, 5, 6, 8}): "IIIIIIIIYIII",
31 frozenset({2, 6}): "IIIIIIIIZIII",
32 frozenset({5}): "IIIIIIIIIXII",
33 frozenset({2, 5, 7}): "IIIIIIIIIYII",
34 frozenset({2, 7}): "IIIIIIIIIZII",
35 frozenset({5, 9}): "IIIIIIIIIIXI",
36 frozenset({2, 5, 9}): "IIIIIIIIIIYI",
37 frozenset({2}): "IIIIIIIIIIZI",
38 frozenset({5, 8, 9}): "IIIIIIIIIIIX",
39 frozenset({2, 5, 6, 7, 8, 9}): "IIIIIIIIIIIY",
40 frozenset({2, 6, 7}): "IIIIIIIIIIIZ",
41 frozenset({0, 3, 6, 8, 9}): "XZIIIIIIIIII",
42 frozenset({0, 3, 6, 7}): "ZXIIIIIIIIII",
43 frozenset({0, 3, 8, 9}): "XIZIIIIIIIII",
44 frozenset({0, 3, 6, 7, 8}): "ZIXIIIIIIIII",
45 frozenset({0, 3, 7, 8, 9}): "XIIZIIIIIIII",
46 frozenset({0, 3, 6, 7, 9}): "ZIIXIIIIIIII",
47 frozenset({1, 3, 7, 8, 9}): "XIIIZIIIIIII",
48 frozenset({0, 4, 6, 7, 9}): "ZIIIXIIIIIII",
49 frozenset({1, 3, 6, 7, 8, 9}): "XIIIIZIIIIII",
50 frozenset({0, 4, 6, 7}): "ZIIIIXIIIIII",
51 frozenset({1, 3, 8, 9}): "XIIIIIZIIIII",
52 frozenset({0, 4, 6, 7, 8, 9}): "ZIIIIIXIIIII",
53 frozenset({1, 3, 6, 8, 9}): "XIIIIIIZIIII",
54 frozenset({0, 4, 6, 7, 8}): "ZIIIIIIXIIII",
55 frozenset({2, 3, 6, 8, 9}): "XIIIIIIIZIII",
56 frozenset({0, 5, 6, 7, 8}): "ZIIIIIIIXIII",
57 frozenset({2, 3, 7, 8, 9}): "XIIIIIIIIZII",
58 frozenset({0, 5, 6, 7}): "ZIIIIIIIIXII",
59 frozenset({2, 3, 8, 9}): "XIIIIIIIIIZI",
60 frozenset({0, 5, 6, 7, 9}): "ZIIIIIIIIIXI",
61 frozenset({2, 3, 6, 7, 8, 9}): "XIIIIIIIIIIZ",
62 frozenset({0, 5, 6, 7, 8, 9}): "ZIIIIIIIIIIX",
63 frozenset({0, 3}): "IXZIIIIIIIII",
64 frozenset({0, 3, 6, 8}): "IZXIIIIIIIII",
65 frozenset({0, 3, 7}): "IXIZIIIIIIII",
66 frozenset({0, 3, 6, 9}): "IZIXIIIIIIII",
67 frozenset({1, 3, 7}): "IXIIZIIIIIII",
68 frozenset({0, 4, 6, 9}): "IZIIXIIIIIII",
69 frozenset({1, 3, 6, 7}): "IXIIIZIIIIII",
70 frozenset({0, 4, 6}): "IZIIIXIIIIII",
71 frozenset({1, 3}): "IXIIIIZIIIII",
72 frozenset({0, 4, 6, 8, 9}): "IZIIIIXIIIII",
73 frozenset({1, 3, 6}): "IXIIIIIZIIII",
74 frozenset({0, 4, 6, 8}): "IZIIIIIXIIII",
75 frozenset({2, 3, 6}): "IXIIIIIIZIII",
76 frozenset({0, 5, 6, 8}): "IZIIIIIIXIII",
77 frozenset({2, 3, 7}): "IXIIIIIIIZII",
78 frozenset({0, 5, 6}): "IZIIIIIIIXII",
79 frozenset({2, 3}): "IXIIIIIIIIZI",
80 frozenset({0, 5, 6, 9}): "IZIIIIIIIIXI",
81 frozenset({2, 3, 6, 7}): "IXIIIIIIIIIZ",
82 frozenset({0, 5, 6, 8, 9}): "IZIIIIIIIIIX",
83 frozenset({0, 3, 7, 8}): "IIXZIIIIIIII",
84 frozenset({0, 3, 9}): "IIZXIIIIIIII",
85 frozenset({1, 3, 7, 8}): "IIXIZIIIIIII",
86 frozenset({0, 4, 9}): "IIZIXIIIIIII",
87 frozenset({1, 3, 6, 7, 8}): "IIXIIZIIIIII",
88 frozenset({0, 4}): "IIZIIXIIIIII",
89 frozenset({1, 3, 8}): "IIXIIIZIIIII",
90 frozenset({0, 4, 8, 9}): "IIZIIIXIIIII",
91 frozenset({1, 3, 6, 8}): "IIXIIIIZIIII",
92 frozenset({0, 4, 8}): "IIZIIIIXIIII",
93 frozenset({2, 3, 6, 8}): "IIXIIIIIZIII",
94 frozenset({0, 5, 8}): "IIZIIIIIXIII",
95 frozenset({2, 3, 7, 8}): "IIXIIIIIIZII",
96 frozenset({0, 5}): "IIZIIIIIIXII",
97 frozenset({2, 3, 8}): "IIXIIIIIIIZI",
98 frozenset({0, 5, 9}): "IIZIIIIIIIXI",
99 frozenset({2, 3, 6, 7, 8}): "IIXIIIIIIIIZ",
100 frozenset({0, 5, 8, 9}): "IIZIIIIIIIIX",
101 frozenset({1, 3, 7, 9}): "IIIXZIIIIIII",
102 frozenset({0, 4, 7, 9}): "IIIZXIIIIIII",
103 frozenset({1, 3, 6, 7, 9}): "IIIXIZIIIIII",
104 frozenset({0, 4, 7}): "IIIZIXIIIIII",
105 frozenset({1, 3, 9}): "IIIXIIZIIIII",
106 frozenset({0, 4, 7, 8, 9}): "IIIZIIXIIIII",
107 frozenset({1, 3, 6, 9}): "IIIXIIIZIIII",
108 frozenset({0, 4, 7, 8}): "IIIZIIIXIIII",
109 frozenset({2, 3, 6, 9}): "IIIXIIIIZIII",
110 frozenset({0, 5, 7, 8}): "IIIZIIIIXIII",
111 frozenset({2, 3, 7, 9}): "IIIXIIIIIZII",
112 frozenset({0, 5, 7}): "IIIZIIIIIXII",
113 frozenset({2, 3, 9}): "IIIXIIIIIIZI",
114 frozenset({0, 5, 7, 9}): "IIIZIIIIIIXI",
115 frozenset({2, 3, 6, 7, 9}): "IIIXIIIIIIIZ",
116 frozenset({0, 5, 7, 8, 9}): "IIIZIIIIIIIX",
117 frozenset({1, 4, 6, 7, 9}): "IIIIXZIIIIII",
118 frozenset({1, 4, 7}): "IIIIZXIIIIII",
119 frozenset({1, 4, 9}): "IIIIXIZIIIII",
120 frozenset({1, 4, 7, 8, 9}): "IIIIZIXIIIII",
121 frozenset({1, 4, 6, 9}): "IIIIXIIZIIII",
122 frozenset({1, 4, 7, 8}): "IIIIZIIXIIII",
123 frozenset({2, 4, 6, 9}): "IIIIXIIIZIII",
124 frozenset({1, 5, 7, 8}): "IIIIZIIIXIII",
125 frozenset({2, 4, 7, 9}): "IIIIXIIIIZII",
126 frozenset({1, 5, 7}): "IIIIZIIIIXII",
127 frozenset({2, 4, 9}): "IIIIXIIIIIZI",
128 frozenset({1, 5, 7, 9}): "IIIIZIIIIIXI",
129 frozenset({2, 4, 6, 7, 9}): "IIIIXIIIIIIZ",
130 frozenset({1, 5, 7, 8, 9}): "IIIIZIIIIIIX",
131 frozenset({1, 4}): "IIIIIXZIIIII",
132 frozenset({1, 4, 6, 7, 8, 9}): "IIIIIZXIIIII",
133 frozenset({1, 4, 6}): "IIIIIXIZIIII",
134 frozenset({1, 4, 6, 7, 8}): "IIIIIZIXIIII",
135 frozenset({2, 4, 6}): "IIIIIXIIZIII",
136 frozenset({1, 5, 6, 7, 8}): "IIIIIZIIXIII",
137 frozenset({2, 4, 7}): "IIIIIXIIIZII",
138 frozenset({1, 5, 6, 7}): "IIIIIZIIIXII",
139 frozenset({2, 4}): "IIIIIXIIIIZI",
140 frozenset({1, 5, 6, 7, 9}): "IIIIIZIIIIXI",
141 frozenset({2, 4, 6, 7}): "IIIIIXIIIIIZ",
142 frozenset({1, 5, 6, 7, 8, 9}): "IIIIIZIIIIIX",
143 frozenset({1, 4, 6, 8, 9}): "IIIIIIXZIIII",
144 frozenset({1, 4, 8}): "IIIIIIZXIIII",
145 frozenset({2, 4, 6, 8, 9}): "IIIIIIXIZIII",
146 frozenset({1, 5, 8}): "IIIIIIZIXIII",
147 frozenset({2, 4, 7, 8, 9}): "IIIIIIXIIZII",
148 frozenset({1, 5}): "IIIIIIZIIXII",
149 frozenset({2, 4, 8, 9}): "IIIIIIXIIIZI",
150 frozenset({1, 5, 9}): "IIIIIIZIIIXI",
151 frozenset({2, 4, 6, 7, 8, 9}): "IIIIIIXIIIIZ",
152 frozenset({1, 5, 8, 9}): "IIIIIIZIIIIX",
153 frozenset({2, 4, 6, 8}): "IIIIIIIXZIII",
154 frozenset({1, 5, 6, 8}): "IIIIIIIZXIII",
155 frozenset({2, 4, 7, 8}): "IIIIIIIXIZII",
156 frozenset({1, 5, 6}): "IIIIIIIZIXII",
157 frozenset({2, 4, 8}): "IIIIIIIXIIZI",
158 frozenset({1, 5, 6, 9}): "IIIIIIIZIIXI",
159 frozenset({2, 4, 6, 7, 8}): "IIIIIIIXIIIZ",
160 frozenset({1, 5, 6, 8, 9}): "IIIIIIIZIIIX",
161 frozenset({2, 5, 7, 8}): "IIIIIIIIXZII",
162 frozenset({2, 5, 6}): "IIIIIIIIZXII",
163 frozenset({2, 5, 8}): "IIIIIIIIXIZI",
164 frozenset({2, 5, 6, 9}): "IIIIIIIIZIXI",
165 frozenset({2, 5, 6, 7, 8}): "IIIIIIIIXIIZ",
166 frozenset({2, 5, 6, 8, 9}): "IIIIIIIIZIIX",
167 frozenset({2, 5}): "IIIIIIIIIXZI",
168 frozenset({2, 5, 7, 9}): "IIIIIIIIIZXI",
169 frozenset({2, 5, 6, 7}): "IIIIIIIIIXIZ",
170 frozenset({2, 5, 7, 8, 9}): "IIIIIIIIIZIX",
171 frozenset({2, 5, 6, 7, 9}): "IIIIIIIIIIXZ",
172 frozenset({2, 5, 8, 9}): "IIIIIIIIIIZX",
173}
174
175generators = [
176 "XXXXIIIIIIII",
177 "IIIIXXXXIIII",
178 "IIIIIIIIXXXX",
179 "ZZZZIIIIIIII",
180 "IIIIZZZZIIII",
181 "IIIIIIIIZZZZ",
182 "XXIIIXIXXIIX",
183 "XIIXXXIIIXIX",
184 "ZIZIIIZZZIIZ",
185 "ZIIZZIZIIIZZ",
186]
187
188logical_basis = ["XIIXIIIIIIXX", "ZIIZIIIIIZIZ", "IXIXIIIIIXXI", "ZZIIIIIIIZZI"]
189
190expanded_logical_basis = [
191 "XIIXIIIIIIXX",
192 "ZIIZIIIIIZIZ",
193 "YIIYIIIIIZXY",
194 "IXIXIIIIIXXI",
195 "ZZIIIIIIIZZI",
196 "ZYIXIIIIIYYI",
197]
198
199
200def results_as_pauli(results: list[qsharp.Result], pauli: str = "Z") -> str:
201 p = ""
202 for r in results:
203 if r == qsharp.Result.One:
204 p += pauli
205 else:
206 p += "I"
207 return p
208
209
210def pauli_as_results(p: str, basis: str = "Z", count: int = 2):
211 results = []
212 chars = "XYZ".replace(basis, "")
213 for i in range(count):
214 if p[i] in chars:
215 results.append(qsharp.Result.One)
216 else:
217 results.append(qsharp.Result.Zero)
218 return results
219
220
221def pauli_support(p: str) -> list[int]:
222 return [i for i, char in enumerate(p) if char != "I"]
223
224
225def logical_indexes_of(pauli: str):
226 for qubit in pauli_support(pauli):
227 character = pauli[qubit]
228 if character == "X":
229 yield 3 * qubit
230 if character == "Z":
231 yield 3 * qubit + 1
232 if character == "Y":
233 yield 3 * qubit + 2
234
235
236def commutes_with(pauli1: str, pauli2: str) -> bool:
237 """Check if two Pauli strings commute."""
238 assert len(pauli1) == len(pauli2)
239 anti_commute_count = 0
240 for p1, p2 in zip(pauli1, pauli2):
241 if p1 == "I" or p2 == "I":
242 continue
243 if p1 != p2:
244 anti_commute_count += 1
245 return anti_commute_count % 2 == 0
246
247
248def syndrome_of(error: str) -> list[int]:
249 syndrome = []
250 for label, generator in enumerate(generators):
251 if not commutes_with(error, generator):
252 syndrome.append(label)
253 return syndrome
254
255
256def mult_paulis(p1: str, p2: str) -> str:
257 if len(p1) < len(p2):
258 p1 = p1 + "I" * (len(p2) - len(p1))
259 elif len(p2) < len(p1):
260 p2 = p2 + "I" * (len(p1) - len(p2))
261 result = ""
262 for a, b in zip(p1, p2):
263 if a == "I":
264 result += b
265 elif b == "I":
266 result += a
267 elif a == b:
268 result += "I"
269 elif (a, b) in [("X", "Y"), ("Y", "X")]:
270 result += "Z"
271 elif (a, b) in [("Y", "Z"), ("Z", "Y")]:
272 result += "X"
273 elif (a, b) in [("Z", "X"), ("X", "Z")]:
274 result += "Y"
275 else:
276 raise ValueError(f"Unexpected Pauli characters: {a}, {b}")
277 return result
278
279
280def unsigned_logical_action_of(error: str) -> str:
281 character_of = ("Y", "Z", "X", "I")
282 commutations = list(map(lambda lb: commutes_with(error, lb), logical_basis))
283 indexes = [2 * x + z for x, z in [commutations[0:2], commutations[2:4]]]
284 characters = "".join(character_of[index] for index in indexes)
285 return characters
286
287
288def representative_of(pauli: str) -> str:
289 generators = (expanded_logical_basis[index] for index in logical_indexes_of(pauli))
290 res = "I" * 12
291 for gen in generators:
292 res = mult_paulis(res, gen)
293 return res
294
295
296def logical_action_of(error: str) -> str:
297 logical = unsigned_logical_action_of(error)
298 return logical
299
300
301def recovery_from_syndrome_measurements(
302 x_meas: list[qsharp.Result], z_meas: list[qsharp.Result]
303) -> str:
304 error_z = results_as_pauli(x_meas, pauli="Z")
305 error_x = results_as_pauli(z_meas, pauli="X")
306 error = mult_paulis(error_z, error_x)
307 syndrome = frozenset(syndrome_of(error))
308 recovery = table.get(syndrome, "IIIIIIIIIIII")
309 return logical_action_of(mult_paulis(recovery, error))
310
311
312# For each tuple of shot results, mark the shot as preselect if any preselect
313# measurement is One. Then use the rounds of error correction syndrome measurements
314# to generate Pauli corrections, collected in a frame. Use the final Pauli frame
315# to calculate the corrected logical results.
316def decode_results(results, basis: str = "Z"):
317 corrected_logical_results = []
318 for res in results:
319 corrected_logical_results.append([])
320 for shot in res:
321 if any([preselect == qsharp.Result.One for preselect in shot[0]]):
322 corrected_logical_results[-1] += ["PREselect"]
323 continue
324 recovery = "IIIIIIIIIIII"
325 r = None
326 for ec_output in shot[1]:
327 r = recovery_from_syndrome_measurements(ec_output[0], ec_output[1])
328 if r is None:
329 corrected_logical_results[-1] += ["POSTselect"]
330 break
331 recovery = mult_paulis(recovery, r)
332 if r is None:
333 corrected_logical_results[-1] += [
334 pauli_as_results(recovery, basis=basis)
335 ]
336 continue
337 if basis == "Z":
338 r = recovery_from_syndrome_measurements([], shot[2])
339 else:
340 assert basis == "X"
341 r = recovery_from_syndrome_measurements(shot[2], [])
342 if r is None:
343 corrected_logical_results[-1] += ["POSTselect"]
344 continue
345 recovery = mult_paulis(recovery, r)
346 corrected_logical_results[-1] += [pauli_as_results(recovery, basis=basis)]
347 return corrected_logical_results
348