|
27 | 27 | nShots = 3 |
28 | 28 | nRounds = 4 |
29 | 29 |
|
30 | | -# error probabily |
| 30 | +# Uncomment for repeatability |
| 31 | +# cudaq.set_random_seed(13) |
| 32 | + |
| 33 | +# error probability |
31 | 34 | p = 0.01 |
32 | 35 | noise = cudaq.NoiseModel() |
33 | 36 | noise.add_all_qubit_channel("x", cudaq.Depolarization2(p), 1) |
|
37 | 40 | # our expected measurement in this state is 0 |
38 | 41 | expected_value = 0 |
39 | 42 |
|
| 43 | +# For large runs, set verbose to False to suppress output |
| 44 | +verbose = nShots <= 10 |
| 45 | + |
40 | 46 | # sample the steane memory circuit with noise on each cx gate |
41 | 47 | # reading out the syndromes after each stabilizer round (xor'd against the previous) |
42 | 48 | # and readout out the data qubits at the end of the experiment |
43 | 49 | syndromes, data = qec.sample_memory_circuit(steane, statePrep, nShots, nRounds, |
44 | 50 | noise) |
45 | | -print("From sample function:\n") |
46 | | -print("syndromes:\n", syndromes) |
47 | | -print("data:\n", data) |
| 51 | +if verbose: |
| 52 | + print("From sample function:\n") |
| 53 | + print("syndromes:\n", syndromes) |
| 54 | + print("data:\n", data) |
48 | 55 |
|
49 | 56 | # Get a decoder |
50 | 57 | decoder = qec.get_decoder("single_error_lut", H) |
|
54 | 61 | logical_measurements = (Lz @ data.transpose()) % 2 |
55 | 62 | # only one logical qubit, so do not need the second axis |
56 | 63 | logical_measurements = logical_measurements.flatten() |
57 | | -print("LMz:\n", logical_measurements) |
| 64 | +if verbose: |
| 65 | + print("LMz:\n", logical_measurements) |
58 | 66 |
|
59 | 67 | # organize data by shot and round if desired |
60 | 68 | syndromes = syndromes.reshape((nShots, nRounds, syndromes.shape[1])) |
|
63 | 71 | # through the stabilizer rounds |
64 | 72 | pauli_frame = np.array([0, 0], dtype=np.uint8) |
65 | 73 | for shot in range(0, nShots): |
66 | | - print("shot:", shot) |
| 74 | + if verbose: |
| 75 | + print("shot:", shot) |
67 | 76 | for syndrome in syndromes[shot]: |
68 | | - print("syndrome:", syndrome) |
| 77 | + if verbose: |
| 78 | + print("syndrome:", syndrome) |
69 | 79 | # Decode the syndrome |
70 | 80 | results = decoder.decode(syndrome) |
71 | 81 | convergence = results.converged |
72 | 82 | result = results.result |
73 | 83 | data_prediction = np.array(result, dtype=np.uint8) |
74 | 84 |
|
75 | 85 | # see if the decoded result anti-commutes with the observables |
76 | | - print("decode result:", data_prediction) |
| 86 | + if verbose: |
| 87 | + print("decode result:", data_prediction) |
77 | 88 | decoded_observables = (observables @ data_prediction) % 2 |
78 | | - print("decoded_observables:", decoded_observables) |
| 89 | + if verbose: |
| 90 | + print("decoded_observables:", decoded_observables) |
79 | 91 |
|
80 | 92 | # update pauli frame |
81 | 93 | pauli_frame = (pauli_frame + decoded_observables) % 2 |
82 | | - print("pauli frame:", pauli_frame) |
| 94 | + if verbose: |
| 95 | + print("pauli frame:", pauli_frame) |
83 | 96 |
|
84 | 97 | # after pauli frame has tracked corrections through the rounds |
85 | 98 | # apply the pauli frame correction to the measurement, and see |
86 | 99 | # if this matches the state we intended to prepare |
87 | 100 | # We prepared |0>, so we check if logical measurement Mz + Pf_X = 0 |
88 | 101 | corrected_mz = (logical_measurements[shot] + pauli_frame[0]) % 2 |
89 | | - print("Expected value:", expected_value) |
90 | | - print("Corrected value:", corrected_mz) |
| 102 | + if verbose: |
| 103 | + print("Expected value:", expected_value) |
| 104 | + print("Corrected value:", corrected_mz) |
91 | 105 | if (corrected_mz != expected_value): |
92 | 106 | nLogicalErrors += 1 |
93 | 107 |
|
94 | 108 | # Count how many shots the decoder failed to correct the errors |
95 | | -print("Number of logical errors:", nLogicalErrors) |
| 109 | +print(f"Number of logical errors out of {nShots} shots: {nLogicalErrors}") |
0 commit comments