From bd1de9ef03702ab2e6f511b7faa48daebed47686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Mon, 6 Nov 2023 13:45:57 +0100 Subject: [PATCH] remove redundant methods: use vector access --- src/edmonds.cpp | 106 ++++++++++++++++++++--------------------- src/graph_attributes.h | 69 ++++++++------------------- 2 files changed, 72 insertions(+), 103 deletions(-) diff --git a/src/edmonds.cpp b/src/edmonds.cpp index 0297497..97a0ddf 100644 --- a/src/edmonds.cpp +++ b/src/edmonds.cpp @@ -13,48 +13,48 @@ void check_integrity(GraphAttributes const & attrs) for(NodeId id = 0; id < attrs.num_nodes(); ++id) { // Check that μ encodes a valid matching - NodeId matched = attrs.matched_neighbor(id); + NodeId matched = attrs.mu[id]; if(matched != id) { - assert(attrs.matched_neighbor(matched) == id); + assert(attrs.mu[matched] == id); } if (attrs.is_out_of_forest(id)) { - assert(attrs.phi(id) == id); - assert(attrs.rho(id) == id); + assert(attrs.phi[id] == id); + assert(attrs.rho[id] == id); } else { // check for a path to the root, i.e. ρ(node) NodeId cur_node = id; - while(cur_node != attrs.rho(cur_node)) + while(cur_node != attrs.rho[cur_node]) { // If the condition was true, then cur_node is outer, part of a blossom // and we want to follow its path // therefore, we check that both φ and μ are not the identity on this node // and point to vertices that have the same rho - assert(attrs.matched_neighbor(cur_node) != cur_node); - assert(attrs.phi(cur_node) != cur_node); - assert(attrs.rho(attrs.matched_neighbor(cur_node)) == attrs.rho(cur_node)); - assert(attrs.rho(attrs.phi(cur_node)) == attrs.rho(cur_node)); + assert(attrs.mu[cur_node] != cur_node); + assert(attrs.phi[cur_node] != cur_node); + assert(attrs.rho[attrs.mu[cur_node]] == attrs.rho[cur_node]); + assert(attrs.rho[attrs.phi[cur_node]] == attrs.rho[cur_node]); // now, walk along the matched edge - cur_node = attrs.matched_neighbor(cur_node); + cur_node = attrs.mu[cur_node]; // now we want to walk along φ, this will again // - not be the identity // - result in a node that has the same rho - assert(attrs.phi(cur_node) != cur_node); - assert(attrs.rho(attrs.phi(cur_node)) == attrs.rho(cur_node)); + assert(attrs.phi[cur_node] != cur_node); + assert(attrs.rho[attrs.phi[cur_node]] == attrs.rho[cur_node]); - cur_node = attrs.matched_neighbor(attrs.phi(cur_node)); + cur_node = attrs.mu[attrs.phi[cur_node]]; } } if (not attrs.is_outer(id)) { - assert(attrs.rho(id) == id); + assert(attrs.rho[id] == id); } } } @@ -71,16 +71,16 @@ std::vector path_to_forest_root(GraphAttributes const & attrs, NodeId id { std::vector retval; retval.push_back(id); - while (attrs.matched_neighbor(id) != id) + while (attrs.mu[id] != id) { - id = attrs.matched_neighbor(id); + id = attrs.mu[id]; retval.push_back(id); // Note that it is guaranteed that this does not produce a loop: // We are traversing the path to a root of the forest, // but we know that each root is exposed by M, so after traversing // the matching edge, we cannot have reached a root. - id = attrs.phi(id); + id = attrs.phi[id]; retval.push_back(id); } return retval; @@ -91,10 +91,10 @@ void collect_exposed_vertices(GraphAttributes & attrs, std::stack & cont std::stack().swap(container); for(NodeId id = 0; id < attrs.num_nodes(); id++) { - if (attrs.matched_neighbor(id) == id) + if (attrs.mu[id] == id) { container.push(id); - attrs.scanned_[id] = true; + attrs.scanned[id] = true; } } } @@ -105,19 +105,19 @@ void augment(GraphAttributes & attrs, std::vector const & x_path, std::v { //std::cout << "Augment" << std::endl; // Paths are disjoint -> augment - attrs.mu_[x_path.front()] = y_path.front(); - attrs.mu_[y_path.front()] = x_path.front(); + attrs.mu[x_path.front()] = y_path.front(); + attrs.mu[y_path.front()] = x_path.front(); // TODO: put this into own method? for(size_t i = 1; i < x_path.size(); i += 2) { - attrs.mu_[x_path[i]] = x_path[i+1]; - attrs.mu_[x_path[i+1]] = x_path[i]; + attrs.mu[x_path[i]] = x_path[i+1]; + attrs.mu[x_path[i+1]] = x_path[i]; } for(size_t i = 1; i < y_path.size(); i += 2) { - attrs.mu_[y_path[i]] = y_path[i+1]; - attrs.mu_[y_path[i+1]] = x_path[i+1]; + attrs.mu[y_path[i]] = y_path[i+1]; + attrs.mu[y_path[i+1]] = x_path[i+1]; } attrs.reset_forest(); collect_exposed_vertices(attrs, outer_unvisited_nodes); @@ -135,7 +135,7 @@ std::tuple find_blossom_root_id(GraphAttributes co --distance_from_y; } // found first vertex of x_path \cap y_path - while (attrs.rho(x_path[distance_from_x]) != x_path[distance_from_x]) + while (attrs.rho[x_path[distance_from_x]] != x_path[distance_from_x]) { ++distance_from_x; ++distance_from_y; @@ -145,7 +145,7 @@ std::tuple find_blossom_root_id(GraphAttributes co } __attribute__((noinline)) -void update_phi_along_blossom_paths(GraphAttributes & attrs, std::vector const & x_path, std::vector const & y_path, +void update_phialong_blossom_paths(GraphAttributes & attrs, std::vector const & x_path, std::vector const & y_path, std::tuple const & blossom_root) { auto const [blossom_root_id, distance_from_x, distance_from_y] = blossom_root; @@ -153,28 +153,28 @@ void update_phi_along_blossom_paths(GraphAttributes & attrs, std::vector // Update φ along the paths to encode the ear decomposition for (size_t i = 1; i <= distance_from_x; i += 2) { - if (attrs.rho(attrs.phi(x_path[i])) != blossom_root_id) + if (attrs.rho[attrs.phi[x_path[i]]] != blossom_root_id) { - attrs.phi_[attrs.phi(x_path[i])] = x_path[i]; + attrs.phi[attrs.phi[x_path[i]]] = x_path[i]; } } for (size_t i = 1; i <= distance_from_y; i += 2) { - if (attrs.rho(attrs.phi(y_path[i])) != blossom_root_id) + if (attrs.rho[attrs.phi[y_path[i]]] != blossom_root_id) { - attrs.phi_[attrs.phi(y_path[i])] = y_path[i]; + attrs.phi[attrs.phi[y_path[i]]] = y_path[i]; } } // Link x and y - if (attrs.rho(x_path.front()) != blossom_root_id) + if (attrs.rho[x_path.front()] != blossom_root_id) { - attrs.phi_[x_path.front()] = y_path.front(); + attrs.phi[x_path.front()] = y_path.front(); } - if (attrs.rho(y_path.front()) != blossom_root_id) + if (attrs.rho[y_path.front()] != blossom_root_id) { - attrs.phi_[y_path.front()] = x_path.front(); + attrs.phi[y_path.front()] = x_path.front(); } } @@ -184,9 +184,9 @@ void contract_rho(GraphAttributes & attrs, NodeId blossom_root_id) // Iterating over whole attrs. for (NodeId node_id = 0; node_id < attrs.num_nodes(); ++node_id) { - if (attrs.rho(attrs.rho(node_id)) == blossom_root_id) + if (attrs.rho[attrs.rho[node_id]] == blossom_root_id) { - attrs.rho_[node_id] = blossom_root_id; + attrs.rho[node_id] = blossom_root_id; } } } @@ -205,16 +205,16 @@ void update_rho(GraphAttributes & attrs, std::vector const & x_path, std auto const [blossom_root_id, distance_from_x, distance_from_y] = blossom_root_description; for (size_t i = 0; i <= distance_from_x; ++i) { - attrs.rho_[x_path[i]] = blossom_root_id; - if (not attrs.scanned_[x_path[i]]) + attrs.rho[x_path[i]] = blossom_root_id; + if (not attrs.scanned[x_path[i]]) { outer_unvisited_nodes.push(x_path[i]); } } for (size_t i = 0; i <= distance_from_y; ++i) { - attrs.rho_[y_path[i]] = blossom_root_id; - if (not attrs.scanned_[y_path[i]]) + attrs.rho[y_path[i]] = blossom_root_id; + if (not attrs.scanned[y_path[i]]) { outer_unvisited_nodes.push(y_path[i]); } @@ -228,7 +228,7 @@ void contract_blossom(GraphAttributes & attrs, std::vector const & x_pat { //std::cout << "Contract blossom" << std::endl; std::tuple const blossom_root_description = find_blossom_root_id(attrs, x_path, y_path); - update_phi_along_blossom_paths(attrs, x_path, y_path, blossom_root_description); + update_phialong_blossom_paths(attrs, x_path, y_path, blossom_root_description); //check_integrity(attrs); update_rho(attrs, x_path, y_path, blossom_root_description, outer_unvisited_nodes); @@ -258,11 +258,11 @@ void maximum_matching_from_initial_matching(Graph const & graph, GraphAttributes { //std::cout << "Grow forest" << std::endl; // Grow Forest - attrs.phi_[neighbor_id] = id; - assert(attrs.matched_neighbor(neighbor_id) != neighbor_id); - outer_unvisited_nodes.push(attrs.matched_neighbor(neighbor_id)); + attrs.phi[neighbor_id] = id; + assert(attrs.mu[neighbor_id] != neighbor_id); + outer_unvisited_nodes.push(attrs.mu[neighbor_id]); } - else if (attrs.is_outer(neighbor_id) and attrs.rho(id) != attrs.rho(neighbor_id)) + else if (attrs.is_outer(neighbor_id) and attrs.rho[id] != attrs.rho[neighbor_id]) { std::vector x_path = path_to_forest_root(attrs, id); std::vector y_path = path_to_forest_root(attrs, neighbor_id); @@ -280,7 +280,7 @@ void maximum_matching_from_initial_matching(Graph const & graph, GraphAttributes } } } - attrs.scanned_[id] = true; + attrs.scanned[id] = true; } }; @@ -289,13 +289,13 @@ void find_greedy_matching(Graph const & graph, GraphAttributes & attrs) attrs.reset_matching(); for(NodeId node_id = 0; node_id < graph.num_nodes(); ++node_id) { - if (attrs.matched_neighbor(node_id) == node_id) { + if (attrs.mu[node_id] == node_id) { for(NodeId const neighbor_id : graph.node(node_id).neighbors()) { - if(attrs.matched_neighbor(neighbor_id) == neighbor_id) + if(attrs.mu[neighbor_id] == neighbor_id) { - attrs.mu_[neighbor_id] = node_id; - attrs.mu_[node_id] = neighbor_id; + attrs.mu[neighbor_id] = node_id; + attrs.mu[node_id] = neighbor_id; break; } } @@ -313,9 +313,9 @@ Graph maximum_matching(Graph & graph) { ED::Graph matching = ED::Graph(graph.num_nodes()); for (NodeId id = 0; id < graph.num_nodes(); ++id) { - if (attrs.matched_neighbor(id) > id) + if (attrs.mu[id] > id) { - matching.add_edge(id, attrs.matched_neighbor(id)); + matching.add_edge(id, attrs.mu[id]); } } return matching; diff --git a/src/graph_attributes.h b/src/graph_attributes.h index 9b4a7f1..b236636 100644 --- a/src/graph_attributes.h +++ b/src/graph_attributes.h @@ -12,12 +12,6 @@ namespace ED [[nodiscard]] NodeId num_nodes() const; - [[nodiscard]] NodeId matched_neighbor(NodeId id) const; - - [[nodiscard]] NodeId phi(NodeId id) const; - - [[nodiscard]] NodeId rho(NodeId id) const; - [[nodiscard]] bool is_outer(NodeId id) const; [[nodiscard]] bool is_inner(NodeId id) const; @@ -28,18 +22,18 @@ namespace ED void reset_matching(); - std::vector phi_; - std::vector rho_; - std::vector mu_; - std::vector scanned_; + std::vector phi; + std::vector rho; + std::vector mu; + std::vector scanned; }; inline GraphAttributes::GraphAttributes(const ED::NodeId num_nodes): - phi_(num_nodes), - rho_(num_nodes), - mu_(num_nodes), - scanned_(num_nodes) + phi(num_nodes), + rho(num_nodes), + mu(num_nodes), + scanned(num_nodes) { } @@ -47,66 +41,41 @@ namespace ED inline NodeId GraphAttributes::num_nodes() const { - assert(phi_.size() == rho_.size()); - assert(phi_.size() == mu_.size()); - assert(phi_.size() == scanned_.size()); - return phi_.size(); - } - - inline - NodeId GraphAttributes::matched_neighbor(NodeId const id) const - { - assert(id <= num_nodes()); - return mu_[id]; - } - - inline - NodeId GraphAttributes::phi(const NodeId id) const - { - assert(id <= num_nodes()); - return phi_[id]; - } - - inline - NodeId GraphAttributes::rho(const NodeId id) const - { - assert(id <= num_nodes()); - return rho_[id]; + assert(phi.size() == rho.size()); + assert(phi.size() == mu.size()); + assert(phi.size() == scanned.size()); + return phi.size(); } inline bool GraphAttributes::is_outer(NodeId const id) const { - return matched_neighbor(id) == id or \ - phi(matched_neighbor(id)) != matched_neighbor(id); + return mu[id] == id or phi[mu[id]] == mu[id]; } inline bool GraphAttributes::is_inner(NodeId const id) const { - return phi(id) != id and \ - phi(matched_neighbor(id)) == matched_neighbor(id); + return phi[id] != id and phi[mu[id]] == mu[id]; } inline bool GraphAttributes::is_out_of_forest(const ED::NodeId id) const { - return matched_neighbor(id) != id and \ - phi(id) == id and \ - phi(matched_neighbor(id)) == matched_neighbor(id); + return mu[id] != id and phi[id] == id and phi[mu[id]] == mu[id]; } inline void GraphAttributes::reset_forest() { - std::iota(phi_.begin(), phi_.end(), 0); - std::iota(rho_.begin(), rho_.end(), 0); - std::fill(scanned_.begin(), scanned_.end(), false); + std::iota(phi.begin(), phi.end(), 0); + std::iota(rho.begin(), rho.end(), 0); + std::fill(scanned.begin(), scanned.end(), false); } inline void GraphAttributes::reset_matching() { - std::iota(mu_.begin(), mu_.end(), 0); + std::iota(mu.begin(), mu.end(), 0); } } #endif //GRAPH_ATTRIBUTES_H