split into separate methods and use noinline attribute to profile
This commit is contained in:
parent
03f9afa67b
commit
f3240b7f6b
1 changed files with 111 additions and 97 deletions
208
src/edmonds.cpp
208
src/edmonds.cpp
|
@ -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,6 +97,114 @@ void collect_exposed_vertices(Graph & graph, std::stack<NodeId> & container)
|
|||
}
|
||||
}
|
||||
|
||||
__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
|
||||
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
|
||||
graph.reset_forest();
|
||||
collect_exposed_vertices(graph, outer_unvisited_nodes);
|
||||
}
|
||||
|
||||
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
|
||||
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.rho(x_path[distance_from_x]) != x_path[distance_from_x])
|
||||
{
|
||||
++distance_from_x;
|
||||
++distance_from_y;
|
||||
};
|
||||
// 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)
|
||||
{
|
||||
graph.node(graph.phi(x_path[i])).phi = x_path[i];
|
||||
}
|
||||
}
|
||||
for (size_t i = 1; i <= distance_from_y; i += 2)
|
||||
{
|
||||
if (graph.rho(graph.phi(y_path[i])) != blossom_root_id)
|
||||
{
|
||||
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();
|
||||
}
|
||||
if (graph.rho(y_path.front()) != blossom_root_id)
|
||||
{
|
||||
graph.node(y_path.front()).phi = x_path.front();
|
||||
}
|
||||
|
||||
// Update root indices. We have to do this for all vertices v with
|
||||
// ρ(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)
|
||||
{
|
||||
graph.node(node_id).rho = blossom_root_id;
|
||||
}
|
||||
}
|
||||
//check_integrity(graph);
|
||||
}
|
||||
|
||||
void maximum_matching_from_initial_matching(Graph & graph)
|
||||
{
|
||||
graph.reset_forest();
|
||||
|
@ -131,107 +240,12 @@ void maximum_matching_from_initial_matching(Graph & graph)
|
|||
|
||||
if (x_path.back() != y_path.back())
|
||||
{
|
||||
//std::cout << "Augment" << std::endl;
|
||||
// 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
|
||||
graph.reset_forest();
|
||||
collect_exposed_vertices(graph, outer_unvisited_nodes);
|
||||
augment(graph, x_path, y_path, outer_unvisited_nodes);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cout << "Contract blossom" << std::endl;
|
||||
// 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.rho(x_path[distance_from_x]) != x_path[distance_from_x])
|
||||
{
|
||||
++distance_from_x;
|
||||
++distance_from_y;
|
||||
};
|
||||
// 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)
|
||||
{
|
||||
graph.node(graph.phi(x_path[i])).phi = x_path[i];
|
||||
}
|
||||
}
|
||||
for(size_t i = 1; i <= distance_from_y; i += 2)
|
||||
{
|
||||
if (graph.rho(graph.phi(y_path[i])) != blossom_root_id)
|
||||
{
|
||||
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();
|
||||
}
|
||||
if (graph.rho(y_path.front()) != blossom_root_id)
|
||||
{
|
||||
graph.node(y_path.front()).phi = x_path.front();
|
||||
}
|
||||
|
||||
// Update root indices. We have to do this for all vertices v with
|
||||
// ρ(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)
|
||||
{
|
||||
graph.node(node_id).rho = blossom_root_id;
|
||||
}
|
||||
}
|
||||
//check_integrity(graph);
|
||||
contract_blossom(graph, x_path, y_path, outer_unvisited_nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue