sloan_ordering.hpp 15 KB

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