def test_measurement_error_probabilities_and_probability_raises_value_error(): H = np.array([[1, 1, 0], [0, 1, 1]]) with pytest.raises(ValueError): m = Matching() m.load_from_check_matrix(H, spacelike_weights=np.array([0.3, 0.7, 0.9]), measurement_error_probabilities=[0.1, 0.1], repetitions=3, measurement_error_probability=[0.1, 0.1])
def test_local_matching_clusters(cluster_size): g = nx.Graph() qid = 0 for i in range(cluster_size): g.add_edge(i, i + 1, weight=1.0, fault_ids=qid) qid += 1 g.add_edge(cluster_size, cluster_size + 1, weight=3 * cluster_size, fault_ids=qid) qid += 1 for i in range(cluster_size + 1, 2 * cluster_size + 1): g.add_edge(i, i + 1, weight=1.0, fault_ids=qid) qid += 1 m = Matching(g) m.decode(np.ones((cluster_size + 1) * 2), num_neighbours=cluster_size) for i in range(1, cluster_size + 1): with pytest.raises(BlossomFailureException): local_matching(m.matching_graph, np.arange(m.num_detectors), num_neighbours=i, max_attempts=1) for i in range(cluster_size + 1, 2 * cluster_size): local_matching(m.matching_graph, np.arange(m.num_detectors), num_neighbours=i, max_attempts=1) local_matching(m.matching_graph, np.arange(m.num_detectors), num_neighbours=1, max_attempts=int(np.log2(cluster_size + 1)) + 2)
def test_mwpm_from_networkx(): g = nx.Graph() g.add_edge(0, 1, fault_ids=0) g.add_edge(0, 2, fault_ids=1) g.add_edge(1, 2, fault_ids=2) m = Matching(g) assert(isinstance(m.matching_graph, MatchingGraph)) assert(m.num_detectors == 3) assert(m.num_fault_ids == 3) assert(m.matching_graph.distance(0,2) == 1) assert(m.matching_graph.shortest_path(0,2) == [0,2]) g = nx.Graph() g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) m = Matching(g) assert(isinstance(m.matching_graph, MatchingGraph)) assert(m.num_detectors == 3) assert(m.num_fault_ids == 0) assert(m.matching_graph.distance(0,2) == 1) assert(m.matching_graph.shortest_path(0,2) == [0,2]) g = nx.Graph() g.add_edge(0, 1, weight=1.5) g.add_edge(0, 2, weight=1.7) g.add_edge(1, 2, weight=1.2) m = Matching(g) assert(isinstance(m.matching_graph, MatchingGraph)) assert(m.num_detectors == 3) assert(m.num_fault_ids == 0) assert(m.matching_graph.distance(0,2) == pytest.approx(1.7)) assert(m.matching_graph.shortest_path(0,2) == [0,2])
def test_timelike_weights(t_weights, expected_edges): H = np.array([[1, 1, 0], [0, 1, 1]]) m = Matching() m.load_from_check_matrix(H, spacelike_weights=np.array([0.3, 0.7, 0.9]), timelike_weights=t_weights, repetitions=3) es = set((tuple(sorted([u, v])), d["weight"]) for u, v, d in m.edges()) assert es == expected_edges
def test_weighted_mwpm_from_array(): H = csc_matrix([[1,0],[1,1],[0,1]]) m = Matching(H, spacelike_weights=np.array([1., 2.])) assert m.matching_graph.distance(0, 1) == 1. assert m.matching_graph.distance(1, 2) == 2. with pytest.raises(ValueError): m = Matching(H, spacelike_weights=np.array([1.]))
def test_bad_syndrome_raises_value_error(): g = nx.Graph() g.add_edge(0, 1, fault_ids=0) g.add_edge(1, 2, fault_ids=1) m = Matching(g) with pytest.raises(TypeError): m.decode('test')
def test_decode_with_multiple_components(): g = nx.Graph() g.add_edge(0, 1) g.add_edge(1, 2) g.add_edge(2, 0) g.add_edge(3, 4) g.add_edge(4, 5) g.add_edge(3, 5) m = Matching(g) for z in (np.array([0]), np.arange(6)): with pytest.raises(ValueError): local_matching(m.matching_graph, z) with pytest.raises(ValueError): exact_matching(m.matching_graph, z) g.nodes[0]['is_boundary'] = True m2 = Matching(g) local_matching(m2.matching_graph, np.array([1])) exact_matching(m2.matching_graph, np.array([1])) for z in (np.arange(6), np.array([3])): with pytest.raises(ValueError): local_matching(m2.matching_graph, z) with pytest.raises(ValueError): exact_matching(m2.matching_graph, z) g.nodes[4]['is_boundary'] = True m3 = Matching(g) for z in (np.array([0]), np.arange(6), np.array([3]), np.array([1, 3])): local_matching(m3.matching_graph, z) exact_matching(m3.matching_graph, z)
def test_bad_syndrome_raises_value_error(): g = nx.Graph() g.add_edge(0, 1, qubit_id=0) g.add_edge(1, 2, qubit_id=1) m = Matching(g) with pytest.raises(ValueError): noise = m.decode('test')
def test_negative_weight_raises_value_error(): g = nx.Graph() g.add_edge(0,1,weight=-1) with pytest.raises(ValueError): Matching(g) with pytest.raises(ValueError): Matching(csr_matrix([[1,1,0],[0,1,1]]), spacelike_weights=np.array([1,1,-1]))
def test_mwmpm_from_networkx(): g = nx.Graph() g.add_edge(0, 1, qubit_id=0) g.add_edge(0, 2, qubit_id=1) g.add_edge(1, 2, qubit_id=2) m = Matching(g) assert(isinstance(m.stabiliser_graph, WeightedStabiliserGraph)) assert(m.num_stabilisers == 3) assert(m.num_qubits == 3) assert(m.stabiliser_graph.distance(0,2) == 1) assert(m.stabiliser_graph.shortest_path(0,2) == [0,2]) g = nx.Graph() g.add_edge(0, 1) g.add_edge(0, 2) g.add_edge(1, 2) m = Matching(g) assert(isinstance(m.stabiliser_graph, WeightedStabiliserGraph)) assert(m.num_stabilisers == 3) assert(m.num_qubits == 0) assert(m.stabiliser_graph.distance(0,2) == 1) assert(m.stabiliser_graph.shortest_path(0,2) == [0,2]) g = nx.Graph() g.add_edge(0, 1, weight=1.5) g.add_edge(0, 2, weight=1.7) g.add_edge(1, 2, weight=1.2) m = Matching(g) assert(isinstance(m.stabiliser_graph, WeightedStabiliserGraph)) assert(m.num_stabilisers == 3) assert(m.num_qubits == 0) assert(m.stabiliser_graph.distance(0,2) == pytest.approx(1.7)) assert(m.stabiliser_graph.shortest_path(0,2) == [0,2])
def test_load_from_networkx_raises_value_error_if_qubit_id_and_fault_ids_both_supplied(): with pytest.raises(ValueError): g = nx.Graph() g.add_edge(0, 1, qubit_id=0, fault_ids=0) g.add_edge(1, 2, qubit_id=1, fault_ids=1) m = Matching() m.load_from_networkx(g)
def test_decode_all_neighbours(): g = nx.Graph() g.add_edge(0, 1, qubit_id=0) g.add_edge(1, 2, qubit_id=1) m = Matching(g) noise = m.decode([1,0,1], num_neighbours=None) assert np.array_equal(noise, np.array([1,1]))
def test_precompute_shortest_paths(): g = nx.Graph() g.add_edge(0, 1, qubit_id=0) g.add_edge(1, 2, qubit_id=1) m = Matching(g) assert not m.stabiliser_graph.has_computed_all_pairs_shortest_paths() m2 = Matching(g, precompute_shortest_paths=True) assert m2.stabiliser_graph.has_computed_all_pairs_shortest_paths()
def test_precompute_shortest_paths(): g = nx.Graph() g.add_edge(0, 1, fault_ids=0) g.add_edge(1, 2, fault_ids=1) m = Matching(g) assert not m.matching_graph.has_computed_all_pairs_shortest_paths() m2 = Matching(g, precompute_shortest_paths=True) assert m2.matching_graph.has_computed_all_pairs_shortest_paths()
def test_double_weight_matching(): w = nx.Graph() w.add_edge(0, 1, qubit_id=0, weight=0.97) w.add_edge(2, 3, qubit_id=1, weight=1.98) w.add_edge(0, 2, qubit_id=2, weight=1.1) w.add_edge(1, 3, qubit_id=3, weight=1.2) m = Matching(w) assert (list(m.decode(np.array([1, 1, 1, 1]))) == list(np.array([0, 0, 1, 1])))
def test_boundary_from_check_matrix(): H = csr_matrix(np.array([[1,1,0,0,0],[0,1,1,0,0], [0,0,1,1,0],[0,0,0,1,1]])) m = Matching(H) assert m.boundary == [4] assert np.array_equal(m.decode(np.array([1,0,0,0])), np.array([1,0,0,0,0])) assert np.array_equal(m.decode(np.array([0,1,0,0])), np.array([1,1,0,0,0])) assert np.array_equal(m.decode(np.array([0,1,1,0])), np.array([0,0,1,0,0])) assert np.array_equal(m.decode(np.array([0,0,1,0])), np.array([0,0,0,1,1]))
def test_bad_qubit_id_raises_value_error(): g = nx.Graph() g.add_edge(0,1, qubit_id='test') with pytest.raises(ValueError): m = Matching(g) g = nx.Graph() g.add_edge(0,1, qubit_id=[[1],[2]]) with pytest.raises(ValueError): m = Matching(g)
def test_mwpm_noisy_decode(n, z_err, c_expected): fn = "css_2D-toric_(4,4)_[[18,2,3]]_Hx.npz" H = load_npz(os.path.join(TEST_DIR, 'data', fn)) m = Matching(H, repetitions=z_err.shape[1]) n_all = np.cumsum(n, 0) % 2 z_noiseless = H.dot(n_all.T) % 2 z_noisy = (z_noiseless + z_err) % 2 z_noisy[:,1:] = (z_noisy[:,1:] - z_noisy[:,:-1]) % 2 c = m.decode(z_noisy) assert(np.array_equal(c, c_expected))
def test_negative_and_positive_in_matching(nn): g = nx.Graph() g.add_edge(0, 1, fault_ids=0, weight=1) g.add_edge(1, 2, fault_ids=1, weight=-10) g.add_edge(2, 3, fault_ids=2, weight=1) g.add_edge(3, 0, fault_ids=3, weight=1) m = Matching(g) c, w = m.decode([0, 1, 0, 1], return_weight=True, num_neighbours=nn) assert np.array_equal(c, np.array([0, 1, 1, 0])) assert w == -9
def test_mwpm_decode_method(): fn = "css_2D-toric_(4,4)_[[18,2,3]]_Hx.npz" H = load_npz(os.path.join(TEST_DIR, 'data', fn)) m = Matching(H) n = np.zeros(H.shape[1], dtype=int) n[5] = 1 n[10] = 1 z = H.dot(n) % 2 c = m.decode(z) assert(np.array_equal(c,n))
def test_unweighted_stabiliser_graph_from_networkx(): w = nx.Graph() w.add_edge(0, 1, qubit_id=0, weight=7.0) w.add_edge(0, 5, qubit_id=1, weight=14.0) w.add_edge(0, 2, qubit_id=2, weight=9.0) w.add_edge(1, 2, qubit_id=-1, weight=10.0) w.add_edge(1, 3, qubit_id=3, weight=15.0) w.add_edge(2, 5, qubit_id=4, weight=2.0) w.add_edge(2, 3, qubit_id=-1, weight=11.0) w.add_edge(3, 4, qubit_id=5, weight=6.0) w.add_edge(4, 5, qubit_id=6, weight=9.0) m = Matching(w) assert(m.num_qubits == 7) assert(m.num_stabilisers == 6) assert(m.stabiliser_graph.shortest_path(3, 5) == [3, 2, 5]) assert(m.stabiliser_graph.distance(5, 0) == pytest.approx(11.0)) assert(np.array_equal( m.decode(np.array([1,0,1,0,0,0])), np.array([0,0,1,0,0,0,0])) ) with pytest.raises(ValueError): m.decode(np.array([1,1,0])) with pytest.raises(ValueError): m.decode(np.array([1,1,1,0,0,0])) assert(np.array_equal( m.decode(np.array([1,0,0,0,0,1])), np.array([0,0,1,0,1,0,0])) ) assert(np.array_equal( m.decode(np.array([0,1,0,0,0,1])), np.array([0,0,0,0,1,0,0])) )
def test_draw_matching(): g = nx.Graph() g.add_edge(0, 1, qubit_id={0}, weight=1.1, error_probability=0.1) g.add_edge(1, 2, qubit_id={1}, weight=2.1, error_probability=0.2) g.add_edge(2, 3, qubit_id={2,3}, weight=0.9, error_probability=0.3) g.nodes[0]['is_boundary'] = True g.nodes[3]['is_boundary'] = True g.add_edge(0, 3, weight=0.0) m = Matching(g) plt.figure() m.draw()
def test_repr(): g = nx.Graph() g.add_edge(0, 1, fault_ids=0) g.add_edge(1, 2, fault_ids=1) g.add_edge(2, 3, fault_ids=2) g.nodes[0]['is_boundary'] = True g.nodes[3]['is_boundary'] = True g.add_edge(0, 3, weight=0.0) m = Matching(g) assert m.__repr__() == ("<pymatching.Matching object with " "2 detectors, 2 boundary nodes, and 4 edges>")
def test_repr(): g = nx.Graph() g.add_edge(0, 1, qubit_id=0) g.add_edge(1, 2, qubit_id=1) g.add_edge(2, 3, qubit_id=2) g.nodes[0]['is_boundary'] = True g.nodes[3]['is_boundary'] = True g.add_edge(0, 3, weight=0.0) m = Matching(g) assert m.__repr__() == ("<pymatching.Matching object with 3 qubits, " "2 stabilisers, 2 boundary nodes, and 4 edges>")
def test_matching_weight(n, num_neighbours): p = 0.4 H = repetition_code(n) noise = np.random.rand(n) < p weights = np.random.rand(n) s = H @ noise % 2 m = Matching(H, spacelike_weights=weights) corr, weight = m.decode(s, num_neighbours=num_neighbours, return_weight=True) expected_weight = np.sum(weights[corr == 1]) assert expected_weight == pytest.approx(weight)
def test_isolated_negative_weight(nn): m = Matching() m.add_edge(0, 1, 0, 1) m.add_edge(1, 2, 1, -10) m.add_edge(2, 3, 2, 1) m.add_edge(3, 0, 3, 1) c, w = m.decode([0, 1, 1, 0], return_weight=True, num_neighbours=nn) assert np.array_equal(c, np.array([0, 1, 0, 0])) assert w == -10
def test_local_matching_connected(cluster_size): g = nx.Graph() qid = 0 for i in range(cluster_size): g.add_edge(i, i+1, weight=1.0, qubit_id=qid) qid += 1 g.add_edge(cluster_size, cluster_size+1, weight=2*cluster_size, qubit_id=qid) qid += 1 for i in range(cluster_size+1, 2*cluster_size + 1): g.add_edge(i, i+1, weight=1.0, qubit_id=qid) qid += 1 m = Matching(g) m.decode([1]*(cluster_size+1)*2, num_neighbours=cluster_size)
def test_add_noise_with_boundary(): g = nx.Graph() for i in range(11): g.add_edge(i, i + 1, qubit_id=i, error_probability=(i + 1) % 2) for i in range(5, 12): g.nodes()[i]['is_boundary'] = True m = Matching(g) noise, syndrome = m.add_noise() assert sum(syndrome) == 6 assert np.array_equal(noise, (np.arange(11) + 1) % 2) assert m.boundary == list(range(5, 12)) assert np.array_equal(syndrome, np.array([1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]))
def test_boundary_from_networkx(): g = nx.Graph() g.add_edge(4,0, qubit_id=0) g.add_edge(0,1, qubit_id=1) g.add_edge(1,2, qubit_id=2) g.add_edge(2,3, qubit_id=3) g.add_edge(3,4, qubit_id=4) g.nodes()[4]['is_boundary'] = True m = Matching(g) assert m.boundary == [4] assert np.array_equal(m.decode(np.array([1,0,0,0])), np.array([1,0,0,0,0])) assert np.array_equal(m.decode(np.array([0,1,0,0])), np.array([1,1,0,0,0])) assert np.array_equal(m.decode(np.array([0,1,1,0])), np.array([0,0,1,0,0])) assert np.array_equal(m.decode(np.array([0,0,1,0])), np.array([0,0,0,1,1]))
def test_negative_weight_repetition_code(nn): m = Matching() m.add_edge(0, 1, 0, -1) m.add_edge(1, 2, 1, -1) m.add_edge(2, 3, 2, -1) m.add_edge(3, 4, 3, -1) m.add_edge(4, 5, 4, -1) m.add_edge(5, 0, 5, -1) c, w = m.decode([0, 1, 1, 0, 0, 0], return_weight=True, num_neighbours=nn) assert np.array_equal(c, np.array([1, 0, 1, 1, 1, 1])) assert w == -5