2
0
mirror of https://github.com/boostorg/graph.git synced 2026-02-11 11:52:12 +00:00

untabified

[SVN r10356]
This commit is contained in:
Dave Abrahams
2001-06-18 13:13:35 +00:00
parent 02a997f4be
commit 8235b88eed

View File

@@ -114,7 +114,7 @@ namespace boost {
Marker(size_type _num, VertexIndexMap index_map)
: tag(1 - std::numeric_limits<value_type>::max()),
data(_num, - std::numeric_limits<value_type>::max()),
id(index_map) {}
id(index_map) {}
void mark_done(Vertex node) { data[id[node]] = done(); }
@@ -195,7 +195,7 @@ namespace boost {
typedef SignedInteger value_type;
typedef typename std::vector<value_type>::size_type size_type;
degreelists_marker(size_type n, VertexIndexMap id)
: marks(n, 0), id(id) {}
: marks(n, 0), id(id) {}
void mark_need_update(Vertex i) { marks[id[i]] = 1; }
bool need_update(Vertex i) { return marks[id[i]] == 1; }
bool outmatched_or_done (Vertex i) { return marks[id[i]] == -1; }
@@ -259,10 +259,10 @@ namespace boost {
};
template<class Graph, class DegreeMap,
class InversePermutationMap,
class PermutationMap,
class SuperNodeMap,
class VertexIndexMap>
class InversePermutationMap,
class PermutationMap,
class SuperNodeMap,
class VertexIndexMap>
class mmd_impl
{
// Typedefs
@@ -273,14 +273,14 @@ namespace boost {
typedef typename Traits::vertex_descriptor vertex_t;
typedef typename Traits::adjacency_iterator adj_iter;
typedef iterator_property_map<typename std::vector<vertex_t>::iterator,
identity_property_map, vertex_t, vertex_t&> IndexVertexMap;
identity_property_map, vertex_t, vertex_t&> IndexVertexMap;
typedef detail::Stacks<diff_t> Workspace;
typedef bucket_sorter<size_type, vertex_t, DegreeMap, VertexIndexMap>
DegreeLists;
DegreeLists;
typedef Numbering<InversePermutationMap, diff_t, vertex_t,VertexIndexMap>
NumberingD;
NumberingD;
typedef degreelists_marker<diff_t, vertex_t, VertexIndexMap>
DegreeListsMarker;
DegreeListsMarker;
typedef Marker<diff_t, vertex_t, VertexIndexMap> MarkerP;
// Data Members
@@ -305,324 +305,324 @@ namespace boost {
Workspace work_space;
public:
mmd_impl(Graph& g, size_type n_, int delta, DegreeMap degree,
InversePermutationMap inverse_perm,
PermutationMap perm,
SuperNodeMap supernode_size,
VertexIndexMap id)
: G(g), delta(delta), degree(degree),
inverse_perm(inverse_perm),
perm(perm),
supernode_size(supernode_size),
vertex_index_map(id),
index_vertex_vec(n_),
n(n_),
degreelists(n_ + 1, n_, degree, id),
numbering(inverse_perm, n_, vertex_index_map),
degree_lists_marker(n_, vertex_index_map),
marker(n_, vertex_index_map),
work_space(n_)
InversePermutationMap inverse_perm,
PermutationMap perm,
SuperNodeMap supernode_size,
VertexIndexMap id)
: G(g), delta(delta), degree(degree),
inverse_perm(inverse_perm),
perm(perm),
supernode_size(supernode_size),
vertex_index_map(id),
index_vertex_vec(n_),
n(n_),
degreelists(n_ + 1, n_, degree, id),
numbering(inverse_perm, n_, vertex_index_map),
degree_lists_marker(n_, vertex_index_map),
marker(n_, vertex_index_map),
work_space(n_)
{
typename graph_traits<Graph>::vertex_iterator v, vend;
size_type vid = 0;
for (tie(v, vend) = vertices(G); v != vend; ++v, ++vid)
index_vertex_vec[vid] = *v;
index_vertex_map = IndexVertexMap(&index_vertex_vec[0]);
typename graph_traits<Graph>::vertex_iterator v, vend;
size_type vid = 0;
for (tie(v, vend) = vertices(G); v != vend; ++v, ++vid)
index_vertex_vec[vid] = *v;
index_vertex_map = IndexVertexMap(&index_vertex_vec[0]);
// Initialize degreelists. Degreelists organizes the nodes
// according to their degree.
for (tie(v, vend) = vertices(G); v != vend; ++v) {
put(degree, *v, out_degree(*v, G));
degreelists.push(*v);
}
// Initialize degreelists. Degreelists organizes the nodes
// according to their degree.
for (tie(v, vend) = vertices(G); v != vend; ++v) {
put(degree, *v, out_degree(*v, G));
degreelists.push(*v);
}
}
void do_mmd()
{
// Eliminate the isolated nodes -- these are simply the nodes
// with no neighbors, which are accessible as a list (really, a
// stack) at location 0. Since these don't affect any other
// nodes, we can eliminate them without doing degree updates.
typename DegreeLists::stack list_isolated = degreelists[0];
while (!list_isolated.empty()) {
vertex_t node = list_isolated.top();
marker.mark_done(node);
numbering(node);
numbering.increment();
list_isolated.pop();
}
size_type min_degree = 1;
typename DegreeLists::stack list_min_degree = degreelists[min_degree];
// Eliminate the isolated nodes -- these are simply the nodes
// with no neighbors, which are accessible as a list (really, a
// stack) at location 0. Since these don't affect any other
// nodes, we can eliminate them without doing degree updates.
typename DegreeLists::stack list_isolated = degreelists[0];
while (!list_isolated.empty()) {
vertex_t node = list_isolated.top();
marker.mark_done(node);
numbering(node);
numbering.increment();
list_isolated.pop();
}
size_type min_degree = 1;
typename DegreeLists::stack list_min_degree = degreelists[min_degree];
while (list_min_degree.empty()) {
++min_degree;
list_min_degree = degreelists[min_degree];
}
while (list_min_degree.empty()) {
++min_degree;
list_min_degree = degreelists[min_degree];
}
// check if the whole eliminating process is done
while (!numbering.all_done()) {
// check if the whole eliminating process is done
while (!numbering.all_done()) {
size_type min_degree_limit = min_degree + delta; // WARNING
typename Workspace::stack llist = work_space.make_stack();
size_type min_degree_limit = min_degree + delta; // WARNING
typename Workspace::stack llist = work_space.make_stack();
// multiple elimination
while (delta >= 0) {
// multiple elimination
while (delta >= 0) {
// Find the next non-empty degree
for (list_min_degree = degreelists[min_degree];
list_min_degree.empty() && min_degree <= min_degree_limit;
++min_degree, list_min_degree = degreelists[min_degree])
;
if (min_degree > min_degree_limit)
break;
// Find the next non-empty degree
for (list_min_degree = degreelists[min_degree];
list_min_degree.empty() && min_degree <= min_degree_limit;
++min_degree, list_min_degree = degreelists[min_degree])
;
if (min_degree > min_degree_limit)
break;
const vertex_t node = list_min_degree.top();
const size_type node_id = vertex_index_map[node];
list_min_degree.pop();
numbering(node);
const vertex_t node = list_min_degree.top();
const size_type node_id = vertex_index_map[node];
list_min_degree.pop();
numbering(node);
// check if node is the last one
if (numbering.all_done(supernode_size[node])) {
numbering.increment(supernode_size[node]);
break;
}
marker.increment_tag();
marker.mark_tagged(node);
// check if node is the last one
if (numbering.all_done(supernode_size[node])) {
numbering.increment(supernode_size[node]);
break;
}
marker.increment_tag();
marker.mark_tagged(node);
this->eliminate(node);
this->eliminate(node);
numbering.increment(supernode_size[node]);
llist.push(node_id);
} // multiple elimination
numbering.increment(supernode_size[node]);
llist.push(node_id);
} // multiple elimination
if (numbering.all_done())
break;
if (numbering.all_done())
break;
this->update( llist, min_degree);
}
this->update( llist, min_degree);
}
} // do_mmd()
void eliminate(vertex_t node)
{
typename Workspace::stack element_neighbor = work_space.make_stack();
typename Workspace::stack element_neighbor = work_space.make_stack();
// Create two function objects for edge removal
predicateRemoveEdge1<Graph, MarkerP, NumberingD,
typename Workspace::stack, VertexIndexMap>
p(G, marker, numbering, element_neighbor, vertex_index_map);
// Create two function objects for edge removal
predicateRemoveEdge1<Graph, MarkerP, NumberingD,
typename Workspace::stack, VertexIndexMap>
p(G, marker, numbering, element_neighbor, vertex_index_map);
predicate_remove_tagged_edges<Graph, MarkerP> p2(G, marker);
predicate_remove_tagged_edges<Graph, MarkerP> p2(G, marker);
// Reconstruct the adjacent node list, push element neighbor in a List.
remove_out_edge_if(node, p, G);
//during removal element neighbors are collected.
// Reconstruct the adjacent node list, push element neighbor in a List.
remove_out_edge_if(node, p, G);
//during removal element neighbors are collected.
while (!element_neighbor.empty()) {
// element absorb
size_type e_id = element_neighbor.top();
vertex_t element = index_vertex_map[e_id];
adj_iter i, i_end;
for (tie(i, i_end) = adjacent_vertices(element, G); i != i_end; ++i){
vertex_t i_node = *i;
if (!marker.is_tagged(i_node) && !numbering.is_numbered(i_node)) {
marker.mark_tagged(i_node);
add_edge(node, i_node, G);
}
}
element_neighbor.pop();
}
adj_iter v, ve;
for (tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v) {
vertex_t v_node = *v;
if (!degree_lists_marker.need_update(v_node)
&& !degree_lists_marker.outmatched_or_done(v_node)) {
degreelists.remove(v_node);
}
//update out edges of v_node
remove_out_edge_if(v_node, p2, G);
while (!element_neighbor.empty()) {
// element absorb
size_type e_id = element_neighbor.top();
vertex_t element = index_vertex_map[e_id];
adj_iter i, i_end;
for (tie(i, i_end) = adjacent_vertices(element, G); i != i_end; ++i){
vertex_t i_node = *i;
if (!marker.is_tagged(i_node) && !numbering.is_numbered(i_node)) {
marker.mark_tagged(i_node);
add_edge(node, i_node, G);
}
}
element_neighbor.pop();
}
adj_iter v, ve;
for (tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v) {
vertex_t v_node = *v;
if (!degree_lists_marker.need_update(v_node)
&& !degree_lists_marker.outmatched_or_done(v_node)) {
degreelists.remove(v_node);
}
//update out edges of v_node
remove_out_edge_if(v_node, p2, G);
if ( out_degree(v_node, G) == 0 ) { // indistinguishable nodes
supernode_size[node] += supernode_size[v_node];
supernode_size[v_node] = 0;
numbering.indistinguishable(v_node, node);
marker.mark_done(v_node);
degree_lists_marker.mark(v_node);
} else { // not indistinguishable nodes
add_edge(v_node, node, G);
degree_lists_marker.mark_need_update(v_node);
}
}
if ( out_degree(v_node, G) == 0 ) { // indistinguishable nodes
supernode_size[node] += supernode_size[v_node];
supernode_size[v_node] = 0;
numbering.indistinguishable(v_node, node);
marker.mark_done(v_node);
degree_lists_marker.mark(v_node);
} else { // not indistinguishable nodes
add_edge(v_node, node, G);
degree_lists_marker.mark_need_update(v_node);
}
}
} // eliminate()
template <class Stack>
void update(Stack llist, size_type& min_degree)
{
size_type min_degree0 = min_degree + delta + 1;
size_type min_degree0 = min_degree + delta + 1;
while (! llist.empty()) {
size_type deg, deg0 = 0;
while (! llist.empty()) {
size_type deg, deg0 = 0;
marker.set_multiple_tag(min_degree0);
typename Workspace::stack q2list = work_space.make_stack();
typename Workspace::stack qxlist = work_space.make_stack();
marker.set_multiple_tag(min_degree0);
typename Workspace::stack q2list = work_space.make_stack();
typename Workspace::stack qxlist = work_space.make_stack();
vertex_t current = index_vertex_map[llist.top()];
adj_iter i, ie;
for (tie(i,ie) = adjacent_vertices(current, G); i != ie; ++i) {
vertex_t i_node = *i;
const size_type i_id = vertex_index_map[i_node];
if (supernode_size[i_node] != 0) {
deg0 += supernode_size[i_node];
marker.mark_multiple_tagged(i_node);
if (degree_lists_marker.need_update(i_node)) {
if (out_degree(i_node, G) == 2)
q2list.push(i_id);
else
qxlist.push(i_id);
}
}
}
vertex_t current = index_vertex_map[llist.top()];
adj_iter i, ie;
for (tie(i,ie) = adjacent_vertices(current, G); i != ie; ++i) {
vertex_t i_node = *i;
const size_type i_id = vertex_index_map[i_node];
if (supernode_size[i_node] != 0) {
deg0 += supernode_size[i_node];
marker.mark_multiple_tagged(i_node);
if (degree_lists_marker.need_update(i_node)) {
if (out_degree(i_node, G) == 2)
q2list.push(i_id);
else
qxlist.push(i_id);
}
}
}
while (!q2list.empty()) {
const size_type u_id = q2list.top();
vertex_t u_node = index_vertex_map[u_id];
// if u_id is outmatched by others, no need to update degree
if (degree_lists_marker.outmatched_or_done(u_node)) {
q2list.pop();
continue;
}
marker.increment_tag();
deg = deg0;
while (!q2list.empty()) {
const size_type u_id = q2list.top();
vertex_t u_node = index_vertex_map[u_id];
// if u_id is outmatched by others, no need to update degree
if (degree_lists_marker.outmatched_or_done(u_node)) {
q2list.pop();
continue;
}
marker.increment_tag();
deg = deg0;
adj_iter nu = adjacent_vertices(u_node, G).first;
vertex_t neighbor = *nu;
if (neighbor == u_node) {
++nu;
neighbor = *nu;
}
if (numbering.is_numbered(neighbor)) {
adj_iter i, ie;
for (tie(i,ie) = adjacent_vertices(neighbor, G);
i != ie; ++i) {
const vertex_t i_node = *i;
if (i_node == u_node || supernode_size[i_node] == 0)
continue;
if (marker.is_tagged(i_node)) {
if (degree_lists_marker.need_update(i_node)) {
if ( out_degree(i_node, G) == 2 ) { // is indistinguishable
supernode_size[u_node] += supernode_size[i_node];
supernode_size[i_node] = 0;
numbering.indistinguishable(i_node, u_node);
marker.mark_done(i_node);
degree_lists_marker.mark(i_node);
} else // is outmatched
degree_lists_marker.mark(i_node);
}
} else {
marker.mark_tagged(i_node);
deg += supernode_size[i_node];
}
}
} else
deg += supernode_size[neighbor];
adj_iter nu = adjacent_vertices(u_node, G).first;
vertex_t neighbor = *nu;
if (neighbor == u_node) {
++nu;
neighbor = *nu;
}
if (numbering.is_numbered(neighbor)) {
adj_iter i, ie;
for (tie(i,ie) = adjacent_vertices(neighbor, G);
i != ie; ++i) {
const vertex_t i_node = *i;
if (i_node == u_node || supernode_size[i_node] == 0)
continue;
if (marker.is_tagged(i_node)) {
if (degree_lists_marker.need_update(i_node)) {
if ( out_degree(i_node, G) == 2 ) { // is indistinguishable
supernode_size[u_node] += supernode_size[i_node];
supernode_size[i_node] = 0;
numbering.indistinguishable(i_node, u_node);
marker.mark_done(i_node);
degree_lists_marker.mark(i_node);
} else // is outmatched
degree_lists_marker.mark(i_node);
}
} else {
marker.mark_tagged(i_node);
deg += supernode_size[i_node];
}
}
} else
deg += supernode_size[neighbor];
deg -= supernode_size[u_node];
degree[u_node] = deg; //update degree
degreelists[deg].push(u_node);
//u_id has been pushed back into degreelists
degree_lists_marker.unmark(u_node);
if (min_degree > deg)
min_degree = deg;
q2list.pop();
} // while (!q2list.empty())
deg -= supernode_size[u_node];
degree[u_node] = deg; //update degree
degreelists[deg].push(u_node);
//u_id has been pushed back into degreelists
degree_lists_marker.unmark(u_node);
if (min_degree > deg)
min_degree = deg;
q2list.pop();
} // while (!q2list.empty())
while (!qxlist.empty()) {
const size_type u_id = qxlist.top();
const vertex_t u_node = index_vertex_map[u_id];
while (!qxlist.empty()) {
const size_type u_id = qxlist.top();
const vertex_t u_node = index_vertex_map[u_id];
// if u_id is outmatched by others, no need to update degree
if (degree_lists_marker.outmatched_or_done(u_node)) {
qxlist.pop();
continue;
}
marker.increment_tag();
deg = deg0;
adj_iter i, ie;
for (tie(i, ie) = adjacent_vertices(u_node, G); i != ie; ++i) {
vertex_t i_node = *i;
if (marker.is_tagged(i_node))
continue;
marker.mark_tagged(i_node);
// if u_id is outmatched by others, no need to update degree
if (degree_lists_marker.outmatched_or_done(u_node)) {
qxlist.pop();
continue;
}
marker.increment_tag();
deg = deg0;
adj_iter i, ie;
for (tie(i, ie) = adjacent_vertices(u_node, G); i != ie; ++i) {
vertex_t i_node = *i;
if (marker.is_tagged(i_node))
continue;
marker.mark_tagged(i_node);
if (numbering.is_numbered(i_node)) {
adj_iter j, je;
for (tie(j, je) = adjacent_vertices(i_node, G); j != je; ++j) {
const vertex_t j_node = *j;
if (marker.is_not_tagged(j_node)) {
marker.mark_tagged(j_node);
deg += supernode_size[j_node];
}
}
} else
deg += supernode_size[i_node];
} // for adjacent vertices of u_node
deg -= supernode_size[u_node];
degree[u_node] = deg;
degreelists[deg].push(u_node);
// u_id has been pushed back into degreelists
degree_lists_marker.unmark(u_node);
if (min_degree > deg)
min_degree = deg;
qxlist.pop();
} // while (!qxlist.empty()) {
if (numbering.is_numbered(i_node)) {
adj_iter j, je;
for (tie(j, je) = adjacent_vertices(i_node, G); j != je; ++j) {
const vertex_t j_node = *j;
if (marker.is_not_tagged(j_node)) {
marker.mark_tagged(j_node);
deg += supernode_size[j_node];
}
}
} else
deg += supernode_size[i_node];
} // for adjacent vertices of u_node
deg -= supernode_size[u_node];
degree[u_node] = deg;
degreelists[deg].push(u_node);
// u_id has been pushed back into degreelists
degree_lists_marker.unmark(u_node);
if (min_degree > deg)
min_degree = deg;
qxlist.pop();
} // while (!qxlist.empty()) {
marker.set_tag_as_multiple_tag();
llist.pop();
} // while (! llist.empty())
marker.set_tag_as_multiple_tag();
llist.pop();
} // while (! llist.empty())
} // update()
void build_permutation(InversePermutationMap next,
PermutationMap prev)
PermutationMap prev)
{
// collect the permutation info
for (size_type i = 0; i < n; ++i) {
diff_t size = supernode_size[index_vertex_map[i]];
if ( size <= 0 ) {
prev[i] = next[i];
supernode_size[index_vertex_map[i]]
= next[i] + 1; // record the supernode info
} else
prev[i] = - next[i];
}
for (size_type i = 1; i < n + 1; ++i) {
if ( prev[i-1] > 0 )
continue;
diff_t parent = i;
while ( prev[parent - 1] < 0 ) {
parent = - prev[parent - 1];
}
// collect the permutation info
for (size_type i = 0; i < n; ++i) {
diff_t size = supernode_size[index_vertex_map[i]];
if ( size <= 0 ) {
prev[i] = next[i];
supernode_size[index_vertex_map[i]]
= next[i] + 1; // record the supernode info
} else
prev[i] = - next[i];
}
for (size_type i = 1; i < n + 1; ++i) {
if ( prev[i-1] > 0 )
continue;
diff_t parent = i;
while ( prev[parent - 1] < 0 ) {
parent = - prev[parent - 1];
}
diff_t root = parent;
diff_t num = prev[root - 1] + 1;
next[i-1] = - num;
prev[root-1] = num;
diff_t root = parent;
diff_t num = prev[root - 1] + 1;
next[i-1] = - num;
prev[root-1] = num;
parent = i;
diff_t next_node = - prev[parent - 1];
while (next_node > 0) {
prev[parent-1] = - root;
parent = next_node;
next_node = - prev[parent - 1];
}
}
for (size_type i = 0; i < n; i++) {
diff_t num = - next[i] - 1;
next[i] = num;
prev[num] = i;
}
parent = i;
diff_t next_node = - prev[parent - 1];
while (next_node > 0) {
prev[parent-1] = - root;
parent = next_node;
next_node = - prev[parent - 1];
}
}
for (size_type i = 0; i < n; i++) {
diff_t num = - next[i] - 1;
next[i] = num;
prev[num] = i;
}
} // build_permutation()
};
@@ -657,7 +657,7 @@ namespace boost {
detail::mmd_impl<Graph,DegreeMap,InversePermutationMap,
PermutationMap, SuperNodeMap, VertexIndexMap>
impl(G, num_vertices(G), delta, degree, inverse_perm,
perm, supernode_size, vertex_index_map);
perm, supernode_size, vertex_index_map);
impl.do_mmd();
impl.build_permutation(inverse_perm, perm);
}