/Src/Dependencies/Boost/boost/graph/sloan_ordering.hpp

http://hadesmem.googlecode.com/ · C++ Header · 447 lines · 269 code · 93 blank · 85 comment · 46 complexity · 4a32a6ac561563ec052b3b374b6ebab4 MD5 · raw file

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