def test_planar_rmps_decoder_correlated_errors(): # check MPS decoder successfully decodes for error # I--+--I--+--I # I I # Y--+--I--+--Y # I I # I--+--I--+--I # and MWPM decoder fails as expected code = PlanarCode(3, 3) error = code.new_pauli().site('Y', (2, 0), (2, 4)).to_bsf() syndrome = pt.bsp(error, code.stabilizers.T) # MPS decoder decoder = PlanarRMPSDecoder() recovery = decoder.decode(code, syndrome) # check recovery ^ error commutes with stabilizers (by construction) assert np.all(pt.bsp(recovery ^ error, code.stabilizers.T) == 0), ( 'recovery ^ error ({} ^ {}) does not commute with stabilizers for MPS decoder.' .format(recovery, error)) # check recovery ^ error commutes with logicals (we expect this to succeed for MPS) assert np.all(pt.bsp(recovery ^ error, code.logicals.T) == 0), ( 'recovery ^ error ({} ^ {}) does not commute with logicals for MPS decoder.' .format(recovery, error)) # MWPM decoder decoder = PlanarMWPMDecoder() recovery = decoder.decode(code, syndrome) # check recovery ^ error commutes with stabilizers (by construction) assert np.all(pt.bsp(recovery ^ error, code.stabilizers.T) == 0), ( 'recovery ^ error ({} ^ {}) does not commute with stabilizers for MWPM decoder.' .format(recovery, error)) # check recovery ^ error commutes with logicals (we expect this to fail for MWPM) assert not np.all(pt.bsp(recovery ^ error, code.logicals.T) == 0), ( 'recovery ^ error ({} ^ {}) does commute with logicals for MWPM decoder.' .format(recovery, error))
def test_planar_rmps_decoder_cosets_probability_equivalence( sample_pauli_f, sample_pauli_g): decoder = PlanarRMPSDecoder(chi=8) # probabilities prob_dist = DepolarizingErrorModel().probability_distribution(0.1) # coset probabilities coset_f_ps, _ = decoder._coset_probabilities(prob_dist, sample_pauli_f) coset_g_ps, _ = decoder._coset_probabilities(prob_dist, sample_pauli_g) print('#Pr(fG)=', coset_f_ps) print('#Pr(gG)=', coset_g_ps) assert all(_is_close( coset_f_ps, coset_g_ps, rtol=1e-9, atol=0)), ('Coset probabilites do not satisfy Pr(fG) ~= Pr(gG)')
def test_planar_rmps_mps_accuracy(error_pauli): error = error_pauli.to_bsf() code = error_pauli.code syndrome = pt.bsp(error, code.stabilizers.T) recovery_pauli = PlanarRMPSDecoder.sample_recovery(code, syndrome) prob_dist = DepolarizingErrorModel().probability_distribution(0.1) rmps_coset_ps, _ = PlanarRMPSDecoder(chi=8)._coset_probabilities( prob_dist, recovery_pauli) print('#rmps_coset_ps (chi=8)=', rmps_coset_ps) mps_coset_ps, _ = PlanarMPSDecoder(chi=8)._coset_probabilities( prob_dist, recovery_pauli) print('#mps_coset_ps (chi=8)=', mps_coset_ps) assert all(_is_close( rmps_coset_ps, mps_coset_ps, rtol=1e-1, atol=0)), ('rmps_coset_ps (chi=8) not close to mps_coset_ps (chi=8)')
def test_planar_rmps_decoder_cosets_probability_stp(): # parameters sample = PlanarCode(3, 4).new_pauli().site('Y', (2, 0), (2, 4)) prob_dist = DepolarizingErrorModel().probability_distribution(0.1) # coset probabilities exact exact_coset_ps, _ = PlanarRMPSDecoder(mode='a')._coset_probabilities( prob_dist, sample) print('#exact_coset_ps=', exact_coset_ps) # coset probabilities approx (chi=6) approx_coset_ps, _ = PlanarRMPSDecoder(chi=6, mode='a')._coset_probabilities( prob_dist, sample) print('#approx_coset_ps=', approx_coset_ps) assert all( _is_close(exact_coset_ps, approx_coset_ps, rtol=1e-14, atol=0)), ('approx_coset_ps not close to exact_coset_ps') # coset probabilities approx (chi=6, stp=0) coset_ps, _ = PlanarRMPSDecoder(chi=6, mode='a', stp=0)._coset_probabilities( prob_dist, sample) print('#coset_ps (chi=6, stp=0)=', coset_ps) assert all(_is_close( approx_coset_ps, coset_ps, rtol=0, atol=0)), ('coset_ps (chi=6, stp=0) not equal to approx_coset_ps') # coset probabilities approx (chi=6, stp=1) coset_ps, _ = PlanarRMPSDecoder(chi=6, mode='a', stp=1)._coset_probabilities( prob_dist, sample) print('#coset_ps (chi=6, stp=1)=', coset_ps) assert all(_is_close( exact_coset_ps, coset_ps, rtol=0, atol=0)), ('coset_ps (chi=6, stp=1) not equal to exact_coset_ps') # coset probabilities approx (chi=6, stp=0.5) coset_ps, _ = PlanarRMPSDecoder(chi=6, mode='a', stp=0.5)._coset_probabilities( prob_dist, sample) print('#coset_ps (chi=6, stp=0.5)=', coset_ps) assert all(_is_close( exact_coset_ps, coset_ps, rtol=1e-10, atol=0)), ('coset_ps (chi=6, stp=0.5) not close to exact_coset_ps') assert all(_is_close( approx_coset_ps, coset_ps, rtol=1e-10, atol=0)), ('coset_ps (chi=6, stp=0.5) not close to approx_coset_ps')
def test_planar_rmps_decoder_decode(error_pauli, chi, caplog): with caplog.at_level(logging.WARN): error = error_pauli.to_bsf() code = error_pauli.code syndrome = pt.bsp(error, code.stabilizers.T) decoder = PlanarRMPSDecoder(chi=chi) recovery = decoder.decode(code, syndrome) assert np.array_equal(pt.bsp( recovery, code.stabilizers.T), syndrome), ( 'recovery {} does not give the same syndrome as the error {}'. format(recovery, error)) assert np.all(pt.bsp(recovery ^ error, code.stabilizers.T) == 0), ( 'recovery ^ error ({} ^ {}) does not commute with stabilizers.'. format(recovery, error)) assert len(caplog.records) == 0, 'Unexpected log messages: {}'.format( caplog.text)
def test_planar_rmps_decoder_sample_recovery(error_pauli): error = error_pauli.to_bsf() code = error_pauli.code syndrome = pt.bsp(error, code.stabilizers.T) recovery_pauli = PlanarRMPSDecoder.sample_recovery(code, syndrome) recovery = recovery_pauli.to_bsf() assert np.array_equal(pt.bsp(recovery, code.stabilizers.T), syndrome), ( 'recovery {} does not give the same syndrome as the error {}'.format( recovery, error)) assert np.all(pt.bsp(recovery ^ error, code.stabilizers.T) == 0), ( 'recovery ^ error ({} ^ {}) does not commute with stabilizers.'.format( recovery, error))
def test_planar_rmps_decoder_cosets_probability_inequality(mode, rtol): code = PlanarCode(25, 25) decoder = PlanarRMPSDecoder(chi=5, mode=mode) # probabilities prob_dist = DepolarizingErrorModel().probability_distribution(0.1) # coset probabilities for null Pauli coset_ps, _ = decoder._coset_probabilities(prob_dist, code.new_pauli()) coset_i_p, coset_x_p, coset_y_p, coset_z_p = coset_ps # expect Pr(IG) > Pr(XG) ~= Pr(ZG) > Pr(YG) print('{} > {} ~= {} > {}. rtol={}'.format( coset_i_p, coset_x_p, coset_z_p, coset_y_p, abs(coset_x_p - coset_z_p) / abs(coset_z_p))) print('types: Pr(IG):{}, Pr(XG):{}, Pr(ZG):{}, Pr(YG):{}'.format( type(coset_i_p), type(coset_x_p), type(coset_z_p), type(coset_y_p))) assert coset_i_p > coset_x_p, 'Coset probabilites do not satisfy Pr(IG) > Pr(XG)' assert coset_i_p > coset_z_p, 'Coset probabilites do not satisfy Pr(IG) > Pr(ZG)' assert _is_close( coset_x_p, coset_z_p, rtol=rtol, atol=0), 'Coset probabilites do not satisfy Pr(XG) ~= Pr(ZG)' assert coset_x_p > coset_y_p, 'Coset probabilites do not satisfy Pr(XG) > Pr(YG)' assert coset_z_p > coset_y_p, 'Coset probabilites do not satisfy Pr(ZG) > Pr(YG)'
def test_planar_rmps_mps_performance(): n_run = 5 code = PlanarCode(21, 21) error_model = DepolarizingErrorModel() error_probability = 0.2 def _timed_runs(decoder): start_time = time.time() for _ in range(n_run): error = error_model.generate(code, error_probability) syndrome = pt.bsp(error, code.stabilizers.T) recovery = decoder.decode(code, syndrome) assert np.all(pt.bsp(recovery ^ error, code.stabilizers.T) == 0), ( 'recovery ^ error ({} ^ {}) does not commute with stabilizers.' .format(recovery, error)) return time.time() - start_time rmps_time = _timed_runs(PlanarRMPSDecoder(chi=8)) mps_time = _timed_runs(PlanarMPSDecoder(chi=8)) # expect rmps_time < mps_time print('rmps_time = {} < {} = mps_time'.format(rmps_time, mps_time)) assert rmps_time < mps_time, 'RMPS decoder slower than MPS decoder'
def test_planar_rmps_decoder_small_codes_exact_approx(): code = PlanarCode(4, 4) exact_decoder = PlanarRMPSDecoder() approx_decoder = PlanarRMPSDecoder(chi=8) identity = code.new_pauli() # probabilities prob_dist = BiasedDepolarizingErrorModel(bias=10).probability_distribution( probability=0.1) # coset probabilities exact_coset_ps, _ = exact_decoder._coset_probabilities(prob_dist, identity) approx_coset_ps, _ = approx_decoder._coset_probabilities( prob_dist, identity) print('#exact Pr(G)=', exact_coset_ps) print('#approx Pr(G)=', approx_coset_ps) assert all(_is_close( exact_coset_ps, approx_coset_ps, rtol=1e-11, atol=0)), ( 'Coset probabilites do not satisfy exact Pr(G) ~= approx Pr(G)')
def test_planar_rmps_decoder_new_invalid_parameters(chi, mode, stp, tol): with pytest.raises((ValueError, TypeError), match=r"^PlanarRMPSDecoder") as exc_info: PlanarRMPSDecoder(chi=chi, mode=mode, stp=stp, tol=tol) print(exc_info)
def test_planar_rmps_decoder_new_valid_parameters(chi, mode, stp, tol): PlanarRMPSDecoder(chi=chi, mode=mode, stp=stp, tol=tol) # no error raised
def test_planar_rmps_decoder_properties(): decoder = PlanarRMPSDecoder(chi=8, mode='r', stp=0.5, tol=1e-14) assert isinstance(decoder.label, str) assert isinstance(repr(decoder), str) assert isinstance(str(decoder), str)
def test_planar_rmps_decoder_cosets_probability_pair_optimisation(shape, mode): code = PlanarCode(*shape) decoder = PlanarRMPSDecoder(mode=mode) # probabilities prob_dist = BiasedDepolarizingErrorModel( bias=10).probability_distribution(0.1) # coset probabilities for null Pauli coset_i_ps, _ = decoder._coset_probabilities(prob_dist, code.new_pauli()) # X coset_x_ps, _ = decoder._coset_probabilities(prob_dist, code.new_pauli().logical_x()) # expect Pr(iIG) ~= Pr(xXG) assert _is_close( coset_i_ps[0], coset_x_ps[1], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iIG) ~= Pr(xXG)') # expect Pr(iXG) ~= Pr(xIG) assert _is_close( coset_i_ps[1], coset_x_ps[0], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iXG) ~= Pr(xIG)') # expect Pr(iYG) ~= Pr(xZG) assert _is_close( coset_i_ps[2], coset_x_ps[3], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iYG) ~= Pr(xZG)') # expect Pr(iZG) ~= Pr(xYG) assert _is_close( coset_i_ps[3], coset_x_ps[2], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iZG) ~= Pr(xYG)') # Y coset_y_ps, _ = decoder._coset_probabilities( prob_dist, code.new_pauli().logical_x().logical_z()) # expect Pr(iIG) ~= Pr(yYG) assert _is_close( coset_i_ps[0], coset_y_ps[2], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iIG) ~= Pr(yYG)') # expect Pr(iXG) ~= Pr(yZG) assert _is_close( coset_i_ps[1], coset_y_ps[3], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iXG) ~= Pr(yZG)') # expect Pr(iYG) ~= Pr(yIG) assert _is_close( coset_i_ps[2], coset_y_ps[0], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iYG) ~= Pr(yIG)') # expect Pr(iZG) ~= Pr(yXG) assert _is_close( coset_i_ps[3], coset_y_ps[1], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iZG) ~= Pr(yXG)') # Z coset_z_ps, _ = decoder._coset_probabilities(prob_dist, code.new_pauli().logical_z()) # expect Pr(iIG) ~= Pr(zZG) assert _is_close( coset_i_ps[0], coset_z_ps[3], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iIG) ~= Pr(zZG)') # expect Pr(iXG) ~= Pr(zYG) assert _is_close( coset_i_ps[1], coset_z_ps[2], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iXG) ~= Pr(zYG)') # expect Pr(iYG) ~= Pr(zXG) assert _is_close( coset_i_ps[2], coset_z_ps[1], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iYG) ~= Pr(zXG)') # expect Pr(iZG) ~= Pr(zIG) assert _is_close( coset_i_ps[3], coset_z_ps[0], rtol=1e-15, atol=0), ('Coset probabilites do not satisfy Pr(iZG) ~= Pr(zIG)')
def decode(self, code, syndrome, **kwargs): return self.decoding @property def label(self): return 'fixed' @pytest.mark.parametrize('code, error_model, decoder', [ # each code with each valid decoder (Color666Code(5), DepolarizingErrorModel(), Color666MPSDecoder(chi=8)), (FiveQubitCode(), DepolarizingErrorModel(), NaiveDecoder()), (PlanarCode(5, 5), DepolarizingErrorModel(), PlanarCMWPMDecoder()), (PlanarCode(5, 5), DepolarizingErrorModel(), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), DepolarizingErrorModel(), PlanarMWPMDecoder()), (PlanarCode(5, 5), DepolarizingErrorModel(), PlanarRMPSDecoder(chi=6)), (PlanarCode(4, 5), BitPhaseFlipErrorModel(), PlanarYDecoder()), (RotatedPlanarCode(7, 7), DepolarizingErrorModel(), RotatedPlanarMPSDecoder(chi=8)), (RotatedPlanarCode(7, 7), DepolarizingErrorModel(), RotatedPlanarRMPSDecoder(chi=8)), (RotatedPlanarCode(7, 7), BiasedDepolarizingErrorModel(100), RotatedPlanarSMWPMDecoder()), (RotatedToricCode(6, 6), BiasedDepolarizingErrorModel(100), RotatedToricSMWPMDecoder()), (SteaneCode(), DepolarizingErrorModel(), NaiveDecoder()), (ToricCode(5, 5), DepolarizingErrorModel(), ToricMWPMDecoder()), # each generic noise model (PlanarCode(5, 5), BiasedDepolarizingErrorModel(10), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), BiasedYXErrorModel(10), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), BitFlipErrorModel(), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), BitPhaseFlipErrorModel(), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), CenterSliceErrorModel((0.2, 0.8, 0), 0.5), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), DepolarizingErrorModel(), PlanarMPSDecoder(chi=6)), (PlanarCode(5, 5), PhaseFlipErrorModel(), PlanarMPSDecoder(chi=6)),