use union-find structure for rho
This commit is contained in:
parent
1d75066eea
commit
497d601ffc
2 changed files with 37 additions and 38 deletions
|
@ -8,7 +8,7 @@ using namespace ED;
|
||||||
|
|
||||||
namespace Edmonds {
|
namespace Edmonds {
|
||||||
|
|
||||||
void check_integrity(GraphAttributes const & attrs)
|
void check_integrity(GraphAttributes & attrs)
|
||||||
{
|
{
|
||||||
for(NodeId id = 0; id < attrs.num_nodes(); ++id)
|
for(NodeId id = 0; id < attrs.num_nodes(); ++id)
|
||||||
{
|
{
|
||||||
|
@ -22,13 +22,13 @@ void check_integrity(GraphAttributes const & attrs)
|
||||||
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
|
||||||
|
@ -36,8 +36,8 @@ void check_integrity(GraphAttributes const & attrs)
|
||||||
// and point to vertices that have the same rho
|
// and point to vertices that have the same rho
|
||||||
assert(attrs.mu[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.mu[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.mu[cur_node];
|
cur_node = attrs.mu[cur_node];
|
||||||
|
@ -46,7 +46,7 @@ void check_integrity(GraphAttributes const & attrs)
|
||||||
// - 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.mu[attrs.phi[cur_node]];
|
cur_node = attrs.mu[attrs.phi[cur_node]];
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ void check_integrity(GraphAttributes const & attrs)
|
||||||
|
|
||||||
if (not attrs.is_outer(id))
|
if (not attrs.is_outer(id))
|
||||||
{
|
{
|
||||||
assert(attrs.rho[id] == id);
|
assert(attrs.rho(id) == id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ __attribute__((noinline))
|
||||||
void augment(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
|
void augment(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
|
||||||
std::stack<NodeId> & outer_unvisited_nodes)
|
std::stack<NodeId> & outer_unvisited_nodes)
|
||||||
{
|
{
|
||||||
//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();
|
||||||
|
@ -124,7 +124,7 @@ void augment(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::v
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
std::tuple<NodeId, size_type, size_type> find_blossom_root_id(GraphAttributes const & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path)
|
std::tuple<NodeId, size_type, size_type> find_blossom_root_id(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path)
|
||||||
{
|
{
|
||||||
size_t distance_from_x = x_path.size() - 1;
|
size_t distance_from_x = x_path.size() - 1;
|
||||||
size_t distance_from_y = y_path.size() - 1;
|
size_t distance_from_y = y_path.size() - 1;
|
||||||
|
@ -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;
|
||||||
|
@ -153,7 +153,7 @@ void update_phialong_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];
|
||||||
}
|
}
|
||||||
|
@ -161,36 +161,23 @@ void update_phialong_blossom_paths(GraphAttributes & attrs, std::vector<NodeId>
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline))
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
attrs.rho[node_id] = blossom_root_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
void update_rho(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
|
void update_rho(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
|
||||||
std::tuple<NodeId, size_type, size_type> const & blossom_root_description,
|
std::tuple<NodeId, size_type, size_type> const & blossom_root_description,
|
||||||
|
@ -205,7 +192,7 @@ 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]);
|
||||||
|
@ -213,20 +200,19 @@ void update_rho(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std
|
||||||
}
|
}
|
||||||
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contract_rho(attrs, blossom_root_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
void contract_blossom(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
|
void contract_blossom(GraphAttributes & attrs, std::vector<NodeId> const & x_path, std::vector<NodeId> const & y_path,
|
||||||
std::stack<NodeId> & outer_unvisited_nodes)
|
std::stack<NodeId> & outer_unvisited_nodes)
|
||||||
{
|
{
|
||||||
//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_phialong_blossom_paths(attrs, x_path, y_path, blossom_root_description);
|
update_phialong_blossom_paths(attrs, x_path, y_path, blossom_root_description);
|
||||||
|
|
||||||
|
@ -253,16 +239,16 @@ void maximum_matching_from_initial_matching(Graph const & graph, GraphAttributes
|
||||||
for(NodeId neighbor_id : graph.node(id).neighbors())
|
for(NodeId neighbor_id : graph.node(id).neighbors())
|
||||||
{
|
{
|
||||||
check_integrity(attrs);
|
check_integrity(attrs);
|
||||||
//std::cout << "Check passed" << std::endl;
|
std::cout << "Check passed" << std::endl;
|
||||||
if (attrs.is_out_of_forest(neighbor_id))
|
if (attrs.is_out_of_forest(neighbor_id))
|
||||||
{
|
{
|
||||||
//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.mu[neighbor_id] != neighbor_id);
|
assert(attrs.mu[neighbor_id] != neighbor_id);
|
||||||
outer_unvisited_nodes.push(attrs.mu[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);
|
||||||
|
|
|
@ -20,10 +20,12 @@ namespace ED
|
||||||
|
|
||||||
void reset_forest();
|
void reset_forest();
|
||||||
|
|
||||||
|
NodeId rho(NodeId id);
|
||||||
|
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
@ -31,7 +33,7 @@ namespace ED
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -41,7 +43,7 @@ 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();
|
||||||
|
@ -68,10 +70,21 @@ namespace ED
|
||||||
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
|
||||||
|
NodeId GraphAttributes::rho(NodeId id)
|
||||||
|
{
|
||||||
|
while(rho_[id] != id)
|
||||||
|
{
|
||||||
|
rho_[id] = rho_[rho_[id]];
|
||||||
|
id = rho_[id];
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void GraphAttributes::reset_matching()
|
void GraphAttributes::reset_matching()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue