Skip to content

Instantly share code, notes, and snippets.

@Strilanc
Created April 3, 2024 21:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Strilanc/7f82414b50d24a15adf8a3bbed82c979 to your computer and use it in GitHub Desktop.
Save Strilanc/7f82414b50d24a15adf8a3bbed82c979 to your computer and use it in GitHub Desktop.
What happens when I postselect the single-round data from the public google 3v5 experimental data?
import collections
import numpy as np
import sinter
import stim
import pathlib
from matplotlib import pyplot as plt
workspace = pathlib.Path("google_qec3v5_experiment_data")
if not workspace.exists():
raise ValueError("Run me from a directory containing unzipped 'google_qec3v5_experiment_data' from https://zenodo.org/records/6804040")
ax, fig = plt.subplots(1, 1)
a = stim.read_shot_data_file(path=workspace / 'surface_code_bZ_d5_r25_center_5_5' / 'obs_flips_predicted_by_belief_matching.01', num_observables=1, format='01')
p = stim.read_shot_data_file(path=workspace / 'surface_code_bZ_d5_r25_center_5_5' / 'obs_flips_actual.01', num_observables=1, format='01')
has_error = np.any(a ^ p, axis=1)
num_shots = len(has_error)
num_error = np.count_nonzero(has_error)
error_per_round = sinter.shot_error_rate_to_piece_error_rate(num_error / num_shots, pieces=25)
plt.hlines(error_per_round, 0, 1, colors='black', linestyles='--', label='d=5 per-round error rate at rounds=25')
xs = collections.defaultdict(list)
ys = collections.defaultdict(list)
for d in workspace.iterdir():
if not d.is_dir() or 'surface' not in d.name:
continue
if '_r01_' not in d.name: # single round only please
continue
c = stim.Circuit.from_file(d / 'circuit_noisy.stim')
r = stim.read_shot_data_file(path=d / 'detection_events.b8', num_detectors=c.num_detectors, format='b8')
a = stim.read_shot_data_file(path=d / 'obs_flips_predicted_by_belief_matching.01', num_observables=c.num_observables, format='01')
p = stim.read_shot_data_file(path=d / 'obs_flips_actual.01', num_observables=c.num_observables, format='01')
x2s = []
y2s = []
for discard_threshold in [0, 1, 2, 3, 4, 2**30]:
should_discard = np.count_nonzero(r, axis=1) > discard_threshold
has_error = np.any(a ^ p, axis=1)
num_shots = len(has_error)
num_discarded = np.count_nonzero(should_discard)
num_kept = np.count_nonzero(~has_error)
num_kept_error = np.count_nonzero(has_error & ~should_discard)
num_error = np.count_nonzero(has_error)
x2s.append(num_discarded / num_shots)
y2s.append(max(num_kept_error / num_kept, 1 / (num_shots + 1)))
b = 'X' if 'bX' in d.name else 'Z' if 'bZ' in d.name else '?'
label = f'd={len(c.shortest_graphlike_error())}, rounds=1, basis={b}, detection_cutoff=[0,1,2,3,4,∞]'
xs[label].append(x2s)
ys[label].append(y2s)
i = 0
for k in xs.keys():
x = xs[k]
y = ys[k]
first = True
for ex, ey in zip(x, y):
plt.plot(ex, ey, label=k if first else None, marker='x', color=f'C{i}')
first = False
i += 1
plt.xlabel('Discard Rate')
plt.ylabel('Kept Error Rate')
plt.title('Google 3v5 data single-round reject-vs-fidelity tradeoff under detection-count postselection\nNote: all error rates clamped to be at least 1/num_shots')
plt.legend(loc='upper right')
plt.semilogy()
plt.ylim(1e-5, 1e-0)
plt.xlim(0, 1)
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment