File indexing completed on 2025-01-18 09:37:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP
0012 #define BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP
0013
0014 #include <vector>
0015 #include <boost/assert.hpp>
0016 #include <boost/config.hpp>
0017 #include <boost/pending/bucket_sorter.hpp>
0018 #include <boost/detail/numeric_traits.hpp> // for integer_traits
0019 #include <boost/graph/graph_traits.hpp>
0020 #include <boost/property_map/property_map.hpp>
0021
0022 namespace boost
0023 {
0024
0025 namespace detail
0026 {
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template < class SignedInteger > class Stacks
0039 {
0040 typedef SignedInteger value_type;
0041 typedef typename std::vector< value_type >::size_type size_type;
0042
0043 public:
0044 Stacks(size_type n) : data(n) {}
0045
0046
0047 class stack
0048 {
0049 typedef typename std::vector< value_type >::iterator Iterator;
0050
0051 public:
0052 stack(Iterator _data, const value_type& head)
0053 : data(_data), current(head)
0054 {
0055 }
0056
0057
0058
0059 stack(Iterator _data)
0060 : data(_data), current(-(std::numeric_limits< value_type >::max)())
0061 {
0062 }
0063
0064 void pop()
0065 {
0066 BOOST_ASSERT(!empty());
0067 current = data[current];
0068 }
0069 void push(value_type v)
0070 {
0071 data[v] = current;
0072 current = v;
0073 }
0074 bool empty()
0075 {
0076 return current == -(std::numeric_limits< value_type >::max)();
0077 }
0078 value_type& top() { return current; }
0079
0080 private:
0081 Iterator data;
0082 value_type current;
0083 };
0084
0085
0086 stack make_stack() { return stack(data.begin()); }
0087
0088 protected:
0089 std::vector< value_type > data;
0090 };
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 template < class SignedInteger, class Vertex, class VertexIndexMap >
0105 class Marker
0106 {
0107 typedef SignedInteger value_type;
0108 typedef typename std::vector< value_type >::size_type size_type;
0109
0110 static value_type done()
0111 {
0112 return (std::numeric_limits< value_type >::max)() / 2;
0113 }
0114
0115 public:
0116 Marker(size_type _num, VertexIndexMap index_map)
0117 : tag(1 - (std::numeric_limits< value_type >::max)())
0118 , data(_num, -(std::numeric_limits< value_type >::max)())
0119 , id(index_map)
0120 {
0121 }
0122
0123 void mark_done(Vertex node) { data[get(id, node)] = done(); }
0124
0125 bool is_done(Vertex node) { return data[get(id, node)] == done(); }
0126
0127 void mark_tagged(Vertex node) { data[get(id, node)] = tag; }
0128
0129 void mark_multiple_tagged(Vertex node)
0130 {
0131 data[get(id, node)] = multiple_tag;
0132 }
0133
0134 bool is_tagged(Vertex node) const { return data[get(id, node)] >= tag; }
0135
0136 bool is_not_tagged(Vertex node) const
0137 {
0138 return data[get(id, node)] < tag;
0139 }
0140
0141 bool is_multiple_tagged(Vertex node) const
0142 {
0143 return data[get(id, node)] >= multiple_tag;
0144 }
0145
0146 void increment_tag()
0147 {
0148 const size_type num = data.size();
0149 ++tag;
0150 if (tag >= done())
0151 {
0152 tag = 1 - (std::numeric_limits< value_type >::max)();
0153 for (size_type i = 0; i < num; ++i)
0154 if (data[i] < done())
0155 data[i] = -(std::numeric_limits< value_type >::max)();
0156 }
0157 }
0158
0159 void set_multiple_tag(value_type mdeg0)
0160 {
0161 const size_type num = data.size();
0162 multiple_tag = tag + mdeg0;
0163
0164 if (multiple_tag >= done())
0165 {
0166 tag = 1 - (std::numeric_limits< value_type >::max)();
0167
0168 for (size_type i = 0; i < num; i++)
0169 if (data[i] < done())
0170 data[i] = -(std::numeric_limits< value_type >::max)();
0171
0172 multiple_tag = tag + mdeg0;
0173 }
0174 }
0175
0176 void set_tag_as_multiple_tag() { tag = multiple_tag; }
0177
0178 protected:
0179 value_type tag;
0180 value_type multiple_tag;
0181 std::vector< value_type > data;
0182 VertexIndexMap id;
0183 };
0184
0185 template < class Iterator, class SignedInteger, class Vertex,
0186 class VertexIndexMap, int offset = 1 >
0187 class Numbering
0188 {
0189 typedef SignedInteger number_type;
0190 number_type num;
0191 Iterator data;
0192 number_type max_num;
0193 VertexIndexMap id;
0194
0195 public:
0196 Numbering(Iterator _data, number_type _max_num, VertexIndexMap id)
0197 : num(1), data(_data), max_num(_max_num), id(id)
0198 {
0199 }
0200 void operator()(Vertex node) { data[get(id, node)] = -num; }
0201 bool all_done(number_type i = 0) const { return num + i > max_num; }
0202 void increment(number_type i = 1) { num += i; }
0203 bool is_numbered(Vertex node) const { return data[get(id, node)] < 0; }
0204 void indistinguishable(Vertex i, Vertex j)
0205 {
0206 data[get(id, i)] = -(get(id, j) + offset);
0207 }
0208 };
0209
0210 template < class SignedInteger, class Vertex, class VertexIndexMap >
0211 class degreelists_marker
0212 {
0213 public:
0214 typedef SignedInteger value_type;
0215 typedef typename std::vector< value_type >::size_type size_type;
0216 degreelists_marker(size_type n, VertexIndexMap id) : marks(n, 0), id(id)
0217 {
0218 }
0219 void mark_need_update(Vertex i) { marks[get(id, i)] = 1; }
0220 bool need_update(Vertex i) { return marks[get(id, i)] == 1; }
0221 bool outmatched_or_done(Vertex i) { return marks[get(id, i)] == -1; }
0222 void mark(Vertex i) { marks[get(id, i)] = -1; }
0223 void unmark(Vertex i) { marks[get(id, i)] = 0; }
0224
0225 private:
0226 std::vector< value_type > marks;
0227 VertexIndexMap id;
0228 };
0229
0230
0231 template < class Graph, class MarkerP, class NumberD, class Stack,
0232 class VertexIndexMap >
0233 class predicateRemoveEdge1
0234 {
0235 typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
0236 typedef typename graph_traits< Graph >::edge_descriptor edge_t;
0237
0238 public:
0239 predicateRemoveEdge1(Graph& _g, MarkerP& _marker, NumberD _numbering,
0240 Stack& n_e, VertexIndexMap id)
0241 : g(&_g)
0242 , marker(&_marker)
0243 , numbering(_numbering)
0244 , neighbor_elements(&n_e)
0245 , id(id)
0246 {
0247 }
0248
0249 bool operator()(edge_t e)
0250 {
0251 vertex_t dist = target(e, *g);
0252 if (marker->is_tagged(dist))
0253 return true;
0254 marker->mark_tagged(dist);
0255 if (numbering.is_numbered(dist))
0256 {
0257 neighbor_elements->push(get(id, dist));
0258 return true;
0259 }
0260 return false;
0261 }
0262
0263 private:
0264 Graph* g;
0265 MarkerP* marker;
0266 NumberD numbering;
0267 Stack* neighbor_elements;
0268 VertexIndexMap id;
0269 };
0270
0271
0272 template < class Graph, class MarkerP > class predicate_remove_tagged_edges
0273 {
0274 typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
0275 typedef typename graph_traits< Graph >::edge_descriptor edge_t;
0276
0277 public:
0278 predicate_remove_tagged_edges(Graph& _g, MarkerP& _marker)
0279 : g(&_g), marker(&_marker)
0280 {
0281 }
0282
0283 bool operator()(edge_t e)
0284 {
0285 vertex_t dist = target(e, *g);
0286 if (marker->is_tagged(dist))
0287 return true;
0288 return false;
0289 }
0290
0291 private:
0292 Graph* g;
0293 MarkerP* marker;
0294 };
0295
0296 template < class Graph, class DegreeMap, class InversePermutationMap,
0297 class PermutationMap, class SuperNodeMap, class VertexIndexMap >
0298 class mmd_impl
0299 {
0300
0301 typedef graph_traits< Graph > Traits;
0302 typedef typename Traits::vertices_size_type size_type;
0303 typedef typename detail::integer_traits< size_type >::difference_type
0304 diff_t;
0305 typedef typename Traits::vertex_descriptor vertex_t;
0306 typedef typename Traits::adjacency_iterator adj_iter;
0307 typedef iterator_property_map< vertex_t*, identity_property_map,
0308 vertex_t, vertex_t& >
0309 IndexVertexMap;
0310 typedef detail::Stacks< diff_t > Workspace;
0311 typedef bucket_sorter< size_type, vertex_t, DegreeMap, VertexIndexMap >
0312 DegreeLists;
0313 typedef Numbering< InversePermutationMap, diff_t, vertex_t,
0314 VertexIndexMap >
0315 NumberingD;
0316 typedef degreelists_marker< diff_t, vertex_t, VertexIndexMap >
0317 DegreeListsMarker;
0318 typedef Marker< diff_t, vertex_t, VertexIndexMap > MarkerP;
0319
0320
0321 bool has_no_edges;
0322
0323
0324 Graph& G;
0325 int delta;
0326 DegreeMap degree;
0327 InversePermutationMap inverse_perm;
0328 PermutationMap perm;
0329 SuperNodeMap supernode_size;
0330 VertexIndexMap vertex_index_map;
0331
0332
0333 std::vector< vertex_t > index_vertex_vec;
0334 size_type n;
0335 IndexVertexMap index_vertex_map;
0336 DegreeLists degreelists;
0337 NumberingD numbering;
0338 DegreeListsMarker degree_lists_marker;
0339 MarkerP marker;
0340 Workspace work_space;
0341
0342 public:
0343 mmd_impl(Graph& g, size_type n_, int delta, DegreeMap degree,
0344 InversePermutationMap inverse_perm, PermutationMap perm,
0345 SuperNodeMap supernode_size, VertexIndexMap id)
0346 : has_no_edges(true)
0347 , G(g)
0348 , delta(delta)
0349 , degree(degree)
0350 , inverse_perm(inverse_perm)
0351 , perm(perm)
0352 , supernode_size(supernode_size)
0353 , vertex_index_map(id)
0354 , index_vertex_vec(n_)
0355 , n(n_)
0356 , degreelists(n_ + 1, n_, degree, id)
0357 , numbering(inverse_perm, n_, vertex_index_map)
0358 , degree_lists_marker(n_, vertex_index_map)
0359 , marker(n_, vertex_index_map)
0360 , work_space(n_)
0361 {
0362 typename graph_traits< Graph >::vertex_iterator v, vend;
0363 size_type vid = 0;
0364 for (boost::tie(v, vend) = vertices(G); v != vend; ++v, ++vid)
0365 index_vertex_vec[vid] = *v;
0366 index_vertex_map = IndexVertexMap(&index_vertex_vec[0]);
0367
0368
0369
0370 for (boost::tie(v, vend) = vertices(G); v != vend; ++v)
0371 {
0372 typename Traits::degree_size_type d = out_degree(*v, G);
0373 put(degree, *v, d);
0374 if (0 < d)
0375 has_no_edges = false;
0376 degreelists.push(*v);
0377 }
0378 }
0379
0380 void do_mmd()
0381 {
0382
0383
0384
0385
0386 typename DegreeLists::stack list_isolated = degreelists[0];
0387 while (!list_isolated.empty())
0388 {
0389 vertex_t node = list_isolated.top();
0390 marker.mark_done(node);
0391 numbering(node);
0392 numbering.increment();
0393 list_isolated.pop();
0394 }
0395
0396 if (has_no_edges)
0397 {
0398 return;
0399 }
0400
0401 size_type min_degree = 1;
0402 typename DegreeLists::stack list_min_degree
0403 = degreelists[min_degree];
0404
0405 while (list_min_degree.empty())
0406 {
0407 ++min_degree;
0408 list_min_degree = degreelists[min_degree];
0409 }
0410
0411
0412 while (!numbering.all_done())
0413 {
0414
0415 size_type min_degree_limit = min_degree + delta;
0416 typename Workspace::stack llist = work_space.make_stack();
0417
0418
0419 while (delta >= 0)
0420 {
0421
0422
0423 for (list_min_degree = degreelists[min_degree];
0424 list_min_degree.empty()
0425 && min_degree <= min_degree_limit;
0426 ++min_degree,
0427 list_min_degree = degreelists[min_degree])
0428 ;
0429 if (min_degree > min_degree_limit)
0430 break;
0431
0432 const vertex_t node = list_min_degree.top();
0433 const size_type node_id = get(vertex_index_map, node);
0434 list_min_degree.pop();
0435 numbering(node);
0436
0437
0438 if (numbering.all_done(supernode_size[node]))
0439 {
0440 numbering.increment(supernode_size[node]);
0441 break;
0442 }
0443 marker.increment_tag();
0444 marker.mark_tagged(node);
0445
0446 this->eliminate(node);
0447
0448 numbering.increment(supernode_size[node]);
0449 llist.push(node_id);
0450 }
0451
0452 if (numbering.all_done())
0453 break;
0454
0455 this->update(llist, min_degree);
0456 }
0457
0458 }
0459
0460 void eliminate(vertex_t node)
0461 {
0462 typename Workspace::stack element_neighbor
0463 = work_space.make_stack();
0464
0465
0466 typedef typename Workspace::stack WorkStack;
0467 predicateRemoveEdge1< Graph, MarkerP, NumberingD, WorkStack,
0468 VertexIndexMap >
0469 p(G, marker, numbering, element_neighbor, vertex_index_map);
0470
0471 predicate_remove_tagged_edges< Graph, MarkerP > p2(G, marker);
0472
0473
0474
0475 remove_out_edge_if(node, p, G);
0476
0477
0478 while (!element_neighbor.empty())
0479 {
0480
0481 size_type e_id = element_neighbor.top();
0482 vertex_t element = get(index_vertex_map, e_id);
0483 adj_iter i, i_end;
0484 for (boost::tie(i, i_end) = adjacent_vertices(element, G);
0485 i != i_end; ++i)
0486 {
0487 vertex_t i_node = *i;
0488 if (!marker.is_tagged(i_node)
0489 && !numbering.is_numbered(i_node))
0490 {
0491 marker.mark_tagged(i_node);
0492 add_edge(node, i_node, G);
0493 }
0494 }
0495 element_neighbor.pop();
0496 }
0497 adj_iter v, ve;
0498 for (boost::tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v)
0499 {
0500 vertex_t v_node = *v;
0501 if (!degree_lists_marker.need_update(v_node)
0502 && !degree_lists_marker.outmatched_or_done(v_node))
0503 {
0504 degreelists.remove(v_node);
0505 }
0506
0507 remove_out_edge_if(v_node, p2, G);
0508
0509 if (out_degree(v_node, G) == 0)
0510 {
0511 supernode_size[node] += supernode_size[v_node];
0512 supernode_size[v_node] = 0;
0513 numbering.indistinguishable(v_node, node);
0514 marker.mark_done(v_node);
0515 degree_lists_marker.mark(v_node);
0516 }
0517 else
0518 {
0519 add_edge(v_node, node, G);
0520 degree_lists_marker.mark_need_update(v_node);
0521 }
0522 }
0523 }
0524
0525 template < class Stack > void update(Stack llist, size_type& min_degree)
0526 {
0527 size_type min_degree0 = min_degree + delta + 1;
0528
0529 while (!llist.empty())
0530 {
0531 size_type deg, deg0 = 0;
0532
0533 marker.set_multiple_tag(min_degree0);
0534 typename Workspace::stack q2list = work_space.make_stack();
0535 typename Workspace::stack qxlist = work_space.make_stack();
0536
0537 vertex_t current = get(index_vertex_map, llist.top());
0538 adj_iter i, ie;
0539 for (boost::tie(i, ie) = adjacent_vertices(current, G); i != ie;
0540 ++i)
0541 {
0542 vertex_t i_node = *i;
0543 const size_type i_id = get(vertex_index_map, i_node);
0544 if (supernode_size[i_node] != 0)
0545 {
0546 deg0 += supernode_size[i_node];
0547 marker.mark_multiple_tagged(i_node);
0548 if (degree_lists_marker.need_update(i_node))
0549 {
0550 if (out_degree(i_node, G) == 2)
0551 q2list.push(i_id);
0552 else
0553 qxlist.push(i_id);
0554 }
0555 }
0556 }
0557
0558 while (!q2list.empty())
0559 {
0560 const size_type u_id = q2list.top();
0561 vertex_t u_node = get(index_vertex_map, u_id);
0562
0563 if (degree_lists_marker.outmatched_or_done(u_node))
0564 {
0565 q2list.pop();
0566 continue;
0567 }
0568 marker.increment_tag();
0569 deg = deg0;
0570
0571 adj_iter nu = adjacent_vertices(u_node, G).first;
0572 vertex_t neighbor = *nu;
0573 if (neighbor == u_node)
0574 {
0575 ++nu;
0576 neighbor = *nu;
0577 }
0578 if (numbering.is_numbered(neighbor))
0579 {
0580 adj_iter i, ie;
0581 for (boost::tie(i, ie) = adjacent_vertices(neighbor, G);
0582 i != ie; ++i)
0583 {
0584 const vertex_t i_node = *i;
0585 if (i_node == u_node || supernode_size[i_node] == 0)
0586 continue;
0587 if (marker.is_tagged(i_node))
0588 {
0589 if (degree_lists_marker.need_update(i_node))
0590 {
0591 if (out_degree(i_node, G) == 2)
0592 {
0593 supernode_size[u_node]
0594 += supernode_size[i_node];
0595 supernode_size[i_node] = 0;
0596 numbering.indistinguishable(
0597 i_node, u_node);
0598 marker.mark_done(i_node);
0599 degree_lists_marker.mark(i_node);
0600 }
0601 else
0602 degree_lists_marker.mark(i_node);
0603 }
0604 }
0605 else
0606 {
0607 marker.mark_tagged(i_node);
0608 deg += supernode_size[i_node];
0609 }
0610 }
0611 }
0612 else
0613 deg += supernode_size[neighbor];
0614
0615 deg -= supernode_size[u_node];
0616 degree[u_node] = deg;
0617 degreelists[deg].push(u_node);
0618
0619 degree_lists_marker.unmark(u_node);
0620 if (min_degree > deg)
0621 min_degree = deg;
0622 q2list.pop();
0623 }
0624
0625 while (!qxlist.empty())
0626 {
0627 const size_type u_id = qxlist.top();
0628 const vertex_t u_node = get(index_vertex_map, u_id);
0629
0630
0631 if (degree_lists_marker.outmatched_or_done(u_node))
0632 {
0633 qxlist.pop();
0634 continue;
0635 }
0636 marker.increment_tag();
0637 deg = deg0;
0638 adj_iter i, ie;
0639 for (boost::tie(i, ie) = adjacent_vertices(u_node, G);
0640 i != ie; ++i)
0641 {
0642 vertex_t i_node = *i;
0643 if (marker.is_tagged(i_node))
0644 continue;
0645 marker.mark_tagged(i_node);
0646
0647 if (numbering.is_numbered(i_node))
0648 {
0649 adj_iter j, je;
0650 for (boost::tie(j, je)
0651 = adjacent_vertices(i_node, G);
0652 j != je; ++j)
0653 {
0654 const vertex_t j_node = *j;
0655 if (marker.is_not_tagged(j_node))
0656 {
0657 marker.mark_tagged(j_node);
0658 deg += supernode_size[j_node];
0659 }
0660 }
0661 }
0662 else
0663 deg += supernode_size[i_node];
0664 }
0665 deg -= supernode_size[u_node];
0666 degree[u_node] = deg;
0667 degreelists[deg].push(u_node);
0668
0669 degree_lists_marker.unmark(u_node);
0670 if (min_degree > deg)
0671 min_degree = deg;
0672 qxlist.pop();
0673 }
0674
0675 marker.set_tag_as_multiple_tag();
0676 llist.pop();
0677 }
0678
0679 }
0680
0681 void build_permutation(InversePermutationMap next, PermutationMap prev)
0682 {
0683
0684 size_type i;
0685 for (i = 0; i < n; ++i)
0686 {
0687 diff_t size = supernode_size[get(index_vertex_map, i)];
0688 if (size <= 0)
0689 {
0690 prev[i] = next[i];
0691 supernode_size[get(index_vertex_map, i)]
0692 = next[i] + 1;
0693 }
0694 else
0695 prev[i] = -next[i];
0696 }
0697 for (i = 1; i < n + 1; ++i)
0698 {
0699 if (prev[i - 1] > 0)
0700 continue;
0701 diff_t parent = i;
0702 while (prev[parent - 1] < 0)
0703 {
0704 parent = -prev[parent - 1];
0705 }
0706
0707 diff_t root = parent;
0708 diff_t num = prev[root - 1] + 1;
0709 next[i - 1] = -num;
0710 prev[root - 1] = num;
0711
0712 parent = i;
0713 diff_t next_node = -prev[parent - 1];
0714 while (next_node > 0)
0715 {
0716 prev[parent - 1] = -root;
0717 parent = next_node;
0718 next_node = -prev[parent - 1];
0719 }
0720 }
0721 for (i = 0; i < n; i++)
0722 {
0723 diff_t num = -next[i] - 1;
0724 next[i] = num;
0725 prev[num] = i;
0726 }
0727 }
0728 };
0729
0730 }
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744 template < class Graph, class DegreeMap, class InversePermutationMap,
0745 class PermutationMap, class SuperNodeMap, class VertexIndexMap >
0746 void minimum_degree_ordering(Graph& G, DegreeMap degree,
0747 InversePermutationMap inverse_perm, PermutationMap perm,
0748 SuperNodeMap supernode_size, int delta, VertexIndexMap vertex_index_map)
0749 {
0750 detail::mmd_impl< Graph, DegreeMap, InversePermutationMap, PermutationMap,
0751 SuperNodeMap, VertexIndexMap >
0752 impl(G, num_vertices(G), delta, degree, inverse_perm, perm,
0753 supernode_size, vertex_index_map);
0754 impl.do_mmd();
0755 impl.build_permutation(inverse_perm, perm);
0756 }
0757
0758 }
0759
0760 #endif