sloan_ordering.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. //
  2. //=======================================================================
  3. // Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch)
  4. // ETH Zurich, Center of Structure Technologies
  5. // (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/)
  6. //
  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. //
  12. #ifndef BOOST_GRAPH_SLOAN_HPP
  13. #define BOOST_GRAPH_SLOAN_HPP
  14. #define WEIGHT1 1 // default weight for the distance in the Sloan algorithm
  15. #define WEIGHT2 2 // default weight for the degree in the Sloan algorithm
  16. #include <boost/config.hpp>
  17. #include <vector>
  18. #include <queue>
  19. #include <algorithm>
  20. #include <limits>
  21. #include <boost/pending/queue.hpp>
  22. #include <boost/graph/graph_traits.hpp>
  23. #include <boost/graph/breadth_first_search.hpp>
  24. #include <boost/graph/properties.hpp>
  25. #include <boost/pending/indirect_cmp.hpp>
  26. #include <boost/property_map/property_map.hpp>
  27. #include <boost/graph/visitors.hpp>
  28. #include <boost/graph/adjacency_list.hpp>
  29. #include <boost/graph/cuthill_mckee_ordering.hpp>
  30. ////////////////////////////////////////////////////////////
  31. //
  32. // Sloan-Algorithm for graph reordering
  33. //(optimzes profile and wavefront, not primiraly bandwidth
  34. //
  35. ////////////////////////////////////////////////////////////
  36. namespace boost
  37. {
  38. /////////////////////////////////////////////////////////////////////////
  39. // Function that returns the maximum depth of
  40. // a rooted level strucutre (RLS)
  41. //
  42. /////////////////////////////////////////////////////////////////////////
  43. template < class Distance > typename Distance::value_type RLS_depth(Distance& d)
  44. {
  45. typename Distance::value_type h_s = 0;
  46. typename Distance::iterator iter;
  47. for (iter = d.begin(); iter != d.end(); ++iter)
  48. {
  49. if (*iter > h_s)
  50. {
  51. h_s = *iter;
  52. }
  53. }
  54. return h_s;
  55. }
  56. /////////////////////////////////////////////////////////////////////////
  57. // Function that returns the width of the largest level of
  58. // a rooted level strucutre (RLS)
  59. //
  60. /////////////////////////////////////////////////////////////////////////
  61. template < class Distance, class my_int >
  62. typename Distance::value_type RLS_max_width(Distance& d, my_int depth)
  63. {
  64. typedef typename Distance::value_type Degree;
  65. // Searching for the maximum width of a level
  66. std::vector< Degree > dummy_width(depth + 1, 0);
  67. typename std::vector< Degree >::iterator my_it;
  68. typename Distance::iterator iter;
  69. Degree w_max = 0;
  70. for (iter = d.begin(); iter != d.end(); ++iter)
  71. {
  72. dummy_width[*iter]++;
  73. }
  74. for (my_it = dummy_width.begin(); my_it != dummy_width.end(); ++my_it)
  75. {
  76. if (*my_it > w_max)
  77. w_max = *my_it;
  78. }
  79. return w_max;
  80. }
  81. /////////////////////////////////////////////////////////////////////////
  82. // Function for finding a good starting node for Sloan algorithm
  83. //
  84. // This is to find a good starting node. "good" is in the sense
  85. // of the ordering generated.
  86. /////////////////////////////////////////////////////////////////////////
  87. template < class Graph, class ColorMap, class DegreeMap >
  88. typename graph_traits< Graph >::vertex_descriptor sloan_start_end_vertices(
  89. Graph& G, typename graph_traits< Graph >::vertex_descriptor& s,
  90. ColorMap color, DegreeMap degree)
  91. {
  92. typedef typename property_traits< DegreeMap >::value_type Degree;
  93. typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
  94. typedef typename std::vector<
  95. typename graph_traits< Graph >::vertices_size_type >::iterator vec_iter;
  96. typedef typename graph_traits< Graph >::vertices_size_type size_type;
  97. typedef typename property_map< Graph, vertex_index_t >::const_type VertexID;
  98. s = *(vertices(G).first);
  99. Vertex e = s;
  100. Vertex i;
  101. Degree my_degree = get(degree, s);
  102. Degree dummy, h_i, h_s, w_i, w_e;
  103. bool new_start = true;
  104. Degree maximum_degree = 0;
  105. // Creating a std-vector for storing the distance from the start vertex in
  106. // dist
  107. std::vector< typename graph_traits< Graph >::vertices_size_type > dist(
  108. num_vertices(G), 0);
  109. // Wrap a property_map_iterator around the std::iterator
  110. boost::iterator_property_map< vec_iter, VertexID, size_type, size_type& >
  111. dist_pmap(dist.begin(), get(vertex_index, G));
  112. // Creating a property_map for the indices of a vertex
  113. typename property_map< Graph, vertex_index_t >::type index_map
  114. = get(vertex_index, G);
  115. // Creating a priority queue
  116. typedef indirect_cmp< DegreeMap, std::greater< Degree > > Compare;
  117. Compare comp(degree);
  118. std::priority_queue< Vertex, std::vector< Vertex >, Compare > degree_queue(
  119. comp);
  120. // step 1
  121. // Scan for the vertex with the smallest degree and the maximum degree
  122. typename graph_traits< Graph >::vertex_iterator ui, ui_end;
  123. for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
  124. {
  125. dummy = get(degree, *ui);
  126. if (dummy < my_degree)
  127. {
  128. my_degree = dummy;
  129. s = *ui;
  130. }
  131. if (dummy > maximum_degree)
  132. {
  133. maximum_degree = dummy;
  134. }
  135. }
  136. // end 1
  137. do
  138. {
  139. new_start = false; // Setting the loop repetition status to false
  140. // step 2
  141. // initialize the the disance std-vector with 0
  142. for (typename std::vector< typename graph_traits<
  143. Graph >::vertices_size_type >::iterator iter
  144. = dist.begin();
  145. iter != dist.end(); ++iter)
  146. *iter = 0;
  147. // generating the RLS (rooted level structure)
  148. breadth_first_search(G, s,
  149. visitor(
  150. make_bfs_visitor(record_distances(dist_pmap, on_tree_edge()))));
  151. // end 2
  152. // step 3
  153. // calculating the depth of the RLS
  154. h_s = RLS_depth(dist);
  155. // step 4
  156. // pushing one node of each degree in an ascending manner into
  157. // degree_queue
  158. std::vector< bool > shrink_trace(maximum_degree, false);
  159. for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
  160. {
  161. dummy = get(degree, *ui);
  162. if ((dist[index_map[*ui]] == h_s) && (!shrink_trace[dummy]))
  163. {
  164. degree_queue.push(*ui);
  165. shrink_trace[dummy] = true;
  166. }
  167. }
  168. // end 3 & 4
  169. // step 5
  170. // Initializing w
  171. w_e = (std::numeric_limits< Degree >::max)();
  172. // end 5
  173. // step 6
  174. // Testing for termination
  175. while (!degree_queue.empty())
  176. {
  177. i = degree_queue.top(); // getting the node with the lowest degree
  178. // from the degree queue
  179. degree_queue.pop(); // ereasing the node with the lowest degree from
  180. // the degree queue
  181. // generating a RLS
  182. for (typename std::vector< typename graph_traits<
  183. Graph >::vertices_size_type >::iterator iter
  184. = dist.begin();
  185. iter != dist.end(); ++iter)
  186. *iter = 0;
  187. breadth_first_search(G, i,
  188. boost::visitor(make_bfs_visitor(
  189. record_distances(dist_pmap, on_tree_edge()))));
  190. // Calculating depth and width of the rooted level
  191. h_i = RLS_depth(dist);
  192. w_i = RLS_max_width(dist, h_i);
  193. // Testing for termination
  194. if ((h_i > h_s) && (w_i < w_e))
  195. {
  196. h_s = h_i;
  197. s = i;
  198. while (!degree_queue.empty())
  199. degree_queue.pop();
  200. new_start = true;
  201. }
  202. else if (w_i < w_e)
  203. {
  204. w_e = w_i;
  205. e = i;
  206. }
  207. }
  208. // end 6
  209. } while (new_start);
  210. return e;
  211. }
  212. //////////////////////////////////////////////////////////////////////////
  213. // Sloan algorithm with a given starting Vertex.
  214. //
  215. // This algorithm requires user to provide a starting vertex to
  216. // compute Sloan ordering.
  217. //////////////////////////////////////////////////////////////////////////
  218. template < class Graph, class OutputIterator, class ColorMap, class DegreeMap,
  219. class PriorityMap, class Weight >
  220. OutputIterator sloan_ordering(Graph& g,
  221. typename graph_traits< Graph >::vertex_descriptor s,
  222. typename graph_traits< Graph >::vertex_descriptor e,
  223. OutputIterator permutation, ColorMap color, DegreeMap degree,
  224. PriorityMap priority, Weight W1, Weight W2)
  225. {
  226. // typedef typename property_traits<DegreeMap>::value_type Degree;
  227. typedef typename property_traits< PriorityMap >::value_type Degree;
  228. typedef typename property_traits< ColorMap >::value_type ColorValue;
  229. typedef color_traits< ColorValue > Color;
  230. typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
  231. typedef typename std::vector<
  232. typename graph_traits< Graph >::vertices_size_type >::iterator vec_iter;
  233. typedef typename graph_traits< Graph >::vertices_size_type size_type;
  234. typedef typename property_map< Graph, vertex_index_t >::const_type VertexID;
  235. // Creating a std-vector for storing the distance from the end vertex in it
  236. typename std::vector< typename graph_traits< Graph >::vertices_size_type >
  237. dist(num_vertices(g), 0);
  238. // Wrap a property_map_iterator around the std::iterator
  239. boost::iterator_property_map< vec_iter, VertexID, size_type, size_type& >
  240. dist_pmap(dist.begin(), get(vertex_index, g));
  241. breadth_first_search(g, e,
  242. visitor(make_bfs_visitor(record_distances(dist_pmap, on_tree_edge()))));
  243. // Creating a property_map for the indices of a vertex
  244. typename property_map< Graph, vertex_index_t >::type index_map
  245. = get(vertex_index, g);
  246. // Sets the color and priority to their initial status
  247. Degree cdeg;
  248. typename graph_traits< Graph >::vertex_iterator ui, ui_end;
  249. for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
  250. {
  251. put(color, *ui, Color::white());
  252. cdeg = get(degree, *ui) + 1;
  253. put(priority, *ui, W1 * dist[index_map[*ui]] - W2 * cdeg);
  254. }
  255. // Priority list
  256. typedef indirect_cmp< PriorityMap, std::greater< Degree > > Compare;
  257. Compare comp(priority);
  258. std::list< Vertex > priority_list;
  259. // Some more declarations
  260. typename graph_traits< Graph >::out_edge_iterator ei, ei_end, ei2, ei2_end;
  261. Vertex u, v, w;
  262. put(color, s,
  263. Color::green()); // Sets the color of the starting vertex to gray
  264. priority_list.push_front(s); // Puts s into the priority_list
  265. while (!priority_list.empty())
  266. {
  267. priority_list.sort(comp); // Orders the elements in the priority list in
  268. // an ascending manner
  269. u = priority_list
  270. .front(); // Accesses the last element in the priority list
  271. priority_list
  272. .pop_front(); // Removes the last element in the priority list
  273. if (get(color, u) == Color::green())
  274. {
  275. // for-loop over all out-edges of vertex u
  276. for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei)
  277. {
  278. v = target(*ei, g);
  279. put(priority, v, get(priority, v) + W2); // updates the priority
  280. if (get(color, v)
  281. == Color::white()) // test if the vertex is inactive
  282. {
  283. put(color, v,
  284. Color::green()); // giving the vertex a preactive status
  285. priority_list.push_front(
  286. v); // writing the vertex in the priority_queue
  287. }
  288. }
  289. }
  290. // Here starts step 8
  291. *permutation++
  292. = u; // Puts u to the first position in the permutation-vector
  293. put(color, u, Color::black()); // Gives u an inactive status
  294. // for loop over all the adjacent vertices of u
  295. for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei)
  296. {
  297. v = target(*ei, g);
  298. if (get(color, v) == Color::green())
  299. { // tests if the vertex is inactive
  300. put(color, v,
  301. Color::red()); // giving the vertex an active status
  302. put(priority, v, get(priority, v) + W2); // updates the priority
  303. // for loop over alll adjacent vertices of v
  304. for (boost::tie(ei2, ei2_end) = out_edges(v, g); ei2 != ei2_end;
  305. ++ei2)
  306. {
  307. w = target(*ei2, g);
  308. if (get(color, w) != Color::black())
  309. { // tests if vertex is postactive
  310. put(priority, w,
  311. get(priority, w) + W2); // updates the priority
  312. if (get(color, w) == Color::white())
  313. {
  314. put(color, w, Color::green()); // gives the vertex a
  315. // preactive status
  316. priority_list.push_front(
  317. w); // puts the vertex into the priority queue
  318. } // end if
  319. } // end if
  320. } // end for
  321. } // end if
  322. } // end for
  323. } // end while
  324. return permutation;
  325. }
  326. /////////////////////////////////////////////////////////////////////////////////////////
  327. // Same algorithm as before, but without the weights given (taking default
  328. // weights
  329. template < class Graph, class OutputIterator, class ColorMap, class DegreeMap,
  330. class PriorityMap >
  331. OutputIterator sloan_ordering(Graph& g,
  332. typename graph_traits< Graph >::vertex_descriptor s,
  333. typename graph_traits< Graph >::vertex_descriptor e,
  334. OutputIterator permutation, ColorMap color, DegreeMap degree,
  335. PriorityMap priority)
  336. {
  337. return sloan_ordering(
  338. g, s, e, permutation, color, degree, priority, WEIGHT1, WEIGHT2);
  339. }
  340. //////////////////////////////////////////////////////////////////////////
  341. // Sloan algorithm without a given starting Vertex.
  342. //
  343. // This algorithm finds a good starting vertex itself to
  344. // compute Sloan-ordering.
  345. //////////////////////////////////////////////////////////////////////////
  346. template < class Graph, class OutputIterator, class Color, class Degree,
  347. class Priority, class Weight >
  348. inline OutputIterator sloan_ordering(Graph& G, OutputIterator permutation,
  349. Color color, Degree degree, Priority priority, Weight W1, Weight W2)
  350. {
  351. typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex;
  352. Vertex s, e;
  353. e = sloan_start_end_vertices(G, s, color, degree);
  354. return sloan_ordering(
  355. G, s, e, permutation, color, degree, priority, W1, W2);
  356. }
  357. /////////////////////////////////////////////////////////////////////////////////////////
  358. // Same as before, but without given weights (default weights are taken instead)
  359. template < class Graph, class OutputIterator, class Color, class Degree,
  360. class Priority >
  361. inline OutputIterator sloan_ordering(Graph& G, OutputIterator permutation,
  362. Color color, Degree degree, Priority priority)
  363. {
  364. return sloan_ordering(
  365. G, permutation, color, degree, priority, WEIGHT1, WEIGHT2);
  366. }
  367. } // namespace boost
  368. #endif // BOOST_GRAPH_SLOAN_HPP