1 //=======================================================================
2 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
3 // Copyright 2004, 2005 Trustees of Indiana University
4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
5 // Doug Gregor, D. Kevin McGrath
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //=======================================================================//
11 #ifndef BOOST_GRAPH_KING_HPP
12 #define BOOST_GRAPH_KING_HPP
17 #include <boost/config.hpp>
18 #include <boost/bind/bind.hpp>
19 #include <boost/tuple/tuple.hpp>
20 #include <boost/graph/detail/sparse_ordering.hpp>
21 #include <boost/graph/graph_utility.hpp>
24 King Algorithm for matrix reordering
31 template < typename OutputIterator, typename Buffer, typename Compare,
32 typename PseudoDegreeMap, typename VecMap, typename VertexIndexMap >
33 class bfs_king_visitor : public default_bfs_visitor
36 bfs_king_visitor(OutputIterator* iter, Buffer* b, Compare compare,
37 PseudoDegreeMap deg, std::vector< int > loc, VecMap color,
38 VertexIndexMap vertices)
45 , vertex_map(vertices)
49 template < typename Vertex, typename Graph >
50 void finish_vertex(Vertex, Graph& g)
52 using namespace boost::placeholders;
54 typename graph_traits< Graph >::out_edge_iterator ei, ei_end;
57 typedef typename std::deque< Vertex >::reverse_iterator
60 reverse_iterator rend = Qptr->rend() - index_begin;
61 reverse_iterator rbegin = Qptr->rbegin();
63 // heap the vertices already there
64 std::make_heap(rbegin, rend, boost::bind< bool >(comp, _2, _1));
68 for (i = index_begin; i != Qptr->size(); ++i)
70 colors[get(vertex_map, (*Qptr)[i])] = 1;
71 Qlocation[get(vertex_map, (*Qptr)[i])] = i;
76 for (; rbegin != rend; rend--)
78 percolate_down< Vertex >(i);
79 w = (*Qptr)[index_begin + i];
80 for (boost::tie(ei, ei_end) = out_edges(w, g); ei != ei_end;
84 put(degree, v, get(degree, v) - 1);
86 if (colors[get(vertex_map, v)] == 1)
88 percolate_up< Vertex >(get(vertex_map, v), i);
92 colors[get(vertex_map, w)] = 0;
97 template < typename Vertex, typename Graph >
98 void examine_vertex(Vertex u, const Graph&)
101 *(*permutation)++ = u;
102 index_begin = Qptr->size();
106 // this function replaces pop_heap, and tracks state information
107 template < typename Vertex > void percolate_down(int offset)
109 int heap_last = index_begin + offset;
110 int heap_first = Qptr->size() - 1;
112 // pop_heap functionality:
114 std::swap((*Qptr)[heap_last], (*Qptr)[heap_first]);
116 // swap in the location queue
117 std::swap(Qlocation[heap_first], Qlocation[heap_last]);
119 // set drifter, children
120 int drifter = heap_first;
121 int drifter_heap = Qptr->size() - drifter;
123 int right_child_heap = drifter_heap * 2 + 1;
124 int right_child = Qptr->size() - right_child_heap;
126 int left_child_heap = drifter_heap * 2;
127 int left_child = Qptr->size() - left_child_heap;
129 // check that we are staying in the heap
130 bool valid = (right_child < heap_last) ? false : true;
132 // pick smallest child of drifter, and keep in mind there might only
134 int smallest_child = (valid
135 && get(degree, (*Qptr)[left_child])
136 > get(degree, (*Qptr)[right_child]))
140 while (valid && smallest_child < heap_last
141 && comp((*Qptr)[drifter], (*Qptr)[smallest_child]))
144 // if smallest child smaller than drifter, swap them
145 std::swap((*Qptr)[smallest_child], (*Qptr)[drifter]);
146 std::swap(Qlocation[drifter], Qlocation[smallest_child]);
148 // update the values, run again, as necessary
149 drifter = smallest_child;
150 drifter_heap = Qptr->size() - drifter;
152 right_child_heap = drifter_heap * 2 + 1;
153 right_child = Qptr->size() - right_child_heap;
155 left_child_heap = drifter_heap * 2;
156 left_child = Qptr->size() - left_child_heap;
158 valid = (right_child < heap_last) ? false : true;
160 smallest_child = (valid
161 && get(degree, (*Qptr)[left_child])
162 > get(degree, (*Qptr)[right_child]))
168 // this is like percolate down, but we always compare against the
169 // parent, as there is only a single choice
170 template < typename Vertex > void percolate_up(int vertex, int offset)
173 int child_location = Qlocation[vertex];
174 int heap_child_location = Qptr->size() - child_location;
175 int heap_parent_location = (int)(heap_child_location / 2);
176 unsigned parent_location = Qptr->size() - heap_parent_location;
178 bool valid = (heap_parent_location != 0
179 && child_location > index_begin + offset
180 && parent_location < Qptr->size());
183 && comp((*Qptr)[child_location], (*Qptr)[parent_location]))
187 std::swap((*Qptr)[child_location], (*Qptr)[parent_location]);
189 // swap in the location queue
191 Qlocation[child_location], Qlocation[parent_location]);
193 child_location = parent_location;
194 heap_child_location = heap_parent_location;
195 heap_parent_location = (int)(heap_child_location / 2);
196 parent_location = Qptr->size() - heap_parent_location;
197 valid = (heap_parent_location != 0
198 && child_location > index_begin + offset);
202 OutputIterator* permutation;
205 PseudoDegreeMap degree;
207 std::vector< int > Qlocation;
209 VertexIndexMap vertex_map;
212 } // namespace detail
214 template < class Graph, class OutputIterator, class ColorMap, class DegreeMap,
215 typename VertexIndexMap >
216 OutputIterator king_ordering(const Graph& g,
217 std::deque< typename graph_traits< Graph >::vertex_descriptor >
219 OutputIterator permutation, ColorMap color, DegreeMap degree,
220 VertexIndexMap index_map)
222 typedef typename property_traits< DegreeMap >::value_type ds_type;
223 typedef typename property_traits< ColorMap >::value_type ColorValue;
224 typedef color_traits< ColorValue > Color;
225 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
226 typedef iterator_property_map< typename std::vector< ds_type >::iterator,
227 VertexIndexMap, ds_type, ds_type& >
229 typedef indirect_cmp< PseudoDegreeMap, std::less< ds_type > > Compare;
230 typedef typename boost::sparse::sparse_ordering_queue< Vertex > queue;
231 typedef typename detail::bfs_king_visitor< OutputIterator, queue, Compare,
232 PseudoDegreeMap, std::vector< int >, VertexIndexMap >
235 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
236 std::vector< ds_type > pseudo_degree_vec(num_vertices(g));
237 PseudoDegreeMap pseudo_degree(pseudo_degree_vec.begin(), index_map);
239 typename graph_traits< Graph >::vertex_iterator ui, ui_end;
241 // Copy degree to pseudo_degree
242 // initialize the color map
243 for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
245 put(pseudo_degree, *ui, get(degree, *ui));
246 put(color, *ui, Color::white());
249 Compare comp(pseudo_degree);
250 std::vector< int > colors(num_vertices(g));
252 for (vertices_size_type i = 0; i < num_vertices(g); i++)
255 std::vector< int > loc(num_vertices(g));
257 // create the visitor
258 Visitor vis(&permutation, &Q, comp, pseudo_degree, loc, colors, index_map);
260 while (!vertex_queue.empty())
262 Vertex s = vertex_queue.front();
263 vertex_queue.pop_front();
265 // call BFS with visitor
266 breadth_first_visit(g, s, Q, vis, color);
272 // This is the case where only a single starting vertex is supplied.
273 template < class Graph, class OutputIterator, class ColorMap, class DegreeMap,
274 typename VertexIndexMap >
275 OutputIterator king_ordering(const Graph& g,
276 typename graph_traits< Graph >::vertex_descriptor s,
277 OutputIterator permutation, ColorMap color, DegreeMap degree,
278 VertexIndexMap index_map)
281 std::deque< typename graph_traits< Graph >::vertex_descriptor >
283 vertex_queue.push_front(s);
284 return king_ordering(
285 g, vertex_queue, permutation, color, degree, index_map);
288 template < class Graph, class OutputIterator, class ColorMap, class DegreeMap,
289 class VertexIndexMap >
290 OutputIterator king_ordering(const Graph& G, OutputIterator permutation,
291 ColorMap color, DegreeMap degree, VertexIndexMap index_map)
293 if (has_no_vertices(G))
296 typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex;
297 typedef typename property_traits< ColorMap >::value_type ColorValue;
298 typedef color_traits< ColorValue > Color;
300 std::deque< Vertex > vertex_queue;
302 // Mark everything white
303 BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white());
305 // Find one vertex from each connected component
306 BGL_FORALL_VERTICES_T(v, G, Graph)
308 if (get(color, v) == Color::white())
310 depth_first_visit(G, v, dfs_visitor<>(), color);
311 vertex_queue.push_back(v);
315 // Find starting nodes for all vertices
316 // TBD: How to do this with a directed graph?
317 for (typename std::deque< Vertex >::iterator i = vertex_queue.begin();
318 i != vertex_queue.end(); ++i)
319 *i = find_starting_node(G, *i, color, degree);
321 return king_ordering(
322 G, vertex_queue, permutation, color, degree, index_map);
325 template < typename Graph, typename OutputIterator, typename VertexIndexMap >
326 OutputIterator king_ordering(
327 const Graph& G, OutputIterator permutation, VertexIndexMap index_map)
329 if (has_no_vertices(G))
332 std::vector< default_color_type > colors(num_vertices(G));
333 return king_ordering(G, permutation,
334 make_iterator_property_map(&colors[0], index_map, colors[0]),
335 make_out_degree_map(G), index_map);
338 template < typename Graph, typename OutputIterator >
339 inline OutputIterator king_ordering(const Graph& G, OutputIterator permutation)
341 return king_ordering(G, permutation, get(vertex_index, G));
346 #endif // BOOST_GRAPH_KING_HPP