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
14 #include <boost/config.hpp>
15 #include <boost/graph/detail/sparse_ordering.hpp>
18 King Algorithm for matrix reordering
23 template<typename OutputIterator
, typename Buffer
, typename Compare
,
24 typename PseudoDegreeMap
, typename VecMap
, typename VertexIndexMap
>
25 class bfs_king_visitor
:public default_bfs_visitor
28 bfs_king_visitor(OutputIterator
*iter
, Buffer
*b
, Compare compare
,
29 PseudoDegreeMap deg
, std::vector
<int> loc
, VecMap color
,
30 VertexIndexMap vertices
):
31 permutation(iter
), Qptr(b
), degree(deg
), comp(compare
),
32 Qlocation(loc
), colors(color
), vertex_map(vertices
) { }
34 template <typename Vertex
, typename Graph
>
35 void finish_vertex(Vertex
, Graph
& g
) {
36 typename graph_traits
<Graph
>::out_edge_iterator ei
, ei_end
;
39 typedef typename
std::deque
<Vertex
>::iterator iterator
;
40 typedef typename
std::deque
<Vertex
>::reverse_iterator reverse_iterator
;
42 reverse_iterator rend
= Qptr
->rend()-index_begin
;
43 reverse_iterator rbegin
= Qptr
->rbegin();
46 //heap the vertices already there
47 std::make_heap(rbegin
, rend
, boost::bind
<bool>(comp
, _2
, _1
));
51 for(i
= index_begin
; i
!= Qptr
->size(); ++i
){
52 colors
[get(vertex_map
, (*Qptr
)[i
])] = 1;
53 Qlocation
[get(vertex_map
, (*Qptr
)[i
])] = i
;
58 for( ; rbegin
!= rend
; rend
--){
59 percolate_down
<Vertex
>(i
);
60 w
= (*Qptr
)[index_begin
+i
];
61 for (tie(ei
, ei_end
) = out_edges(w
, g
); ei
!= ei_end
; ++ei
) {
63 put(degree
, v
, get(degree
, v
) - 1);
65 if (colors
[get(vertex_map
, v
)] == 1) {
66 percolate_up
<Vertex
>(get(vertex_map
, v
), i
);
70 colors
[get(vertex_map
, w
)] = 0;
75 template <typename Vertex
, typename Graph
>
76 void examine_vertex(Vertex u
, const Graph
&) {
78 *(*permutation
)++ = u
;
79 index_begin
= Qptr
->size();
85 //this function replaces pop_heap, and tracks state information
86 template <typename Vertex
>
87 void percolate_down(int offset
){
88 typedef typename
std::deque
<Vertex
>::reverse_iterator reverse_iterator
;
90 int heap_last
= index_begin
+ offset
;
91 int heap_first
= Qptr
->size() - 1;
93 //pop_heap functionality:
95 std::swap((*Qptr
)[heap_last
], (*Qptr
)[heap_first
]);
97 //swap in the location queue
98 std::swap(Qlocation
[heap_first
], Qlocation
[heap_last
]);
100 //set drifter, children
101 int drifter
= heap_first
;
102 int drifter_heap
= Qptr
->size() - drifter
;
104 int right_child_heap
= drifter_heap
* 2 + 1;
105 int right_child
= Qptr
->size() - right_child_heap
;
107 int left_child_heap
= drifter_heap
* 2;
108 int left_child
= Qptr
->size() - left_child_heap
;
110 //check that we are staying in the heap
111 bool valid
= (right_child
< heap_last
) ? false : true;
113 //pick smallest child of drifter, and keep in mind there might only be left child
114 int smallest_child
= (valid
&& get(degree
, (*Qptr
)[left_child
]) > get(degree
,(*Qptr
)[right_child
])) ?
115 right_child
: left_child
;
117 while(valid
&& smallest_child
< heap_last
&& comp((*Qptr
)[drifter
], (*Qptr
)[smallest_child
])){
119 //if smallest child smaller than drifter, swap them
120 std::swap((*Qptr
)[smallest_child
], (*Qptr
)[drifter
]);
121 std::swap(Qlocation
[drifter
], Qlocation
[smallest_child
]);
123 //update the values, run again, as necessary
124 drifter
= smallest_child
;
125 drifter_heap
= Qptr
->size() - drifter
;
127 right_child_heap
= drifter_heap
* 2 + 1;
128 right_child
= Qptr
->size() - right_child_heap
;
130 left_child_heap
= drifter_heap
* 2;
131 left_child
= Qptr
->size() - left_child_heap
;
133 valid
= (right_child
< heap_last
) ? false : true;
135 smallest_child
= (valid
&& get(degree
, (*Qptr
)[left_child
]) > get(degree
,(*Qptr
)[right_child
])) ?
136 right_child
: left_child
;
143 // this is like percolate down, but we always compare against the
144 // parent, as there is only a single choice
145 template <typename Vertex
>
146 void percolate_up(int vertex
, int offset
){
148 int child_location
= Qlocation
[vertex
];
149 int heap_child_location
= Qptr
->size() - child_location
;
150 int heap_parent_location
= (int)(heap_child_location
/2);
151 unsigned parent_location
= Qptr
->size() - heap_parent_location
;
153 bool valid
= (heap_parent_location
!= 0 && child_location
> index_begin
+ offset
&&
154 parent_location
< Qptr
->size());
156 while(valid
&& comp((*Qptr
)[child_location
], (*Qptr
)[parent_location
])){
159 std::swap((*Qptr
)[child_location
], (*Qptr
)[parent_location
]);
161 //swap in the location queue
162 std::swap(Qlocation
[child_location
], Qlocation
[parent_location
]);
164 child_location
= parent_location
;
165 heap_child_location
= heap_parent_location
;
166 heap_parent_location
= (int)(heap_child_location
/2);
167 parent_location
= Qptr
->size() - heap_parent_location
;
168 valid
= (heap_parent_location
!= 0 && child_location
> index_begin
+ offset
);
172 OutputIterator
*permutation
;
175 PseudoDegreeMap degree
;
177 std::vector
<int> Qlocation
;
179 VertexIndexMap vertex_map
;
183 } // namespace detail
186 template<class Graph
, class OutputIterator
, class ColorMap
, class DegreeMap
,
187 typename VertexIndexMap
>
189 king_ordering(const Graph
& g
,
190 std::deque
< typename graph_traits
<Graph
>::vertex_descriptor
>
192 OutputIterator permutation
,
193 ColorMap color
, DegreeMap degree
,
194 VertexIndexMap index_map
)
196 typedef typename property_traits
<DegreeMap
>::value_type ds_type
;
197 typedef typename property_traits
<ColorMap
>::value_type ColorValue
;
198 typedef color_traits
<ColorValue
> Color
;
199 typedef typename graph_traits
<Graph
>::vertex_descriptor Vertex
;
200 typedef iterator_property_map
<typename
std::vector
<ds_type
>::iterator
, VertexIndexMap
, ds_type
, ds_type
&> PseudoDegreeMap
;
201 typedef indirect_cmp
<PseudoDegreeMap
, std::less
<ds_type
> > Compare
;
202 typedef typename
boost::sparse::sparse_ordering_queue
<Vertex
> queue
;
203 typedef typename
detail::bfs_king_visitor
<OutputIterator
, queue
, Compare
,
204 PseudoDegreeMap
, std::vector
<int>, VertexIndexMap
> Visitor
;
205 typedef typename graph_traits
<Graph
>::vertices_size_type
207 std::vector
<ds_type
> pseudo_degree_vec(num_vertices(g
));
208 PseudoDegreeMap
pseudo_degree(pseudo_degree_vec
.begin(), index_map
);
210 typename graph_traits
<Graph
>::vertex_iterator ui
, ui_end
;
212 // Copy degree to pseudo_degree
213 // initialize the color map
214 for (tie(ui
, ui_end
) = vertices(g
); ui
!= ui_end
; ++ui
){
215 put(pseudo_degree
, *ui
, get(degree
, *ui
));
216 put(color
, *ui
, Color::white());
219 Compare
comp(pseudo_degree
);
220 std::vector
<int> colors(num_vertices(g
));
222 for(vertices_size_type i
= 0; i
< num_vertices(g
); i
++)
225 std::vector
<int> loc(num_vertices(g
));
228 Visitor
vis(&permutation
, &Q
, comp
, pseudo_degree
, loc
, colors
, index_map
);
230 while( !vertex_queue
.empty() ) {
231 Vertex s
= vertex_queue
.front();
232 vertex_queue
.pop_front();
234 //call BFS with visitor
235 breadth_first_visit(g
, s
, Q
, vis
, color
);
242 // This is the case where only a single starting vertex is supplied.
243 template <class Graph
, class OutputIterator
,
244 class ColorMap
, class DegreeMap
, typename VertexIndexMap
>
246 king_ordering(const Graph
& g
,
247 typename graph_traits
<Graph
>::vertex_descriptor s
,
248 OutputIterator permutation
,
249 ColorMap color
, DegreeMap degree
, VertexIndexMap index_map
)
252 std::deque
< typename graph_traits
<Graph
>::vertex_descriptor
> vertex_queue
;
253 vertex_queue
.push_front( s
);
254 return king_ordering(g
, vertex_queue
, permutation
, color
, degree
,
259 template < class Graph
, class OutputIterator
,
260 class ColorMap
, class DegreeMap
, class VertexIndexMap
>
262 king_ordering(const Graph
& G
, OutputIterator permutation
,
263 ColorMap color
, DegreeMap degree
, VertexIndexMap index_map
)
265 if (vertices(G
).first
== vertices(G
).second
)
268 typedef typename
boost::graph_traits
<Graph
>::vertex_descriptor Vertex
;
269 typedef typename
boost::graph_traits
<Graph
>::vertex_iterator VerIter
;
270 typedef typename property_traits
<ColorMap
>::value_type ColorValue
;
271 typedef color_traits
<ColorValue
> Color
;
273 std::deque
<Vertex
> vertex_queue
;
275 // Mark everything white
276 BGL_FORALL_VERTICES_T(v
, G
, Graph
) put(color
, v
, Color::white());
278 // Find one vertex from each connected component
279 BGL_FORALL_VERTICES_T(v
, G
, Graph
) {
280 if (get(color
, v
) == Color::white()) {
281 depth_first_visit(G
, v
, dfs_visitor
<>(), color
);
282 vertex_queue
.push_back(v
);
286 // Find starting nodes for all vertices
287 // TBD: How to do this with a directed graph?
288 for (typename
std::deque
<Vertex
>::iterator i
= vertex_queue
.begin();
289 i
!= vertex_queue
.end(); ++i
)
290 *i
= find_starting_node(G
, *i
, color
, degree
);
292 return king_ordering(G
, vertex_queue
, permutation
, color
, degree
,
296 template<typename Graph
, typename OutputIterator
, typename VertexIndexMap
>
298 king_ordering(const Graph
& G
, OutputIterator permutation
,
299 VertexIndexMap index_map
)
301 if (vertices(G
).first
== vertices(G
).second
)
304 typedef out_degree_property_map
<Graph
> DegreeMap
;
305 std::vector
<default_color_type
> colors(num_vertices(G
));
306 return king_ordering(G
, permutation
,
307 make_iterator_property_map(&colors
[0], index_map
,
309 make_out_degree_map(G
), index_map
);
312 template<typename Graph
, typename OutputIterator
>
313 inline OutputIterator
314 king_ordering(const Graph
& G
, OutputIterator permutation
)
315 { return king_ordering(G
, permutation
, get(vertex_index
, G
)); }
320 #endif // BOOST_GRAPH_KING_HPP