split into separate methods and use noinline attribute to profile

This commit is contained in:
Maximilian Keßler 2023-11-06 12:28:57 +01:00
parent 03f9afa67b
commit f3240b7f6b
Signed by: max
GPG Key ID: BCC5A619923C0BA5

View File

@ -64,6 +64,7 @@ void check_integrity(Graph const & graph)
* @note This assumes that the values of μ, φ and ρ represent a special
* blossom forest on the graph when this method is called.
* **/
__attribute__((noinline))
std::vector<NodeId> path_to_forest_root(Graph const & graph, NodeId id)
{
std::vector<NodeId> retval;
@ -96,40 +97,9 @@ void collect_exposed_vertices(Graph & graph, std::stack<NodeId> & container)
}
}
void maximum_matching_from_initial_matching(Graph & graph)
{
graph.reset_forest();
// 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);
//std::cout << "Check passed" << std::endl;
if (graph.is_out_of_forest(neighbor_id))
{
//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))
{
std::vector<NodeId> x_path = path_to_forest_root(graph, id);
std::vector<NodeId> y_path = path_to_forest_root(graph, neighbor_id);
if (x_path.back() != y_path.back())
__attribute__((noinline))
void augment(Graph & graph, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
std::stack<NodeId> & outer_unvisited_nodes)
{
//std::cout << "Augment" << std::endl;
// Paths are disjoint -> augment
@ -151,9 +121,10 @@ void maximum_matching_from_initial_matching(Graph & graph)
// new stack frames in OPT mode
graph.reset_forest();
collect_exposed_vertices(graph, outer_unvisited_nodes);
break;
}
else
void contract_blossom(Graph & graph, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
std::stack<NodeId> & outer_unvisited_nodes)
{
//std::cout << "Contract blossom" << std::endl;
// Paths are not disjoint -> shrink blossom
@ -233,6 +204,49 @@ void maximum_matching_from_initial_matching(Graph & graph)
}
//check_integrity(graph);
}
void maximum_matching_from_initial_matching(Graph & graph)
{
graph.reset_forest();
// 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);
//std::cout << "Check passed" << std::endl;
if (graph.is_out_of_forest(neighbor_id))
{
//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))
{
std::vector<NodeId> x_path = path_to_forest_root(graph, id);
std::vector<NodeId> y_path = path_to_forest_root(graph, neighbor_id);
if (x_path.back() != y_path.back())
{
augment(graph, x_path, y_path, outer_unvisited_nodes);
break;
}
else
{
contract_blossom(graph, x_path, y_path, outer_unvisited_nodes);
}
}
}
graph.node(id).scanned = true;