use stack to maintain unscanned vertices
This commit is contained in:
parent
5674dff7a6
commit
4fee5333a2
3 changed files with 68 additions and 20 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "edmonds.h"
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
|
||||
using namespace ED;
|
||||
|
||||
|
@ -82,6 +83,7 @@ std::vector<NodeId> path_to_forest_root(Graph const & graph, NodeId id)
|
|||
return retval;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
NodeId find_outer_vertex(Graph const & graph)
|
||||
{
|
||||
for(NodeId id = 0; id < graph.num_nodes(); ++id)
|
||||
|
@ -94,12 +96,35 @@ NodeId find_outer_vertex(Graph const & graph)
|
|||
return invalid_node_id;
|
||||
}
|
||||
|
||||
void collect_exposed_vertices(Graph & graph, std::stack<NodeId> & container)
|
||||
{
|
||||
std::stack<NodeId>().swap(container);
|
||||
for(NodeId id = 0; id < graph.num_nodes(); id++)
|
||||
{
|
||||
if (graph.matched_neighbor(id) == id)
|
||||
{
|
||||
container.push(id);
|
||||
graph.node(id).scanned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void maximum_matching_from_initial_matching(Graph & graph)
|
||||
{
|
||||
graph.reset_forest();
|
||||
NodeId id;
|
||||
while((id = find_outer_vertex(graph)) != invalid_node_id)
|
||||
// Over the course of the algorithm, this will maintain all outer vertices
|
||||
// that have not been scanned yet.
|
||||
// Note that at the beginning, this is exactly the exposed edges.
|
||||
// Throughout the algorithm, we push new ids whenever there are new outer vertices.
|
||||
// Also note that we separately mark each node whether it has been collected to this stack.
|
||||
// When this stack runs out, then we know that all vertices marked 'scanned' have already been processed,
|
||||
// but also all vertices not marked 'scanned' are not outer vertices, so we can in fact terminate.
|
||||
std::stack<NodeId> outer_unvisited_nodes;
|
||||
collect_exposed_vertices(graph, outer_unvisited_nodes);
|
||||
while(not outer_unvisited_nodes.empty())
|
||||
{
|
||||
NodeId const id = outer_unvisited_nodes.top();
|
||||
outer_unvisited_nodes.pop();
|
||||
for(NodeId neighbor_id : graph.node(id).neighbors())
|
||||
{
|
||||
//check_integrity(graph);
|
||||
|
@ -109,6 +134,8 @@ void maximum_matching_from_initial_matching(Graph & graph)
|
|||
//std::cout << "Grow forest" << std::endl;
|
||||
// Grow Forest
|
||||
graph.node(neighbor_id).phi = id;
|
||||
assert(graph.matched_neighbor(neighbor_id) != neighbor_id);
|
||||
outer_unvisited_nodes.push(graph.matched_neighbor(neighbor_id));
|
||||
}
|
||||
else if (graph.is_outer(neighbor_id) and graph.rho(id) != graph.rho(neighbor_id))
|
||||
{
|
||||
|
@ -136,6 +163,7 @@ void maximum_matching_from_initial_matching(Graph & graph)
|
|||
// Note that since this is tail-recursion, this will not generate
|
||||
// new stack frames in OPT mode
|
||||
graph.reset_forest();
|
||||
collect_exposed_vertices(graph, outer_unvisited_nodes);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -158,6 +186,8 @@ void maximum_matching_from_initial_matching(Graph & graph)
|
|||
};
|
||||
// found first vertex fixed by rho
|
||||
NodeId blossom_root_id = x_path[distance_from_x];
|
||||
|
||||
// Update φ along the paths to encode the ear decomposition
|
||||
for(size_t i = 1; i <= distance_from_x; i += 2)
|
||||
{
|
||||
if (graph.rho(graph.phi(x_path[i])) != blossom_root_id)
|
||||
|
@ -172,6 +202,8 @@ void maximum_matching_from_initial_matching(Graph & graph)
|
|||
graph.node(graph.phi(y_path[i])).phi = y_path[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Link x and y
|
||||
if (graph.rho(x_path.front()) != blossom_root_id)
|
||||
{
|
||||
graph.node(x_path.front()).phi = y_path.front();
|
||||
|
@ -185,14 +217,26 @@ void maximum_matching_from_initial_matching(Graph & graph)
|
|||
// ρ(v) in the paths from x or y to r
|
||||
// We update ρ(v) first for the paths themselves, and then 'contract' ρ
|
||||
// by updating ρ(v) to r for all vertices where ρ(ρ(v)) = r
|
||||
// Also, while walking along the paths, we can add all vertices (which are now outer)
|
||||
// to the stack.
|
||||
for(size_t i = 0; i <= distance_from_x; ++i)
|
||||
{
|
||||
graph.node(x_path[i]).rho = blossom_root_id;
|
||||
if(not graph.node(x_path[i]).scanned)
|
||||
{
|
||||
outer_unvisited_nodes.push(x_path[i]);
|
||||
}
|
||||
}
|
||||
for(size_t i = 0; i <= distance_from_y; ++i)
|
||||
{
|
||||
graph.node(y_path[i]).rho = blossom_root_id;
|
||||
if(not graph.node(y_path[i]).scanned)
|
||||
{
|
||||
outer_unvisited_nodes.push(y_path[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterating over whole graph.
|
||||
for(NodeId node_id = 0; node_id < graph.num_nodes(); ++node_id)
|
||||
{
|
||||
if (graph.rho(graph.rho(node_id)) == blossom_root_id)
|
||||
|
|
|
@ -176,24 +176,6 @@ std::ostream & operator<<(std::ostream & output, Graph const & graph)
|
|||
return output;
|
||||
}
|
||||
|
||||
bool Graph::is_outer(NodeId const id) const {
|
||||
return matched_neighbor(id) == id or \
|
||||
phi(matched_neighbor(id)) != matched_neighbor(id);
|
||||
}
|
||||
|
||||
bool Graph::is_inner(NodeId const id) const
|
||||
{
|
||||
return phi(id) != id and \
|
||||
phi(matched_neighbor(id)) == matched_neighbor(id);
|
||||
}
|
||||
|
||||
bool Graph::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);
|
||||
}
|
||||
|
||||
void Graph::reset_forest()
|
||||
{
|
||||
NodeId cur_id = 0;
|
||||
|
|
|
@ -260,6 +260,28 @@ NodeId Graph::rho(const NodeId id) const
|
|||
return _nodes[id].rho;
|
||||
}
|
||||
|
||||
inline
|
||||
bool Graph::is_outer(NodeId const id) const {
|
||||
return matched_neighbor(id) == id or \
|
||||
phi(matched_neighbor(id)) != matched_neighbor(id);
|
||||
}
|
||||
|
||||
inline
|
||||
bool Graph::is_inner(NodeId const id) const
|
||||
{
|
||||
return phi(id) != id and \
|
||||
phi(matched_neighbor(id)) == matched_neighbor(id);
|
||||
}
|
||||
|
||||
inline
|
||||
bool Graph::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);
|
||||
}
|
||||
|
||||
|
||||
} // namespace ED
|
||||
|
||||
#endif /* GRAPH_HPP */
|
||||
|
|
Loading…
Reference in a new issue