Skip to content

Commit

Permalink
Merge pull request #40 from oscarhiggott/fix-syndrome-on-boundary
Browse files Browse the repository at this point in the history
Zero out syndrome in the support of UserGraph boundary nodes. Fixes #41
  • Loading branch information
oscarhiggott committed Oct 29, 2022
2 parents df64928 + feed3ce commit 9b14b29
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/pymatching/sparse_blossom/driver/mwpm_decoding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ void process_timeline_until_completion(pm::Mwpm& mwpm, const std::vector<uint64_
for (auto& detection : detection_events) {
if (detection >= mwpm.flooder.graph.nodes.size())
throw std::invalid_argument("Detection event index too large");
mwpm.create_detection_event(&mwpm.flooder.graph.nodes[detection]);
if (detection + 1 > mwpm.flooder.graph.is_user_graph_boundary_node.size() ||
!mwpm.flooder.graph.is_user_graph_boundary_node[detection])
mwpm.create_detection_event(&mwpm.flooder.graph.nodes[detection]);
}

} else {
Expand All @@ -102,7 +104,9 @@ void process_timeline_until_completion(pm::Mwpm& mwpm, const std::vector<uint64_
"Detection event index `" + std::to_string(detection) +
"` is larger than any detector node index in the graph.");
if (!mwpm.flooder.graph.nodes[detection].radius_of_arrival) {
mwpm.create_detection_event(&mwpm.flooder.graph.nodes[detection]);
if (detection + 1 > mwpm.flooder.graph.is_user_graph_boundary_node.size() ||
!mwpm.flooder.graph.is_user_graph_boundary_node[detection])
mwpm.create_detection_event(&mwpm.flooder.graph.nodes[detection]);
} else {
// Unmark node
mwpm.flooder.graph.nodes[detection].radius_of_arrival = 0;
Expand Down
6 changes: 6 additions & 0 deletions src/pymatching/sparse_blossom/driver/user_graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ pm::MatchingGraph pm::UserGraph::to_matching_graph(pm::weight_int num_distinct_w
matching_graph.add_boundary_edge(u, weight, observables);
});
matching_graph.normalising_constant = normalising_constant;
if (boundary_nodes.size() > 0) {
matching_graph.is_user_graph_boundary_node.clear();
matching_graph.is_user_graph_boundary_node.resize(nodes.size(), false);
for (auto& i : boundary_nodes)
matching_graph.is_user_graph_boundary_node[i] = true;
}
return matching_graph;
}

Expand Down
23 changes: 23 additions & 0 deletions src/pymatching/sparse_blossom/driver/user_graph.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

#include "pymatching/sparse_blossom/driver/user_graph.h"
#include "pymatching/sparse_blossom/driver/mwpm_decoding.h"

#include <cmath>
#include <gtest/gtest.h>
Expand Down Expand Up @@ -143,3 +144,25 @@ TEST(UserGraph, NodesAlongShortestPath) {
ASSERT_EQ(nodes, nodes_expected);
}
}

TEST(UserGraph, DecodeUserGraphDetectionEventOnBoundaryNode) {
{
pm::UserGraph graph;
graph.add_or_merge_edge(0, 1, {0}, 1.0, -1);
graph.add_or_merge_edge(1, 2, {1}, 1.0, -1);
graph.set_boundary({2});
auto& mwpm = graph.get_mwpm();
pm::ExtendedMatchingResult res(mwpm.flooder.graph.num_observables);
pm::decode_detection_events(mwpm, {2}, res.obs_crossed.data(), res.weight);
}

{
pm::UserGraph graph;
graph.add_or_merge_edge(0, 1, {0}, -1.0, -1);
graph.add_or_merge_edge(1, 2, {1}, 1.0, -1);
graph.set_boundary({2});
auto& mwpm = graph.get_mwpm();
pm::ExtendedMatchingResult res(mwpm.flooder.graph.num_observables);
pm::decode_detection_events(mwpm, {2}, res.obs_crossed.data(), res.weight);
}
}
1 change: 1 addition & 0 deletions src/pymatching/sparse_blossom/flooder/graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ MatchingGraph::MatchingGraph(MatchingGraph&& graph) noexcept
: nodes(std::move(graph.nodes)),
negative_weight_detection_events_set(std::move(graph.negative_weight_detection_events_set)),
negative_weight_observables_set(std::move(graph.negative_weight_observables_set)),
is_user_graph_boundary_node(std::move(graph.is_user_graph_boundary_node)),
negative_weight_sum(graph.negative_weight_sum),
num_nodes(graph.num_nodes),
num_observables(graph.num_observables),
Expand Down
5 changes: 5 additions & 0 deletions src/pymatching/sparse_blossom/flooder/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class MatchingGraph {
std::set<size_t> negative_weight_observables_set;
/// The sum of the negative edge weights. This number is negative, rather than the absolute value.
pm::total_weight_int negative_weight_sum;
/// is_user_graph_boundary_node is only filled if MatchingGraph is constructed from a UserGraph
/// is_user_graph_boundary_node[i] is true if i is a boudary node in the UserGraph
/// This vector is used to check that a detection event is not added to a node marked as a boundary node
/// in the UserGraph (as such an event cannot be matched, and will raise an error).
std::vector<bool> is_user_graph_boundary_node;
size_t num_nodes;
size_t num_observables;
/// This is the normalising constant that the edge weights were multiplied by when converting from floats to
Expand Down
13 changes: 13 additions & 0 deletions tests/matching/decode_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,16 @@ def test_decode_wrong_syndrome_type_raises_type_error():
m = Matching()
m.add_edge(0, 1)
m.decode([0, "A"])


def test_syndrome_on_boundary_nodes():
m = Matching()
m.add_edge(0, 1, fault_ids={0})
m.add_edge(1, 2, fault_ids={1})
m.add_edge(2, 3, fault_ids={2})
m.add_edge(3, 4, fault_ids={3})
m.set_boundary_nodes({3, 4})
m.decode([0, 0, 0, 1, 0])
m.decode([0, 0, 0, 0, 1])
m.decode([0, 0, 0, 1, 1])
m.decode([1, 0, 1, 0, 1])

0 comments on commit 9b14b29

Please sign in to comment.