def test_run_seeded(): code = PlanarCode(5, 5) error_model = DepolarizingErrorModel() decoder = PlanarMPSDecoder() error_probability = 0.101 max_runs = 5 random_seed = 5 data1 = app.run(code, error_model, decoder, error_probability, max_runs=max_runs, random_seed=random_seed) data2 = app.run(code, error_model, decoder, error_probability, max_runs=max_runs, random_seed=random_seed) # remove wall_time from data for data in (data1, data2): del data['wall_time'] assert data1 == data2, 'Identically seeded runs are not the same. '
def test_run_invalid_override(decoding1, decoding2): decodings = itertools.cycle((decoding1, decoding2)) class _CycleDecoder(Decoder): def decode(self, code, syndrome, **kwargs): return next(decodings) @property def label(self): return 'Cycle' # should raise error due to inconsistent logical_commutations with pytest.raises(QecsimError): app.run(FiveQubitCode(), BitFlipErrorModel(), _CycleDecoder(), 0.0, max_runs=5)
def test_run_override(code, error, decoding, max_runs, expected_data): # test n_fail and n_logical_commutations when returning different data data = app.run(code, _FixedErrorModel(error), _FixedDecoder(decoding), 0.0, max_runs=max_runs) print(data) assert data['n_fail'] == expected_data['n_fail'] assert data['n_logical_commutations'] == expected_data['n_logical_commutations'] assert data['custom_totals'] == expected_data['custom_totals']
def test_run_physical_error_rate(code, error_model, decoder, error_probability): max_runs = 100 # Need to repeat many times to ensure physical_error_rate is close to error_probability data = app.run(code, error_model, decoder, error_probability, max_runs) # no error raised for key in ('error_probability', 'physical_error_rate', 'error_weight_pvar'): assert key in data, 'data={} does not contain key={}'.format(data, key) e_prob = data['error_probability'] p_rate = data['physical_error_rate'] p_var = data['error_weight_pvar'] / (data['n_k_d'][0] ** 2) # physical_error_rate_pvar (power of 2 is correct) p_std = math.sqrt(p_var) # physical_error_rate_std assert p_rate - p_std < e_prob < p_rate + p_std, ( 'physical_error_rate={} is not within 1 std={} of error_probability={}'.format(p_rate, p_std, e_prob))
def test_file_error_model_generated_sample_error_probability(code, filename, decoder): with CliRunner().isolated_filesystem(): # isolate from logging_qecsim.ini # error model and probability from sample error_model = FileErrorModel(filename, start=1000) e_prob = error_model._probability # runs (repeat many times to ensure physical_error_rate is close to error_probability) max_runs = 100 data = app.run(code, error_model, decoder, e_prob, max_runs) # no error raised p_rate = data['physical_error_rate'] p_var = data['error_weight_pvar'] / (data['n_k_d'][0] ** 2) # physical_error_rate_pvar (power of 2 is correct) p_std = math.sqrt(p_var) # physical_error_rate_std assert p_rate - p_std < e_prob < p_rate + p_std, ( 'physical_error_rate={} is not within 1 std={} of error_probability={}'.format(p_rate, p_std, e_prob))
def run(code, error_model, decoder, error_probabilities, max_failures, max_runs, output, random_seed): """ Simulate quantum error correction. Arguments: \b CODE Stabilizer code in format name(<args>) #CODE_PARAMETERS# \b ERROR_MODEL Error model in format name(<args>) #ERROR_MODEL_PARAMETERS# \b DECODER Decoder in format name(<args>) #DECODER_PARAMETERS# \b ERROR_PROBABILITY... One or more probabilities as FLOAT in [0.0, 1.0] Examples: qecsim run -r10 "five_qubit" "generic.depolarizing" "generic.naive" 0.1 qecsim run -f5 -r50 -s13 "steane" "generic.phase_flip" "generic.naive" 0.1 qecsim run -r20 "planar(7,7)" "generic.bit_flip" "planar.mps(6)" 0.101 0.102 0.103 qecsim run -r10 "color666(7)" "generic.bit_flip" "color666.mps(16)" 0.09 0.10 qecsim run -o"data.json" -f9 "toric(3,3)" "generic.bit_flip" "toric.mwpm" 0.1 """ # INPUT code.validate() logger.info('RUN STARTING: code={}, error_model={}, decoder={}, error_probabilities={}, max_failures={}, ' 'max_runs={}, random_seed={}.' .format(code, error_model, decoder, error_probabilities, max_failures, max_runs, random_seed)) # RUN data = [] for error_probability in error_probabilities: runs_data = app.run(code, error_model, decoder, error_probability, max_runs=max_runs, max_failures=max_failures, random_seed=random_seed) data.append(runs_data) logger.info('RUN COMPLETE: data={}'.format(data)) # OUTPUT _write_data(output, data)
def test_run_count(max_runs, max_failures): code = FiveQubitCode() error_model = BitPhaseFlipErrorModel() decoder = NaiveDecoder() error_probability = 0.05 data = app.run(code, error_model, decoder, error_probability, max_runs=max_runs, max_failures=max_failures) # no error raised assert {'n_run', 'n_fail'} <= data.keys(), 'data={} missing count keys' if max_runs is None and max_failures is None: assert data['n_run'] == 1, 'n_run does not equal 1 when max_runs and max_failures unspecified' if max_runs is not None: assert data['n_run'] <= max_runs, ('n_run is not <= requested max_runs (data={}).'.format(data)) if max_failures is not None: assert data['n_fail'] <= max_failures, ('n_fail is not <= requested max_failures (data={}).'.format(data))
def test_run(code, error_model, decoder): error_probability = 0.15 max_runs = 2 data = app.run(code, error_model, decoder, error_probability, max_runs) # no error raised expected_keys = {'code', 'n_k_d', 'error_model', 'decoder', 'error_probability', 'time_steps', 'measurement_error_probability', 'n_run', 'n_success', 'n_fail', 'n_logical_commutations', 'custom_totals', 'error_weight_total', 'error_weight_pvar', 'logical_failure_rate', 'physical_error_rate', 'wall_time'} assert data.keys() == expected_keys, 'data={} has missing/extra keys' assert data['n_run'] == max_runs, 'n_run does not equal requested max_runs (data={}).'.format(data) assert data['n_success'] + data['n_fail'] == max_runs, ( 'n_success + n_fail does not equal requested max_runs (data={}).'.format(data)) assert data['n_success'] >= 0, 'n_success is negative (data={}).'.format(data) assert data['n_fail'] >= 0, 'n_fail is negative (data={}).'.format(data) assert data['n_fail'] <= sum(data['n_logical_commutations']), ( 'n_fail exceeds n_logical_commutations (data={}).'.format(data)) assert data['logical_failure_rate'] == data['n_fail'] / data['n_run']
def test_threequbit_error_rate_reduction(p): """Test that the 3-qubit code with bit-flip noise and minimum-weight decoding reduces the error rate as expected.""" # calculate expected logical error rate # 3 ways to fail with 2 bit-flips and 1 way to fail with 3 bit-flips expected_logical_p = 3 * (1 - p) * p**2 + p**3 # initialise models code = ThreeQubitCode() error_model = ThreeQubitBitFlipErrorModel() decoder = ThreeQubitLookupDecoder() # run simulations (with seeded random number generator for test consistency) data = app.run(code, error_model, decoder, p, max_runs=1000, random_seed=13) # extract logical error rate recorded_logical_p = data['logical_failure_rate'] # check logical error rate is less than physical error rate assert recorded_logical_p < p # check logical error rate is within 20% of expected logical error rate assert math.isclose(expected_logical_p, recorded_logical_p, rel_tol=0.2)
def parallel_step_p(code, error_model, decoder, max_runs, error_probability): return app.run(code, error_model, decoder, error_probability, max_runs=100)
def test_run_invalid_parameters(error_probability): with pytest.raises(ValueError) as exc_info: app.run(FiveQubitCode(), DepolarizingErrorModel(), NaiveDecoder(), error_probability, max_runs=2) print(exc_info)