diff --git a/Cargo.toml b/Cargo.toml index 85327227..17ec3567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ MWPM_reverse_order = [ ] # test the logical error rate arbitrariness of MWPM decoders, see articles/UFandMWPM.md fusion_blossom = ["fusion-blossom"] # hyperion = ["mwpf"] +include_different_type_edges = [] [lib] name = "qecp" diff --git a/benchmark/fault_tolerant_MWPM/automated_threshold_evaluation.py b/benchmark/fault_tolerant_MWPM/automated_threshold_evaluation.py index 0e9653db..471f742a 100644 --- a/benchmark/fault_tolerant_MWPM/automated_threshold_evaluation.py +++ b/benchmark/fault_tolerant_MWPM/automated_threshold_evaluation.py @@ -13,25 +13,33 @@ """ from distutils.command.build import build -import os, sys, math, subprocess, random +import os +import sys +import math +import subprocess +import random import scipy.stats import numpy as np import tempfile -import subprocess, sys -qec_playground_root_dir = subprocess.run("git rev-parse --show-toplevel", cwd=os.path.dirname(os.path.abspath(__file__)), shell=True, check=True, capture_output=True).stdout.decode(sys.stdout.encoding).strip(" \r\n") +import subprocess +import sys +qec_playground_root_dir = subprocess.run("git rev-parse --show-toplevel", cwd=os.path.dirname(os.path.abspath( + __file__)), shell=True, check=True, capture_output=True).stdout.decode(sys.stdout.encoding).strip(" \r\n") # rust_dir = os.path.join(qec_playground_root_dir, "backend", "rust") rust_dir = qec_playground_root_dir # updated project structure + def main(): # # test basic command runner # random_error_rate, confidence_interval, full_result = qec_playground_fault_tolerant_MWPM_simulator_runner(0.005, (5, 5, 5), "-b10 -p0 --use_xzzx_code --bias_eta 100 --noise_model GenericBiasedWithBiasedCX".split(" "), True, True) # print(random_error_rate, confidence_interval, full_result) # exit(0) - # UnionFind Decoder (max_half_weight = 10), XZZX code, - pair = [ (4, 12, 12), (5, 15, 15) ] # (di, dj, T) - parameters = "-p0 --use_xzzx_code --bias_eta 10 --noise_model GenericBiasedWithBiasedCX".split(" ") + # UnionFind Decoder (max_half_weight = 10), XZZX code, + pair = [(4, 12, 12), (5, 15, 15)] # (di, dj, T) + parameters = "-p0 --use_xzzx_code --bias_eta 10 --noise_model GenericBiasedWithBiasedCX".split( + " ") evaluator = AutomatedThresholdEvaluator(pair, parameters=parameters) threshold, relative_confidence_interval = evaluator.evaluate_threshold() print("\n\nresult:") @@ -40,6 +48,7 @@ def main(): print(f"threshold = {threshold}") print(f"relative_confidence_interval = {relative_confidence_interval}") + """ use_fake_runner: help to debug the script, by using a simple error rate model 0.2 * (p/pth)^d @@ -52,17 +61,22 @@ def main(): QEC_PLAYGROUND_COMPILATION_DONE = False if 'MANUALLY_COMPILE_QEC' in os.environ and os.environ["MANUALLY_COMPILE_QEC"] == "TRUE": QEC_PLAYGROUND_COMPILATION_DONE = True + + def compile_code_if_necessary(additional_build_parameters=None): global QEC_PLAYGROUND_COMPILATION_DONE if QEC_PLAYGROUND_COMPILATION_DONE is False: build_parameters = ["cargo", "build", "--release"] if additional_build_parameters is not None: - build_parameters += additional_build_parameters + build_parameters.append(additional_build_parameters) # print(build_parameters) - process = subprocess.Popen(build_parameters, universal_newlines=True, stdout=sys.stdout, stderr=sys.stderr, cwd=rust_dir) + process = subprocess.Popen(build_parameters, universal_newlines=True, + stdout=sys.stdout, stderr=sys.stderr, cwd=rust_dir) process.wait() assert process.returncode == 0, "compile has error" QEC_PLAYGROUND_COMPILATION_DONE = True + + def run_qec_playground_command_get_stdout(command, no_stdout=False, use_tmp_out=False, stderr_to_stdout=False): compile_code_if_necessary() env = os.environ.copy() @@ -74,7 +88,8 @@ def run_qec_playground_command_get_stdout(command, no_stdout=False, use_tmp_out= stdout = out_file if no_stdout: stdout = sys.stdout - process = subprocess.Popen(command, universal_newlines=True, env=env, stdout=stdout, stderr=(stdout if stderr_to_stdout else sys.stderr), bufsize=100000000) + process = subprocess.Popen(command, universal_newlines=True, env=env, stdout=stdout, stderr=( + stdout if stderr_to_stdout else sys.stderr), bufsize=100000000) # process.wait() # this causes lock on macOS, why is this even necessary? process.communicate already wait for ending stdout, _ = process.communicate() if use_tmp_out: @@ -85,6 +100,7 @@ def run_qec_playground_command_get_stdout(command, no_stdout=False, use_tmp_out= os.remove(out_filename) return stdout, process.returncode + def qec_playground_fault_tolerant_MWPM_simulator_runner_vec_command(p_vec, di_vec, dj_vec, T_vec, parameters, max_N=100000, min_error_cases=3000, rust_dir=rust_dir, time_budget=None): print("[error] command 'fault_tolerant_benchmark' deprecated, please consider migrate the script to newer interface 'benchmark', or start a feature request in https://github.com/yuewuo/QEC-Playground to ask the maintainer to do this migration. sorry for the inconvenience.") raise "not longer supported, please revert back to commit 0a7cd03b33d6ad1e62fff7d7fb4e88d60c3fbe55 to use this script" @@ -93,32 +109,38 @@ def qec_playground_fault_tolerant_MWPM_simulator_runner_vec_command(p_vec, di_ve dj_str = "[" + ",".join([str(e) for e in dj_vec]) + "]" T_str = "[" + ",".join([str(e) for e in T_vec]) + "]" qecp_path = os.path.join(rust_dir, "target", "release", "qecp-cli") - command = [qecp_path, "tool", "fault_tolerant_benchmark", di_str, "--djs", dj_str, T_str, f"-m{max_N}", f"-e{min_error_cases}", p_str] + parameters + command = [qecp_path, "tool", "fault_tolerant_benchmark", di_str, "--djs", + dj_str, T_str, f"-m{max_N}", f"-e{min_error_cases}", p_str] + parameters if time_budget is not None: command += ["--time_budget", f"{time_budget}"] return command + def qec_playground_benchmark_simulator_runner_vec_command(p_vec, di_vec, dj_vec, T_vec, parameters, max_N=100000, min_error_cases=3000, rust_dir=rust_dir, time_budget=None): p_str = "[" + ",".join([f"{e:.8e}" for e in p_vec]) + "]" di_str = "[" + ",".join([str(e) for e in di_vec]) + "]" dj_str = "[" + ",".join([str(e) for e in dj_vec]) + "]" T_str = "[" + ",".join([str(e) for e in T_vec]) + "]" qecp_path = os.path.join(rust_dir, "target", "release", "qecp-cli") - command = [qecp_path, "tool", "benchmark", di_str, "--djs", dj_str, T_str, f"-m{max_N}", f"-e{min_error_cases}", p_str] + parameters + command = [qecp_path, "tool", "benchmark", di_str, "--djs", dj_str, + T_str, f"-m{max_N}", f"-e{min_error_cases}", p_str] + parameters if time_budget is not None: command += ["--time_budget", f"{time_budget}"] return command + def qec_playground_fault_tolerant_MWPM_simulator_runner(p, pair_one, parameters, is_rough_test, verbose, use_fake_runner=False, max_N=100000, min_error_cases=3000): di, dj, T = pair_one min_error_cases = min_error_cases if is_rough_test else max_N - command = qec_playground_fault_tolerant_MWPM_simulator_runner_vec_command([p], [di], [dj], [T], parameters, max_N, min_error_cases) + command = qec_playground_fault_tolerant_MWPM_simulator_runner_vec_command( + [p], [di], [dj], [T], parameters, max_N, min_error_cases) if verbose: print(" ".join(command)) if use_fake_runner: origin_error_rate = 0.2 * math.pow(p / 0.07, di) confidence_interval = 0.025 # 3000 error cases - error_rate = random_non_negative(origin_error_rate, confidence_interval) + error_rate = random_non_negative( + origin_error_rate, confidence_interval) full_result = f"full result not available for fake runner {pair_one}, {p}, {error_rate}({confidence_interval})" else: stdout, returncode = run_qec_playground_command_get_stdout(command) @@ -132,6 +154,7 @@ def qec_playground_fault_tolerant_MWPM_simulator_runner(p, pair_one, parameters, confidence_interval = float(lst[7]) return error_rate, confidence_interval, full_result + def random_non_negative(error_rate, confidence_interval_95): stddev = error_rate * confidence_interval_95 / 1.96 random_error_rate = 0 @@ -139,6 +162,7 @@ def random_non_negative(error_rate, confidence_interval_95): random_error_rate = random.gauss(error_rate, stddev) return random_error_rate + def combine_full_result(result1, result2): if result1 is None: return result2 @@ -154,27 +178,34 @@ def combine_full_result(result1, result2): total_repeats = int(lst1[3]) + int(lst2[3]) qec_failed = int(lst1[4]) + int(lst2[4]) error_rate = qec_failed / total_repeats - confidence_interval_95_percent = math.sqrt(1.96 * (error_rate * (1. - error_rate) / total_repeats)) / error_rate + confidence_interval_95_percent = math.sqrt( + 1.96 * (error_rate * (1. - error_rate) / total_repeats)) / error_rate # error_rate assert lst1[6] == lst2[6], "di must be equal" # confidence_interval_95_percent assert lst1[8] == lst2[8], "pe must be equal" return f"{lst1[0]} {lst1[1]} {lst1[2]} {total_repeats} {qec_failed} {str(error_rate)} {lst1[6]} {str(confidence_interval_95_percent)} {lst1[8]}" + class AutomatedThresholdEvaluator: def __init__(self, pair, parameters=[], simulator_runner=qec_playground_fault_tolerant_MWPM_simulator_runner): - assert (isinstance(pair, list) or isinstance(pair, tuple)) and len(pair) == 2, "pair should be a list of 2" + assert (isinstance(pair, list) or isinstance(pair, tuple) + ) and len(pair) == 2, "pair should be a list of 2" self.pair = pair self.parameters = parameters self.simulator_runner = simulator_runner # initialize searching parameters that can be later adjusted self.searching_upper_bound = 0.5 # most threshold is between 1e-4 and 0.5 self.searching_lower_bound = 0.0001 - self.target_threshold_accuracy = 0.05 # target a 5% accuracy of threshold would be reasonable - self.reasonable_threshold_range = 1.0 # drop if intersection point is not in [p_estimate / (1 + self.reasonable_threshold_range), p_estimate * (1 + self.reasonable_threshold_range)] - self.do_not_believe_logical_error_rate_above = 0.45 # don't believe the data if the logical error rate is more than 45% + # target a 5% accuracy of threshold would be reasonable + self.target_threshold_accuracy = 0.05 + # drop if intersection point is not in [p_estimate / (1 + self.reasonable_threshold_range), p_estimate * (1 + self.reasonable_threshold_range)] + self.reasonable_threshold_range = 1.0 + # don't believe the data if the logical error rate is more than 45% + self.do_not_believe_logical_error_rate_above = 0.45 self.verbose = True - self.accurate_sample_count = 5 # sample equally-spaced in [rough / (1 + self.target_threshold_accuracy), rough * (1 + self.target_threshold_accuracy)] + # sample equally-spaced in [rough / (1 + self.target_threshold_accuracy), rough * (1 + self.target_threshold_accuracy)] + self.accurate_sample_count = 5 self.random_intersection_count = 1000 def get_rough_estimation(self): @@ -184,7 +215,8 @@ def get_rough_estimation(self): print(f"rough threshold estimation:") while upper_bound / lower_bound - 1 > self.target_threshold_accuracy: searching_p = math.sqrt(upper_bound * lower_bound) - error_rate_1, confidence_interval_1, _ = self.simulator_runner(searching_p, self.pair[0], self.parameters, True, self.verbose) + error_rate_1, confidence_interval_1, _ = self.simulator_runner( + searching_p, self.pair[0], self.parameters, True, self.verbose) # do not believe the data if logical error rate is too high if error_rate_1 >= self.do_not_believe_logical_error_rate_above: upper_bound = searching_p @@ -193,7 +225,8 @@ def get_rough_estimation(self): if error_rate_1 == 0 or confidence_interval_1 >= 0.5: lower_bound = searching_p continue - error_rate_2, confidence_interval_2, _ = self.simulator_runner(searching_p, self.pair[1], self.parameters, True, self.verbose) + error_rate_2, confidence_interval_2, _ = self.simulator_runner( + searching_p, self.pair[1], self.parameters, True, self.verbose) # do not believe the data if logical error rate is too high if error_rate_2 >= self.do_not_believe_logical_error_rate_above: upper_bound = searching_p @@ -211,24 +244,30 @@ def get_rough_estimation(self): lower_bound = searching_p else: upper_bound = searching_p - + return math.sqrt(upper_bound * lower_bound) def get_accurate_threshold(self, rough_estimation): - sampling_p_lower_bound = rough_estimation / (1 + self.target_threshold_accuracy) - sampling_step = math.pow(1 + self.target_threshold_accuracy, 2 / (self.accurate_sample_count - 1)) - sampling_p_higher_bound = sampling_p_lower_bound * math.pow(sampling_step, self.accurate_sample_count) + sampling_p_lower_bound = rough_estimation / \ + (1 + self.target_threshold_accuracy) + sampling_step = math.pow( + 1 + self.target_threshold_accuracy, 2 / (self.accurate_sample_count - 1)) + sampling_p_higher_bound = sampling_p_lower_bound * \ + math.pow(sampling_step, self.accurate_sample_count) sampling_p_vec = [] for i in range(self.accurate_sample_count): - sampling_p_vec.append(sampling_p_lower_bound * math.pow(sampling_step, i)) + sampling_p_vec.append( + sampling_p_lower_bound * math.pow(sampling_step, i)) if self.verbose: print(f"accurate threshold estimation: {sampling_p_vec}") result_1_vec = [] result_2_vec = [] for i in range(self.accurate_sample_count): searching_p = sampling_p_vec[i] - error_rate_1, confidence_interval_1, fr1 = self.simulator_runner(searching_p, self.pair[0], self.parameters, False, self.verbose) - error_rate_2, confidence_interval_2, fr2 = self.simulator_runner(searching_p, self.pair[1], self.parameters, False, self.verbose) + error_rate_1, confidence_interval_1, fr1 = self.simulator_runner( + searching_p, self.pair[0], self.parameters, False, self.verbose) + error_rate_2, confidence_interval_2, fr2 = self.simulator_runner( + searching_p, self.pair[1], self.parameters, False, self.verbose) result_1_vec.append((error_rate_1, confidence_interval_1, fr1)) result_2_vec.append((error_rate_2, confidence_interval_2, fr2)) if self.verbose: @@ -240,20 +279,26 @@ def get_accurate_threshold(self, rough_estimation): print(result_2_vec[i][2]) ln_pth_vec = [] X = [math.log(p) for p in sampling_p_vec] - ln_pth_lower_bound = math.log(rough_estimation / (1 + self.reasonable_threshold_range)) - ln_pth_upper_bound = math.log(rough_estimation * (1 + self.reasonable_threshold_range)) + ln_pth_lower_bound = math.log( + rough_estimation / (1 + self.reasonable_threshold_range)) + ln_pth_upper_bound = math.log( + rough_estimation * (1 + self.reasonable_threshold_range)) for j in range(self.random_intersection_count): - Y1 = [math.log(random_non_negative(e[0], e[1])) for e in result_1_vec] + Y1 = [math.log(random_non_negative(e[0], e[1])) + for e in result_1_vec] slope1, intercept1, _, _, _ = scipy.stats.linregress(X, Y1) - Y2 = [math.log(random_non_negative(e[0], e[1])) for e in result_2_vec] + Y2 = [math.log(random_non_negative(e[0], e[1])) + for e in result_2_vec] slope2, intercept2, _, _, _ = scipy.stats.linregress(X, Y2) lnp = (intercept2 - intercept1) / (slope1 - slope2) if lnp < ln_pth_lower_bound or lnp > ln_pth_upper_bound: - print(f"[warning] found unreasonable intersection point (threshold) value p = {math.exp(lnp)}, algorithm may fail") + print( + f"[warning] found unreasonable intersection point (threshold) value p = {math.exp(lnp)}, algorithm may fail") continue ln_pth_vec.append(lnp) threshold = math.exp(np.mean(ln_pth_vec)) - confidence_interval = 1.96 * np.std(ln_pth_vec) # e^ε = 1 + ε when ε << 1 + confidence_interval = 1.96 * \ + np.std(ln_pth_vec) # e^ε = 1 + ε when ε << 1 is_extrapolated = threshold > sampling_p_higher_bound or threshold < sampling_p_lower_bound return threshold, confidence_interval, is_extrapolated @@ -263,13 +308,17 @@ def evaluate_threshold(self): if self.verbose: print("rough_estimation:", rough_estimation) # more accurate logical error rate around the threshold point - threshold, confidence_interval, is_extrapolated = self.get_accurate_threshold(rough_estimation) + threshold, confidence_interval, is_extrapolated = self.get_accurate_threshold( + rough_estimation) # if error exceeds the target or threshold is extrapolated, then re-run the experiment if is_extrapolated or confidence_interval > self.target_threshold_accuracy: - threshold, confidence_interval, is_extrapolated = self.get_accurate_threshold(threshold) + threshold, confidence_interval, is_extrapolated = self.get_accurate_threshold( + threshold) if is_extrapolated: - print(f"[warning] extrapolated threshold value even after retry: {threshold} {confidence_interval}") + print( + f"[warning] extrapolated threshold value even after retry: {threshold} {confidence_interval}") return threshold, confidence_interval + if __name__ == "__main__": main() diff --git a/benchmark/paper_splitting_decoder/README.md b/benchmark/paper_splitting_decoder/README.md new file mode 100644 index 00000000..590da1c0 --- /dev/null +++ b/benchmark/paper_splitting_decoder/README.md @@ -0,0 +1,8 @@ +# Evaluation + +In the original splitting decoder paper, it says that introducing the Y errors on the corner will reduce the +code distance. However, in my first attempt to reproduce this, I didn't find the effect. Although the logical +error rate is indeed worse than the decoder without the Y edges. + +This evaluation aims to answer this question in detail, including code capacity noise model, phenomenological noise +model and circuit-level noise model. diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_noise.gp b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_noise.gp new file mode 100644 index 00000000..f604015a --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_noise.gp @@ -0,0 +1,33 @@ +set terminal postscript eps color "Arial, 20" +set title "Circuit-Level Noise Rotated Surface Code" +set xlabel "Depolarizing Error Rate (p)" font "Arial, 20" +set ylabel "Logical Error Rate (p_L)" font "Arial, 20" +set grid ytics +set size 1,1.2 + +set logscale x +set xrange [0.00001:0.1] +set xtics ("10^{-5}" 0.00001, "10^{-4}" 0.0001, "10^{-3}" 0.001, "10^{-2}" 0.01, "10^{-1}" 0.1) +set logscale y +set ytics ("10^{-8}" 0.00000001, "10^{-7}" 0.0000001, "10^{-6}" 0.000001, "10^{-5}" 0.00001, "10^{-4}" 0.0001, "10^{-3}" 0.001, "10^{-2}" 0.01, "10^{-1}" 0.1) +set yrange [0.00000001:1] +set key outside horizontal top center font "Arial, 24" + +set style fill transparent solid 0.2 noborder + +set output "circuit_level_noise.eps" + +plot "circuit_level_normal/d_3.txt" using 1:6 with linespoints lt rgb "red" linewidth 5 pointtype 2 pointsize 1 title "d=3",\ + "circuit_level_normal/d_5.txt" using 1:6 with linespoints lt rgb "blue" linewidth 5 pointtype 2 pointsize 1 title "d=5",\ + "circuit_level_normal/d_7.txt" using 1:6 with linespoints lt rgb "green" linewidth 5 pointtype 2 pointsize 1 title "d=7",\ + "circuit_level_normal/d_9.txt" using 1:6 with linespoints lt rgb "yellow" linewidth 5 pointtype 2 pointsize 1 title "d=9",\ + "circuit_level_normal/d_11.txt" using 1:6 with linespoints lt rgb "purple" linewidth 5 pointtype 2 pointsize 1 title "d=11",\ + "circuit_level_normal/d_13.txt" using 1:6 with linespoints lt rgb "orange" linewidth 5 pointtype 2 pointsize 1 title "d=13",\ + "circuit_level_with_y/d_3.txt" using 1:6 with linespoints lt rgb "red" dashtype 3 linewidth 5 pointtype 2 pointsize 1 title "d=3(Y)",\ + "circuit_level_with_y/d_5.txt" using 1:6 with linespoints lt rgb "blue" dashtype 3 linewidth 5 pointtype 2 pointsize 1 title "d=5(Y)",\ + "circuit_level_with_y/d_7.txt" using 1:6 with linespoints lt rgb "green" dashtype 3 linewidth 5 pointtype 2 pointsize 1 title "d=7(Y)",\ + "circuit_level_with_y/d_9.txt" using 1:6 with linespoints lt rgb "yellow" dashtype 3 linewidth 5 pointtype 2 pointsize 1 title "d=9(Y)",\ + "circuit_level_with_y/d_11.txt" using 1:6 with linespoints lt rgb "purple" dashtype 3 linewidth 5 pointtype 2 pointsize 1 title "d=11(Y)",\ + "circuit_level_with_y/d_13.txt" using 1:6 with linespoints lt rgb "orange" dashtype 3 linewidth 5 pointtype 2 pointsize 1 title "d=13(Y)" + +system("ps2pdf -dEPSCrop circuit_level_noise.eps circuit_level_noise.pdf") diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_11.txt b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_11.txt new file mode 100644 index 00000000..ae9a9402 --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_11.txt @@ -0,0 +1,21 @@ +0.4 11 11 79857 40007 0.5009830071252364 11 6.9e-3 0 +0.315478672 11 11 79830 40004 0.5011148690968308 11 6.9e-3 0 +0.199053585 11 11 80358 40004 0.4978222454516041 11 6.9e-3 0 +0.125594322 11 11 79721 40006 0.5018251150888724 11 6.9e-3 0 +0.0792446596 11 11 80011 40007 0.5000187474222294 11 6.9e-3 0 +0.05 11 11 80330 40004 0.4979957674592307 11 6.9e-3 0 +0.0315478672 11 11 80178 40006 0.4989648033126294 11 6.9e-3 0 +0.0199053585 11 11 83110 40007 0.48137408254121045 11 7.1e-3 0 +0.0125594322 11 11 168314 40000 0.2376510569530758 11 8.6e-3 0 +0.00792446596 11 11 1062019 40000 0.03766410958749326 11 9.6e-3 0 +0.005 11 11 12858500 40000 0.0031107827507096475 11 9.8e-3 0 +0.00315478672 11 11 26814844 5432 0.00020257436515386777 11 2.7e-2 0 +0.00199053585 11 11 33309250 406 0.000012188806412633128 11 9.7e-2 0 +0.00125594322 11 11 36301713 24 0.000000661125826211011 11 4.0e-1 0 +0.000792446596 11 11 39921400 1 0.000000025049221720681138 11 2.0e0 0 +0.0005 11 11 40584905 0 0 11 NaN 0 +0.000315478672 11 11 42043338 0 0 11 NaN 0 +0.000199053585 11 11 35666466 0 0 11 NaN 0 +0.000125594322 11 11 42376156 0 0 11 NaN 0 +0.0000792446596 11 11 43229428 0 0 11 NaN 0 +0.00005 11 11 36123725 0 0 11 NaN 0 diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_13.txt b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_13.txt new file mode 100644 index 00000000..96546df9 --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_13.txt @@ -0,0 +1,21 @@ +0.4 13 13 80401 40004 0.49755600054725685 13 6.9e-3 0 +0.315478672 13 13 79837 40006 0.501095983065496 13 6.9e-3 0 +0.199053585 13 13 80011 40004 0.49998125257777054 13 6.9e-3 0 +0.125594322 13 13 79963 40005 0.500293885922239 13 6.9e-3 0 +0.0792446596 13 13 79723 40008 0.5018376127340918 13 6.9e-3 0 +0.05 13 13 79727 40006 0.5017873493295872 13 6.9e-3 0 +0.0315478672 13 13 79824 40006 0.5011775906995389 13 6.9e-3 0 +0.0199053585 13 13 81181 40004 0.49277540311156554 13 7.0e-3 0 +0.0125594322 13 13 141323 40001 0.2830466378438046 13 8.3e-3 0 +0.00792446596 13 13 1083320 40000 0.0369235313665399 13 9.6e-3 0 +0.005 13 13 11322151 21590 0.0019068814750836656 13 1.3e-2 0 +0.00315478672 13 13 15435670 1089 0.00007055087339908147 13 5.9e-2 0 +0.00199053585 13 13 18994195 53 0.000002790326202294964 13 2.7e-1 0 +0.00125594322 13 13 21313144 0 0 13 NaN 0 +0.000792446596 13 13 23179065 0 0 13 NaN 0 +0.0005 13 13 24625193 0 0 13 NaN 0 +0.000315478672 13 13 25907142 0 0 13 NaN 0 +0.000199053585 13 13 26423072 0 0 13 NaN 0 +0.000125594322 13 13 27368016 0 0 13 NaN 0 +0.0000792446596 13 13 26423681 0 0 13 NaN 0 +0.00005 13 13 28014581 0 0 13 NaN 0 diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_3.txt b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_3.txt new file mode 100644 index 00000000..bf1e6c0a --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_3.txt @@ -0,0 +1,21 @@ +0.4 3 3 80185 40004 0.49889630230092913 3 6.9e-3 0 +0.315478672 3 3 80058 40007 0.49972519923055786 3 6.9e-3 0 +0.199053585 3 3 80058 40004 0.4996877263983612 3 6.9e-3 0 +0.125594322 3 3 80111 40003 0.49934465928524174 3 6.9e-3 0 +0.0792446596 3 3 86003 40005 0.46515819215608756 3 7.2e-3 0 +0.05 3 3 108256 40005 0.3695407182973692 3 7.8e-3 0 +0.0315478672 3 3 164158 40003 0.24368596108627055 3 8.5e-3 0 +0.0199053585 3 3 292140 40001 0.13692407749709043 3 9.1e-3 0 +0.0125594322 3 3 596465 40000 0.0670617722749868 3 9.5e-3 0 +0.00792446596 3 3 1301614 40000 0.030731076955226356 3 9.6e-3 0 +0.005 3 3 2964924 40000 0.013491070934701867 3 9.7e-3 0 +0.00315478672 3 3 7187926 40001 0.005565026685027086 3 9.8e-3 0 +0.00199053585 3 3 17261671 40000 0.0023172727599778723 3 9.8e-3 0 +0.00125594322 3 3 42259228 40000 0.0009465388246089115 3 9.8e-3 0 +0.000792446596 3 3 100000011 38266 0.00038265995790740464 3 1.0e-2 0 +0.0005 3 3 100000011 15484 0.00015483998296760189 3 1.6e-2 0 +0.000315478672 3 3 100000011 6129 0.00006128999325810074 3 2.5e-2 0 +0.000199053585 3 3 100000011 2433 0.000024329997323700296 3 4.0e-2 0 +0.000125594322 3 3 100000011 997 0.00000996999890330012 3 6.2e-2 0 +0.0000792446596 3 3 100000011 344 0.0000034399996216000414 3 1.1e-1 0 +0.00005 3 3 100000011 148 0.0000014799998372000179 3 1.6e-1 0 diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_5.txt b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_5.txt new file mode 100644 index 00000000..52b69c03 --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_5.txt @@ -0,0 +1,21 @@ +0.4 5 5 79793 40003 0.5013347035454238 5 6.9e-3 0 +0.315478672 5 5 80179 40003 0.49892116389578317 5 6.9e-3 0 +0.199053585 5 5 79799 40008 0.5013596661612301 5 6.9e-3 0 +0.125594322 5 5 80204 40007 0.49881552042292154 5 6.9e-3 0 +0.0792446596 5 5 80264 40007 0.4984426392903419 5 6.9e-3 0 +0.05 5 5 80886 40006 0.4945973345201889 5 7.0e-3 0 +0.0315478672 5 5 96301 40004 0.4154058628674676 5 7.5e-3 0 +0.0199053585 5 5 159999 40003 0.2500203126269539 5 8.5e-3 0 +0.0125594322 5 5 367859 40001 0.10874003354546172 5 9.3e-3 0 +0.00792446596 5 5 1102707 40000 0.03627436844057397 5 9.6e-3 0 +0.005 5 5 3712948 40001 0.010773380074269825 5 9.7e-3 0 +0.00315478672 5 5 13365351 40000 0.002992813282644055 5 9.8e-3 0 +0.00199053585 5 5 50735624 40000 0.0007884006708974349 5 9.8e-3 0 +0.00125594322 5 5 100000011 20320 0.00020319997764800245 5 1.4e-2 0 +0.000792446596 5 5 100000011 5111 0.00005110999437790062 5 2.7e-2 0 +0.0005 5 5 100000011 1326 0.000013259998541400161 5 5.4e-2 0 +0.000315478672 5 5 100000011 339 0.000003389999627100041 5 1.1e-1 0 +0.000199053585 5 5 100000011 92 0.0000009199998988000111 5 2.0e-1 0 +0.000125594322 5 5 100000011 21 0.00000020999997690000254 5 4.3e-1 0 +0.0000792446596 5 5 100000011 10 0.00000009999998900000121 5 6.2e-1 0 +0.00005 5 5 100000011 0 0 5 NaN 0 diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_7.txt b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_7.txt new file mode 100644 index 00000000..028ffaf9 --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_7.txt @@ -0,0 +1,21 @@ +0.4 7 7 79939 40005 0.500444088617571 7 6.9e-3 0 +0.315478672 7 7 79468 40004 0.5033975940001006 7 6.9e-3 0 +0.199053585 7 7 80274 40004 0.49834317462690286 7 6.9e-3 0 +0.125594322 7 7 79811 40007 0.5012717545200537 7 6.9e-3 0 +0.0792446596 7 7 80218 40008 0.4987409309631255 7 6.9e-3 0 +0.05 7 7 79913 40003 0.5005818827975423 7 6.9e-3 0 +0.0315478672 7 7 82641 40005 0.4840817511888772 7 7.0e-3 0 +0.0199053585 7 7 110637 40005 0.3615878955503132 7 7.8e-3 0 +0.0125594322 7 7 267787 40002 0.14937991762109437 7 9.0e-3 0 +0.00792446596 7 7 1035593 40000 0.03862521280078177 7 9.6e-3 0 +0.005 7 7 5259796 40000 0.007604857678890968 7 9.8e-3 0 +0.00315478672 7 7 30252231 40000 0.0013222165333855874 7 9.8e-3 0 +0.00199053585 7 7 100000011 21961 0.00021960997584290266 7 1.3e-2 0 +0.00125594322 7 7 100000011 3488 0.00003487999616320042 7 3.3e-2 0 +0.000792446596 7 7 100000011 535 0.000005349999411500065 7 8.5e-2 0 +0.0005 7 7 100000011 86 0.0000008599999054000104 7 2.1e-1 0 +0.000315478672 7 7 100000011 14 0.0000001399999846000017 7 5.2e-1 0 +0.000199053585 7 7 100000011 0 0 7 NaN 0 +0.000125594322 7 7 100000011 0 0 7 NaN 0 +0.0000792446596 7 7 100000011 0 0 7 NaN 0 +0.00005 7 7 100000011 0 0 7 NaN 0 diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_9.txt b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_9.txt new file mode 100644 index 00000000..33c46b25 --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/d_9.txt @@ -0,0 +1,21 @@ +0.4 9 9 80342 40004 0.4979213860745314 9 6.9e-3 0 +0.315478672 9 9 80140 40005 0.49918891939106563 9 6.9e-3 0 +0.199053585 9 9 80201 40004 0.49879677310756726 9 6.9e-3 0 +0.125594322 9 9 80237 40007 0.4986103667883894 9 6.9e-3 0 +0.0792446596 9 9 79458 40006 0.5034861184525158 9 6.9e-3 0 +0.05 9 9 79815 40008 0.5012591618116895 9 6.9e-3 0 +0.0315478672 9 9 80416 40005 0.4974756267409471 9 6.9e-3 0 +0.0199053585 9 9 90995 40007 0.43966151986372876 9 7.3e-3 0 +0.0125594322 9 9 207362 40001 0.19290419652588228 9 8.8e-3 0 +0.00792446596 9 9 1040993 40000 0.038424850119069 9 9.6e-3 0 +0.005 9 9 8122524 40001 0.004924700745728791 9 9.8e-3 0 +0.00315478672 9 9 44121881 23411 0.0005305984121574508 9 1.3e-2 0 +0.00199053585 9 9 51585179 2807 0.000054414854313096405 9 3.7e-2 0 +0.00125594322 9 9 61453996 319 0.000005190874813087826 9 1.1e-1 0 +0.000792446596 9 9 63094049 34 0.0000005388780802449372 9 3.4e-1 0 +0.0005 9 9 65707284 1 0.000000015219012857082936 9 2.0e0 0 +0.000315478672 9 9 75395215 0 0 9 NaN 0 +0.000199053585 9 9 77256910 0 0 9 NaN 0 +0.000125594322 9 9 78059885 0 0 9 NaN 0 +0.0000792446596 9 9 79175301 0 0 9 NaN 0 +0.00005 9 9 79526460 0 0 9 NaN 0 diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/run.py b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/run.py new file mode 100644 index 00000000..1e4740e2 --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/run.py @@ -0,0 +1,80 @@ +import os +import sys +import subprocess +import sys +qec_playground_root_dir = subprocess.run("git rev-parse --show-toplevel", cwd=os.path.dirname(os.path.abspath( + __file__)), shell=True, check=True, capture_output=True).stdout.decode(sys.stdout.encoding).strip(" \r\n") +rust_dir = os.path.join(qec_playground_root_dir, "backend", "rust") +fault_toleran_MWPM_dir = os.path.join( + qec_playground_root_dir, "benchmark", "fault_tolerant_MWPM") +sys.path.insert(0, fault_toleran_MWPM_dir) + +if True: + from automated_threshold_evaluation import qec_playground_benchmark_simulator_runner_vec_command + from automated_threshold_evaluation import run_qec_playground_command_get_stdout, compile_code_if_necessary + sys.path.insert(0, os.path.join(qec_playground_root_dir, + "benchmark", "slurm_utilities")) + import slurm_distribute + from slurm_distribute import slurm_threads_or as STO + from slurm_distribute import cpu_hours as CH + +# rotated surface code only supports odd number code distances +di_vec = [3, 5, 7, 9, 11, 13] +p_vec = [0.5 * (10 ** (- i / 5)) for i in range(5 * 4 + 1)] +p_vec[0] = 0.4 +min_error_cases = 40000 +max_N = 100000000 + +print(p_vec) + +slurm_distribute.SLURM_DISTRIBUTE_TIME = "1:20:00" +slurm_distribute.SLURM_DISTRIBUTE_MEM_PER_TASK = '8G' +# for more usuable machines, use `SLURM_USE_SCAVENGE_PARTITION=1` flag +slurm_distribute.SLURM_DISTRIBUTE_CPUS_PER_TASK = 12 +parameters = f"""-p{STO(0)} --time-budget {CH(10)} --code-type rotated-planar-code --decoder fusion --noise-model stim-noise-model --ignore-logical-i""".split(" ") + +compile_code_if_necessary() + + +@slurm_distribute.slurm_distribute_run(os.path.dirname(__file__)) +def experiment(slurm_commands_vec=None, run_command_get_stdout=run_qec_playground_command_get_stdout): + + for di in di_vec: + filename = os.path.join(os.path.dirname(__file__), f"d_{di}.txt") + + results = [] + for p in p_vec: + command = qec_playground_benchmark_simulator_runner_vec_command( + [p], [di], [di], [di], parameters, max_N=max_N, min_error_cases=min_error_cases) + if slurm_commands_vec is not None: + slurm_commands_vec.sanity_checked_append(command) + continue + print(" ".join(command)) + + # run experiment + stdout, returncode = run_command_get_stdout(command) + print("\n" + stdout) + assert returncode == 0, "command fails..." + + # full result + full_result = stdout.strip(" \r\n").split("\n")[-1] + lst = full_result.split(" ") + total_rounds = int(lst[3]) + error_count = int(lst[4]) + error_rate = float(lst[5]) + confidence_interval = float(lst[7]) + + # record result + print_result = f"{full_result}" + results.append(print_result) + print(print_result) + + if slurm_commands_vec is not None: + continue + + print("\n\n") + print("\n".join(results)) + print("\n\n") + + with open(filename, "w", encoding="utf-8") as f: + f.write("\n".join(results) + "\n") diff --git a/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/slurm_jobs/_aggregated.hjson b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/slurm_jobs/_aggregated.hjson new file mode 100644 index 00000000..53d6312f --- /dev/null +++ b/benchmark/paper_splitting_decoder/rotated_surface_code/circuit_level_normal/slurm_jobs/_aggregated.hjson @@ -0,0 +1,1136 @@ +[ + [ + /gpfs/gibbs/project/lin_zhong/yw729/QEC-Playground/target/release/qecp-cli tool benchmark '[3]' --djs '[3]' '[3]' -m100000000 -e40000 '[4.00000000e-01]' -p12 --time-budget 3000.0 --code-type rotated-planar-code --decoder fusion --noise-model stim-noise-model --ignore-logical-i + + ''' + format: