remove redundant methods: use vector access

This commit is contained in:
Maximilian Keßler 2023-11-06 13:45:57 +01:00
parent 65aa75bc46
commit bd1de9ef03
Signed by: max
GPG key ID: BCC5A619923C0BA5
2 changed files with 72 additions and 103 deletions

View file

@ -13,48 +13,48 @@ void check_integrity(GraphAttributes const & attrs)
for(NodeId id = 0; id < attrs.num_nodes(); ++id) for(NodeId id = 0; id < attrs.num_nodes(); ++id)
{ {
// Check that μ encodes a valid matching // Check that μ encodes a valid matching
NodeId matched = attrs.matched_neighbor(id); NodeId matched = attrs.mu[id];
if(matched != id) if(matched != id)
{ {
assert(attrs.matched_neighbor(matched) == id); assert(attrs.mu[matched] == id);
} }
if (attrs.is_out_of_forest(id)) if (attrs.is_out_of_forest(id))
{ {
assert(attrs.phi(id) == id); assert(attrs.phi[id] == id);
assert(attrs.rho(id) == id); assert(attrs.rho[id] == id);
} }
else else
{ {
// check for a path to the root, i.e. ρ(node) // check for a path to the root, i.e. ρ(node)
NodeId cur_node = id; 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 // If the condition was true, then cur_node is outer, part of a blossom
// and we want to follow its path // and we want to follow its path
// therefore, we check that both φ and μ are not the identity on this node // therefore, we check that both φ and μ are not the identity on this node
// and point to vertices that have the same rho // and point to vertices that have the same rho
assert(attrs.matched_neighbor(cur_node) != cur_node); assert(attrs.mu[cur_node] != cur_node);
assert(attrs.phi(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.mu[cur_node]] == attrs.rho[cur_node]);
assert(attrs.rho(attrs.phi(cur_node)) == attrs.rho(cur_node)); assert(attrs.rho[attrs.phi[cur_node]] == attrs.rho[cur_node]);
// now, walk along the matched edge // 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 // now we want to walk along φ, this will again
// - not be the identity // - not be the identity
// - result in a node that has the same rho // - result in a node that has the same rho
assert(attrs.phi(cur_node) != cur_node); assert(attrs.phi[cur_node] != cur_node);
assert(attrs.rho(attrs.phi(cur_node)) == attrs.rho(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)) if (not attrs.is_outer(id))
{ {
assert(attrs.rho(id) == id); assert(attrs.rho[id] == id);
} }
} }
} }
@ -71,16 +71,16 @@ std::vector<NodeId> path_to_forest_root(GraphAttributes const & attrs, NodeId id
{ {
std::vector<NodeId> retval; std::vector<NodeId> retval;
retval.push_back(id); 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); retval.push_back(id);
// Note that it is guaranteed that this does not produce a loop: // Note that it is guaranteed that this does not produce a loop:
// We are traversing the path to a root of the forest, // We are traversing the path to a root of the forest,
// but we know that each root is exposed by M, so after traversing // but we know that each root is exposed by M, so after traversing
// the matching edge, we cannot have reached a root. // the matching edge, we cannot have reached a root.
id = attrs.phi(id); id = attrs.phi[id];
retval.push_back(id); retval.push_back(id);
} }
return retval; return retval;
@ -91,10 +91,10 @@ void collect_exposed_vertices(GraphAttributes & attrs, std::stack<NodeId> & cont
std::stack<NodeId>().swap(container); std::stack<NodeId>().swap(container);
for(NodeId id = 0; id < attrs.num_nodes(); id++) for(NodeId id = 0; id < attrs.num_nodes(); id++)
{ {
if (attrs.matched_neighbor(id) == id) if (attrs.mu[id] == id)
{ {
container.push(id); container.push(id);
attrs.scanned_[id] = true; attrs.scanned[id] = true;
} }
} }
} }
@ -105,19 +105,19 @@ void augment(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::v
{ {
//std::cout << "Augment" << std::endl; //std::cout << "Augment" << std::endl;
// Paths are disjoint -> augment // Paths are disjoint -> augment
attrs.mu_[x_path.front()] = y_path.front(); attrs.mu[x_path.front()] = y_path.front();
attrs.mu_[y_path.front()] = x_path.front(); attrs.mu[y_path.front()] = x_path.front();
// TODO: put this into own method? // TODO: put this into own method?
for(size_t i = 1; i < x_path.size(); i += 2) 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]] = x_path[i+1];
attrs.mu_[x_path[i+1]] = x_path[i]; attrs.mu[x_path[i+1]] = x_path[i];
} }
for(size_t i = 1; i < y_path.size(); i += 2) 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]] = y_path[i+1];
attrs.mu_[y_path[i+1]] = x_path[i+1]; attrs.mu[y_path[i+1]] = x_path[i+1];
} }
attrs.reset_forest(); attrs.reset_forest();
collect_exposed_vertices(attrs, outer_unvisited_nodes); collect_exposed_vertices(attrs, outer_unvisited_nodes);
@ -135,7 +135,7 @@ std::tuple<NodeId, size_type, size_type> find_blossom_root_id(GraphAttributes co
--distance_from_y; --distance_from_y;
} }
// found first vertex of x_path \cap y_path // 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_x;
++distance_from_y; ++distance_from_y;
@ -145,7 +145,7 @@ std::tuple<NodeId, size_type, size_type> find_blossom_root_id(GraphAttributes co
} }
__attribute__((noinline)) __attribute__((noinline))
void update_phi_along_blossom_paths(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path, void update_phialong_blossom_paths(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
std::tuple<NodeId, size_type, size_type> const & blossom_root) std::tuple<NodeId, size_type, size_type> const & blossom_root)
{ {
auto const [blossom_root_id, distance_from_x, distance_from_y] = 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<NodeId>
// Update φ along the paths to encode the ear decomposition // Update φ along the paths to encode the ear decomposition
for (size_t i = 1; i <= distance_from_x; i += 2) 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) 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 // 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. // Iterating over whole attrs.
for (NodeId node_id = 0; node_id < attrs.num_nodes(); ++node_id) 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<NodeId> const & x_path, std
auto const [blossom_root_id, distance_from_x, distance_from_y] = blossom_root_description; auto const [blossom_root_id, distance_from_x, distance_from_y] = blossom_root_description;
for (size_t i = 0; i <= distance_from_x; ++i) for (size_t i = 0; i <= distance_from_x; ++i)
{ {
attrs.rho_[x_path[i]] = blossom_root_id; attrs.rho[x_path[i]] = blossom_root_id;
if (not attrs.scanned_[x_path[i]]) if (not attrs.scanned[x_path[i]])
{ {
outer_unvisited_nodes.push(x_path[i]); outer_unvisited_nodes.push(x_path[i]);
} }
} }
for (size_t i = 0; i <= distance_from_y; ++i) for (size_t i = 0; i <= distance_from_y; ++i)
{ {
attrs.rho_[y_path[i]] = blossom_root_id; attrs.rho[y_path[i]] = blossom_root_id;
if (not attrs.scanned_[y_path[i]]) if (not attrs.scanned[y_path[i]])
{ {
outer_unvisited_nodes.push(y_path[i]); outer_unvisited_nodes.push(y_path[i]);
} }
@ -228,7 +228,7 @@ void contract_blossom(GraphAttributes & attrs, std::vector<NodeId> const & x_pat
{ {
//std::cout << "Contract blossom" << std::endl; //std::cout << "Contract blossom" << std::endl;
std::tuple<NodeId, size_type, size_type> const blossom_root_description = find_blossom_root_id(attrs, x_path, y_path); std::tuple<NodeId, size_type, size_type> 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); //check_integrity(attrs);
update_rho(attrs, x_path, y_path, blossom_root_description, outer_unvisited_nodes); 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; //std::cout << "Grow forest" << std::endl;
// Grow Forest // Grow Forest
attrs.phi_[neighbor_id] = id; attrs.phi[neighbor_id] = id;
assert(attrs.matched_neighbor(neighbor_id) != neighbor_id); assert(attrs.mu[neighbor_id] != neighbor_id);
outer_unvisited_nodes.push(attrs.matched_neighbor(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<NodeId> x_path = path_to_forest_root(attrs, id); std::vector<NodeId> x_path = path_to_forest_root(attrs, id);
std::vector<NodeId> y_path = path_to_forest_root(attrs, neighbor_id); std::vector<NodeId> 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(); attrs.reset_matching();
for(NodeId node_id = 0; node_id < graph.num_nodes(); ++node_id) 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()) 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[neighbor_id] = node_id;
attrs.mu_[node_id] = neighbor_id; attrs.mu[node_id] = neighbor_id;
break; break;
} }
} }
@ -313,9 +313,9 @@ Graph maximum_matching(Graph & graph) {
ED::Graph matching = ED::Graph(graph.num_nodes()); ED::Graph matching = ED::Graph(graph.num_nodes());
for (NodeId id = 0; id < graph.num_nodes(); ++id) 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; return matching;

View file

@ -12,12 +12,6 @@ namespace ED
[[nodiscard]] NodeId num_nodes() const; [[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_outer(NodeId id) const;
[[nodiscard]] bool is_inner(NodeId id) const; [[nodiscard]] bool is_inner(NodeId id) const;
@ -28,18 +22,18 @@ namespace ED
void reset_matching(); void reset_matching();
std::vector<NodeId> phi_; std::vector<NodeId> phi;
std::vector<NodeId> rho_; std::vector<NodeId> rho;
std::vector<NodeId> mu_; std::vector<NodeId> mu;
std::vector<bool> scanned_; std::vector<bool> scanned;
}; };
inline inline
GraphAttributes::GraphAttributes(const ED::NodeId num_nodes): GraphAttributes::GraphAttributes(const ED::NodeId num_nodes):
phi_(num_nodes), phi(num_nodes),
rho_(num_nodes), rho(num_nodes),
mu_(num_nodes), mu(num_nodes),
scanned_(num_nodes) scanned(num_nodes)
{ {
} }
@ -47,66 +41,41 @@ namespace ED
inline inline
NodeId GraphAttributes::num_nodes() const NodeId GraphAttributes::num_nodes() const
{ {
assert(phi_.size() == rho_.size()); assert(phi.size() == rho.size());
assert(phi_.size() == mu_.size()); assert(phi.size() == mu.size());
assert(phi_.size() == scanned_.size()); assert(phi.size() == scanned.size());
return phi_.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];
} }
inline inline
bool GraphAttributes::is_outer(NodeId const id) const { bool GraphAttributes::is_outer(NodeId const id) const {
return matched_neighbor(id) == id or \ return mu[id] == id or phi[mu[id]] == mu[id];
phi(matched_neighbor(id)) != matched_neighbor(id);
} }
inline inline
bool GraphAttributes::is_inner(NodeId const id) const bool GraphAttributes::is_inner(NodeId const id) const
{ {
return phi(id) != id and \ return phi[id] != id and phi[mu[id]] == mu[id];
phi(matched_neighbor(id)) == matched_neighbor(id);
} }
inline inline
bool GraphAttributes::is_out_of_forest(const ED::NodeId id) const bool GraphAttributes::is_out_of_forest(const ED::NodeId id) const
{ {
return matched_neighbor(id) != id and \ return mu[id] != id and phi[id] == id and phi[mu[id]] == mu[id];
phi(id) == id and \
phi(matched_neighbor(id)) == matched_neighbor(id);
} }
inline inline
void GraphAttributes::reset_forest() void GraphAttributes::reset_forest()
{ {
std::iota(phi_.begin(), phi_.end(), 0); std::iota(phi.begin(), phi.end(), 0);
std::iota(rho_.begin(), rho_.end(), 0); std::iota(rho.begin(), rho.end(), 0);
std::fill(scanned_.begin(), scanned_.end(), false); std::fill(scanned.begin(), scanned.end(), false);
} }
inline inline
void GraphAttributes::reset_matching() void GraphAttributes::reset_matching()
{ {
std::iota(mu_.begin(), mu_.end(), 0); std::iota(mu.begin(), mu.end(), 0);
} }
} }
#endif //GRAPH_ATTRIBUTES_H #endif //GRAPH_ATTRIBUTES_H