From 1b9f930adf0b353a700cc7057660dd455b988bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Sun, 5 Nov 2023 13:06:50 +0100 Subject: [PATCH] ensure all outer vertices are scanned --- src/edmonds.cpp | 166 ++++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 77 deletions(-) diff --git a/src/edmonds.cpp b/src/edmonds.cpp index 7cfe584..a77f82b 100644 --- a/src/edmonds.cpp +++ b/src/edmonds.cpp @@ -30,101 +30,113 @@ std::vector path_to_forest_root(Graph const & graph, NodeId id) return retval; } +NodeId find_outer_vertex(Graph const & graph) +{ + for(NodeId id = 0; id < graph.num_nodes(); ++id) + { + if (not graph.node(id).scanned and graph.is_outer(id)) + { + return id; + } + } + return invalid_node_id; +} + Graph maximum_matching_from_initial_matching(Graph & graph) { graph.reset_forest(); - for(NodeId id = 0; id < graph.num_nodes(); ++id) { - if (graph.is_outer(id)) + NodeId id; + while((id = find_outer_vertex(graph)) != invalid_node_id) + { + for(NodeId neighbor_id : graph.node(id).neighbors()) { - for(NodeId neighbor_id : graph.node(id).neighbors()) + if (graph.is_out_of_forest(neighbor_id)) { - if (graph.is_out_of_forest(neighbor_id)) - { - // Grow Forest - graph.node(neighbor_id).ear_or_root_neighbor = id; - } - else if (graph.is_outer(neighbor_id) and \ - graph.root_of_ear_component(id) != graph.root_of_ear_component(neighbor_id)) - { - std::vector x_path = path_to_forest_root(graph, id); - std::vector y_path = path_to_forest_root(graph, neighbor_id); + // Grow Forest + graph.node(neighbor_id).ear_or_root_neighbor = id; + } + else if (graph.is_outer(neighbor_id) and \ + graph.root_of_ear_component(id) != graph.root_of_ear_component(neighbor_id)) + { + std::vector x_path = path_to_forest_root(graph, id); + std::vector y_path = path_to_forest_root(graph, neighbor_id); - if (x_path.back() != y_path.back()) + if (x_path.back() != y_path.back()) + { + // Paths are disjoint -> augment + graph.node(x_path.front()).matched_neighbor = y_path.front(); + graph.node(y_path.front()).matched_neighbor = x_path.front(); + + // TODO: put this into own method? + for(size_t i = 1; i < x_path.size(); i += 2) { - // Paths are disjoint -> augment - graph.node(x_path.front()).matched_neighbor = y_path.front(); - graph.node(y_path.front()).matched_neighbor = x_path.front(); - - // TODO: put this into own method? - for(size_t i = 1; i < x_path.size(); i += 2) - { - graph.node(x_path[i]).matched_neighbor = x_path[i+1]; - graph.node(x_path[i+1]).matched_neighbor = x_path[i]; - } - for(size_t i = 1; i < y_path.size(); i += 2) - { - graph.node(y_path[i]).matched_neighbor = y_path[i+1]; - graph.node(y_path[i+1]).matched_neighbor = y_path[i]; - } - // Note that since this is tail-recursion, this will not generate - // new stack frames in OPT mode - return maximum_matching(graph); + graph.node(x_path[i]).matched_neighbor = x_path[i+1]; + graph.node(x_path[i+1]).matched_neighbor = x_path[i]; } - else + for(size_t i = 1; i < y_path.size(); i += 2) { - // Paths are not disjoint -> shrink blossom - size_t distance_from_x = x_path.size() - 1; - size_t distance_from_y = y_path.size() - 1; - while (distance_from_x > 0 and distance_from_y > 0 and \ - x_path[distance_from_x - 1] == y_path[distance_from_y - 1]) + graph.node(y_path[i]).matched_neighbor = y_path[i+1]; + graph.node(y_path[i+1]).matched_neighbor = y_path[i]; + } + // Note that since this is tail-recursion, this will not generate + // new stack frames in OPT mode + return maximum_matching(graph); + } + else + { + // Paths are not disjoint -> shrink blossom + size_t distance_from_x = x_path.size() - 1; + size_t distance_from_y = y_path.size() - 1; + while (distance_from_x > 0 and distance_from_y > 0 and \ + x_path[distance_from_x - 1] == y_path[distance_from_y - 1]) + { + --distance_from_x; + --distance_from_y; + } + // found first vertex of x_path \cap y_path + while (graph.root_of_ear_component(x_path[distance_from_x]) != x_path[distance_from_x]) + { + ++distance_from_x; + ++distance_from_y; + }; + // found first vertex fixed by root_of_ear_component + NodeId blossom_root_id = x_path[distance_from_x]; + for(size_t i = 1; i <= distance_from_x; i += 2) + { + if (graph.root_of_ear_component(graph.ear_or_root_neighbor(x_path[i])) != blossom_root_id) { - --distance_from_x; - --distance_from_y; + graph.node(graph.ear_or_root_neighbor(x_path[i])).ear_or_root_neighbor = x_path[i]; } - // found first vertex of x_path \cap y_path - while (graph.root_of_ear_component(x_path[distance_from_x]) != x_path[distance_from_x]) + } + for(size_t i = 1; i <= distance_from_y; i += 2) + { + if (graph.root_of_ear_component(graph.ear_or_root_neighbor(y_path[i])) != blossom_root_id) { - ++distance_from_x; - ++distance_from_y; - }; - // found first vertex fixed by root_of_ear_component - NodeId blossom_root_id = x_path[distance_from_x]; - for(size_t i = 1; i <= distance_from_x; i += 2) - { - if (graph.root_of_ear_component(graph.ear_or_root_neighbor(x_path[i])) != blossom_root_id) - { - graph.node(graph.ear_or_root_neighbor(x_path[i])).ear_or_root_neighbor = x_path[i]; - } - } - for(size_t i = 1; i <= distance_from_y; i += 2) - { - if (graph.root_of_ear_component(graph.ear_or_root_neighbor(y_path[i])) != blossom_root_id) - { - graph.node(graph.ear_or_root_neighbor(y_path[i])).ear_or_root_neighbor = y_path[i]; - } - } - if (graph.root_of_ear_component(x_path.front()) != blossom_root_id) - { - graph.node(x_path.front()).ear_or_root_neighbor = y_path.front(); - } - if (graph.root_of_ear_component(y_path.front()) != blossom_root_id) - { - graph.node(x_path.front()).ear_or_root_neighbor = x_path.front(); + graph.node(graph.ear_or_root_neighbor(y_path[i])).ear_or_root_neighbor = y_path[i]; } + } + if (graph.root_of_ear_component(x_path.front()) != blossom_root_id) + { + graph.node(x_path.front()).ear_or_root_neighbor = y_path.front(); + } + if (graph.root_of_ear_component(y_path.front()) != blossom_root_id) + { + graph.node(x_path.front()).ear_or_root_neighbor = x_path.front(); + } - // Update root indices - for(size_t i = 0; i <= distance_from_x; ++i) - { - graph.node(x_path[i]).root_of_ear_component = blossom_root_id; - } - for(size_t i = 0; i <= distance_from_y; ++i) - { - graph.node(y_path[i]).root_of_ear_component = blossom_root_id; - } + // Update root indices + for(size_t i = 0; i <= distance_from_x; ++i) + { + graph.node(x_path[i]).root_of_ear_component = blossom_root_id; + } + for(size_t i = 0; i <= distance_from_y; ++i) + { + graph.node(y_path[i]).root_of_ear_component = blossom_root_id; } } } } + graph.node(id).scanned = true; } return graph; };