annotate DEPENDENCIES/generic/include/boost/graph/king_ordering.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 //=======================================================================
Chris@16 2 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
Chris@16 3 // Copyright 2004, 2005 Trustees of Indiana University
Chris@16 4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
Chris@16 5 // Doug Gregor, D. Kevin McGrath
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 8 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 9 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10 //=======================================================================//
Chris@16 11 #ifndef BOOST_GRAPH_KING_HPP
Chris@16 12 #define BOOST_GRAPH_KING_HPP
Chris@16 13
Chris@16 14 #include <boost/config.hpp>
Chris@16 15 #include <boost/graph/detail/sparse_ordering.hpp>
Chris@16 16 #include <boost/graph/graph_utility.hpp>
Chris@16 17
Chris@16 18 /*
Chris@16 19 King Algorithm for matrix reordering
Chris@16 20 */
Chris@16 21
Chris@16 22 namespace boost {
Chris@16 23 namespace detail {
Chris@16 24 template<typename OutputIterator, typename Buffer, typename Compare,
Chris@16 25 typename PseudoDegreeMap, typename VecMap, typename VertexIndexMap>
Chris@16 26 class bfs_king_visitor:public default_bfs_visitor
Chris@16 27 {
Chris@16 28 public:
Chris@16 29 bfs_king_visitor(OutputIterator *iter, Buffer *b, Compare compare,
Chris@16 30 PseudoDegreeMap deg, std::vector<int> loc, VecMap color,
Chris@16 31 VertexIndexMap vertices):
Chris@16 32 permutation(iter), Qptr(b), degree(deg), comp(compare),
Chris@16 33 Qlocation(loc), colors(color), vertex_map(vertices) { }
Chris@16 34
Chris@16 35 template <typename Vertex, typename Graph>
Chris@16 36 void finish_vertex(Vertex, Graph& g) {
Chris@16 37 typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
Chris@16 38 Vertex v, w;
Chris@16 39
Chris@16 40 typedef typename std::deque<Vertex>::reverse_iterator reverse_iterator;
Chris@16 41
Chris@16 42 reverse_iterator rend = Qptr->rend()-index_begin;
Chris@16 43 reverse_iterator rbegin = Qptr->rbegin();
Chris@16 44
Chris@16 45
Chris@16 46 //heap the vertices already there
Chris@16 47 std::make_heap(rbegin, rend, boost::bind<bool>(comp, _2, _1));
Chris@16 48
Chris@16 49 unsigned i = 0;
Chris@16 50
Chris@16 51 for(i = index_begin; i != Qptr->size(); ++i){
Chris@16 52 colors[get(vertex_map, (*Qptr)[i])] = 1;
Chris@16 53 Qlocation[get(vertex_map, (*Qptr)[i])] = i;
Chris@16 54 }
Chris@16 55
Chris@16 56 i = 0;
Chris@16 57
Chris@16 58 for( ; rbegin != rend; rend--){
Chris@16 59 percolate_down<Vertex>(i);
Chris@16 60 w = (*Qptr)[index_begin+i];
Chris@16 61 for (boost::tie(ei, ei_end) = out_edges(w, g); ei != ei_end; ++ei) {
Chris@16 62 v = target(*ei, g);
Chris@16 63 put(degree, v, get(degree, v) - 1);
Chris@16 64
Chris@16 65 if (colors[get(vertex_map, v)] == 1) {
Chris@16 66 percolate_up<Vertex>(get(vertex_map, v), i);
Chris@16 67 }
Chris@16 68 }
Chris@16 69
Chris@16 70 colors[get(vertex_map, w)] = 0;
Chris@16 71 i++;
Chris@16 72 }
Chris@16 73 }
Chris@16 74
Chris@16 75 template <typename Vertex, typename Graph>
Chris@16 76 void examine_vertex(Vertex u, const Graph&) {
Chris@16 77
Chris@16 78 *(*permutation)++ = u;
Chris@16 79 index_begin = Qptr->size();
Chris@16 80
Chris@16 81 }
Chris@16 82 protected:
Chris@16 83
Chris@16 84
Chris@16 85 //this function replaces pop_heap, and tracks state information
Chris@16 86 template <typename Vertex>
Chris@16 87 void percolate_down(int offset){
Chris@16 88 int heap_last = index_begin + offset;
Chris@16 89 int heap_first = Qptr->size() - 1;
Chris@16 90
Chris@16 91 //pop_heap functionality:
Chris@16 92 //swap first, last
Chris@16 93 std::swap((*Qptr)[heap_last], (*Qptr)[heap_first]);
Chris@16 94
Chris@16 95 //swap in the location queue
Chris@16 96 std::swap(Qlocation[heap_first], Qlocation[heap_last]);
Chris@16 97
Chris@16 98 //set drifter, children
Chris@16 99 int drifter = heap_first;
Chris@16 100 int drifter_heap = Qptr->size() - drifter;
Chris@16 101
Chris@16 102 int right_child_heap = drifter_heap * 2 + 1;
Chris@16 103 int right_child = Qptr->size() - right_child_heap;
Chris@16 104
Chris@16 105 int left_child_heap = drifter_heap * 2;
Chris@16 106 int left_child = Qptr->size() - left_child_heap;
Chris@16 107
Chris@16 108 //check that we are staying in the heap
Chris@16 109 bool valid = (right_child < heap_last) ? false : true;
Chris@16 110
Chris@16 111 //pick smallest child of drifter, and keep in mind there might only be left child
Chris@16 112 int smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ?
Chris@16 113 right_child : left_child;
Chris@16 114
Chris@16 115 while(valid && smallest_child < heap_last && comp((*Qptr)[drifter], (*Qptr)[smallest_child])){
Chris@16 116
Chris@16 117 //if smallest child smaller than drifter, swap them
Chris@16 118 std::swap((*Qptr)[smallest_child], (*Qptr)[drifter]);
Chris@16 119 std::swap(Qlocation[drifter], Qlocation[smallest_child]);
Chris@16 120
Chris@16 121 //update the values, run again, as necessary
Chris@16 122 drifter = smallest_child;
Chris@16 123 drifter_heap = Qptr->size() - drifter;
Chris@16 124
Chris@16 125 right_child_heap = drifter_heap * 2 + 1;
Chris@16 126 right_child = Qptr->size() - right_child_heap;
Chris@16 127
Chris@16 128 left_child_heap = drifter_heap * 2;
Chris@16 129 left_child = Qptr->size() - left_child_heap;
Chris@16 130
Chris@16 131 valid = (right_child < heap_last) ? false : true;
Chris@16 132
Chris@16 133 smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ?
Chris@16 134 right_child : left_child;
Chris@16 135 }
Chris@16 136
Chris@16 137 }
Chris@16 138
Chris@16 139
Chris@16 140
Chris@16 141 // this is like percolate down, but we always compare against the
Chris@16 142 // parent, as there is only a single choice
Chris@16 143 template <typename Vertex>
Chris@16 144 void percolate_up(int vertex, int offset){
Chris@16 145
Chris@16 146 int child_location = Qlocation[vertex];
Chris@16 147 int heap_child_location = Qptr->size() - child_location;
Chris@16 148 int heap_parent_location = (int)(heap_child_location/2);
Chris@16 149 unsigned parent_location = Qptr->size() - heap_parent_location;
Chris@16 150
Chris@16 151 bool valid = (heap_parent_location != 0 && child_location > index_begin + offset &&
Chris@16 152 parent_location < Qptr->size());
Chris@16 153
Chris@16 154 while(valid && comp((*Qptr)[child_location], (*Qptr)[parent_location])){
Chris@16 155
Chris@16 156 //swap in the heap
Chris@16 157 std::swap((*Qptr)[child_location], (*Qptr)[parent_location]);
Chris@16 158
Chris@16 159 //swap in the location queue
Chris@16 160 std::swap(Qlocation[child_location], Qlocation[parent_location]);
Chris@16 161
Chris@16 162 child_location = parent_location;
Chris@16 163 heap_child_location = heap_parent_location;
Chris@16 164 heap_parent_location = (int)(heap_child_location/2);
Chris@16 165 parent_location = Qptr->size() - heap_parent_location;
Chris@16 166 valid = (heap_parent_location != 0 && child_location > index_begin + offset);
Chris@16 167 }
Chris@16 168 }
Chris@16 169
Chris@16 170 OutputIterator *permutation;
Chris@16 171 int index_begin;
Chris@16 172 Buffer *Qptr;
Chris@16 173 PseudoDegreeMap degree;
Chris@16 174 Compare comp;
Chris@16 175 std::vector<int> Qlocation;
Chris@16 176 VecMap colors;
Chris@16 177 VertexIndexMap vertex_map;
Chris@16 178 };
Chris@16 179
Chris@16 180
Chris@16 181 } // namespace detail
Chris@16 182
Chris@16 183
Chris@16 184 template<class Graph, class OutputIterator, class ColorMap, class DegreeMap,
Chris@16 185 typename VertexIndexMap>
Chris@16 186 OutputIterator
Chris@16 187 king_ordering(const Graph& g,
Chris@16 188 std::deque< typename graph_traits<Graph>::vertex_descriptor >
Chris@16 189 vertex_queue,
Chris@16 190 OutputIterator permutation,
Chris@16 191 ColorMap color, DegreeMap degree,
Chris@16 192 VertexIndexMap index_map)
Chris@16 193 {
Chris@16 194 typedef typename property_traits<DegreeMap>::value_type ds_type;
Chris@16 195 typedef typename property_traits<ColorMap>::value_type ColorValue;
Chris@16 196 typedef color_traits<ColorValue> Color;
Chris@16 197 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 198 typedef iterator_property_map<typename std::vector<ds_type>::iterator, VertexIndexMap, ds_type, ds_type&> PseudoDegreeMap;
Chris@16 199 typedef indirect_cmp<PseudoDegreeMap, std::less<ds_type> > Compare;
Chris@16 200 typedef typename boost::sparse::sparse_ordering_queue<Vertex> queue;
Chris@16 201 typedef typename detail::bfs_king_visitor<OutputIterator, queue, Compare,
Chris@16 202 PseudoDegreeMap, std::vector<int>, VertexIndexMap > Visitor;
Chris@16 203 typedef typename graph_traits<Graph>::vertices_size_type
Chris@16 204 vertices_size_type;
Chris@16 205 std::vector<ds_type> pseudo_degree_vec(num_vertices(g));
Chris@16 206 PseudoDegreeMap pseudo_degree(pseudo_degree_vec.begin(), index_map);
Chris@16 207
Chris@16 208 typename graph_traits<Graph>::vertex_iterator ui, ui_end;
Chris@16 209 queue Q;
Chris@16 210 // Copy degree to pseudo_degree
Chris@16 211 // initialize the color map
Chris@16 212 for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui){
Chris@16 213 put(pseudo_degree, *ui, get(degree, *ui));
Chris@16 214 put(color, *ui, Color::white());
Chris@16 215 }
Chris@16 216
Chris@16 217 Compare comp(pseudo_degree);
Chris@16 218 std::vector<int> colors(num_vertices(g));
Chris@16 219
Chris@16 220 for(vertices_size_type i = 0; i < num_vertices(g); i++)
Chris@16 221 colors[i] = 0;
Chris@16 222
Chris@16 223 std::vector<int> loc(num_vertices(g));
Chris@16 224
Chris@16 225 //create the visitor
Chris@16 226 Visitor vis(&permutation, &Q, comp, pseudo_degree, loc, colors, index_map);
Chris@16 227
Chris@16 228 while( !vertex_queue.empty() ) {
Chris@16 229 Vertex s = vertex_queue.front();
Chris@16 230 vertex_queue.pop_front();
Chris@16 231
Chris@16 232 //call BFS with visitor
Chris@16 233 breadth_first_visit(g, s, Q, vis, color);
Chris@16 234 }
Chris@16 235
Chris@16 236 return permutation;
Chris@16 237 }
Chris@16 238
Chris@16 239
Chris@16 240 // This is the case where only a single starting vertex is supplied.
Chris@16 241 template <class Graph, class OutputIterator,
Chris@16 242 class ColorMap, class DegreeMap, typename VertexIndexMap>
Chris@16 243 OutputIterator
Chris@16 244 king_ordering(const Graph& g,
Chris@16 245 typename graph_traits<Graph>::vertex_descriptor s,
Chris@16 246 OutputIterator permutation,
Chris@16 247 ColorMap color, DegreeMap degree, VertexIndexMap index_map)
Chris@16 248 {
Chris@16 249
Chris@16 250 std::deque< typename graph_traits<Graph>::vertex_descriptor > vertex_queue;
Chris@16 251 vertex_queue.push_front( s );
Chris@16 252 return king_ordering(g, vertex_queue, permutation, color, degree,
Chris@16 253 index_map);
Chris@16 254 }
Chris@16 255
Chris@16 256
Chris@16 257 template < class Graph, class OutputIterator,
Chris@16 258 class ColorMap, class DegreeMap, class VertexIndexMap>
Chris@16 259 OutputIterator
Chris@16 260 king_ordering(const Graph& G, OutputIterator permutation,
Chris@16 261 ColorMap color, DegreeMap degree, VertexIndexMap index_map)
Chris@16 262 {
Chris@16 263 if (has_no_vertices(G))
Chris@16 264 return permutation;
Chris@16 265
Chris@16 266 typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 267 typedef typename property_traits<ColorMap>::value_type ColorValue;
Chris@16 268 typedef color_traits<ColorValue> Color;
Chris@16 269
Chris@16 270 std::deque<Vertex> vertex_queue;
Chris@16 271
Chris@16 272 // Mark everything white
Chris@16 273 BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white());
Chris@16 274
Chris@16 275 // Find one vertex from each connected component
Chris@16 276 BGL_FORALL_VERTICES_T(v, G, Graph) {
Chris@16 277 if (get(color, v) == Color::white()) {
Chris@16 278 depth_first_visit(G, v, dfs_visitor<>(), color);
Chris@16 279 vertex_queue.push_back(v);
Chris@16 280 }
Chris@16 281 }
Chris@16 282
Chris@16 283 // Find starting nodes for all vertices
Chris@16 284 // TBD: How to do this with a directed graph?
Chris@16 285 for (typename std::deque<Vertex>::iterator i = vertex_queue.begin();
Chris@16 286 i != vertex_queue.end(); ++i)
Chris@16 287 *i = find_starting_node(G, *i, color, degree);
Chris@16 288
Chris@16 289 return king_ordering(G, vertex_queue, permutation, color, degree,
Chris@16 290 index_map);
Chris@16 291 }
Chris@16 292
Chris@16 293 template<typename Graph, typename OutputIterator, typename VertexIndexMap>
Chris@16 294 OutputIterator
Chris@16 295 king_ordering(const Graph& G, OutputIterator permutation,
Chris@16 296 VertexIndexMap index_map)
Chris@16 297 {
Chris@16 298 if (has_no_vertices(G))
Chris@16 299 return permutation;
Chris@16 300
Chris@16 301 std::vector<default_color_type> colors(num_vertices(G));
Chris@16 302 return king_ordering(G, permutation,
Chris@16 303 make_iterator_property_map(&colors[0], index_map,
Chris@16 304 colors[0]),
Chris@16 305 make_out_degree_map(G), index_map);
Chris@16 306 }
Chris@16 307
Chris@16 308 template<typename Graph, typename OutputIterator>
Chris@16 309 inline OutputIterator
Chris@16 310 king_ordering(const Graph& G, OutputIterator permutation)
Chris@16 311 { return king_ordering(G, permutation, get(vertex_index, G)); }
Chris@16 312
Chris@16 313 } // namespace boost
Chris@16 314
Chris@16 315
Chris@16 316 #endif // BOOST_GRAPH_KING_HPP