core_numbers.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. //
  2. //=======================================================================
  3. // Copyright 2007 Stanford University
  4. // Authors: David Gleich
  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_CORE_NUMBERS_HPP
  12. #define BOOST_GRAPH_CORE_NUMBERS_HPP
  13. #include <boost/graph/detail/d_ary_heap.hpp>
  14. #include <boost/graph/breadth_first_search.hpp>
  15. #include <boost/iterator/reverse_iterator.hpp>
  16. #include <boost/concept/assert.hpp>
  17. /*
  18. * core_numbers
  19. *
  20. * Requirement: IncidenceGraph
  21. */
  22. // History
  23. //
  24. // 30 July 2007
  25. // Added visitors to the implementation
  26. //
  27. // 8 February 2008
  28. // Fixed headers and missing typename
  29. namespace boost
  30. {
  31. // A linear time O(m) algorithm to compute the indegree core number
  32. // of a graph for unweighted graphs.
  33. //
  34. // and a O((n+m) log n) algorithm to compute the in-edge-weight core
  35. // numbers of a weighted graph.
  36. //
  37. // The linear algorithm comes from:
  38. // Vladimir Batagelj and Matjaz Zaversnik, "An O(m) Algorithm for Cores
  39. // Decomposition of Networks." Sept. 1 2002.
  40. template < typename Visitor, typename Graph > struct CoreNumbersVisitorConcept
  41. {
  42. void constraints()
  43. {
  44. BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >));
  45. vis.examine_vertex(u, g);
  46. vis.finish_vertex(u, g);
  47. vis.examine_edge(e, g);
  48. }
  49. Visitor vis;
  50. Graph g;
  51. typename graph_traits< Graph >::vertex_descriptor u;
  52. typename graph_traits< Graph >::edge_descriptor e;
  53. };
  54. template < class Visitors = null_visitor >
  55. class core_numbers_visitor : public bfs_visitor< Visitors >
  56. {
  57. public:
  58. core_numbers_visitor() {}
  59. core_numbers_visitor(Visitors vis) : bfs_visitor< Visitors >(vis) {}
  60. private:
  61. template < class Vertex, class Graph >
  62. void initialize_vertex(Vertex, Graph&)
  63. {
  64. }
  65. template < class Vertex, class Graph > void discover_vertex(Vertex, Graph&)
  66. {
  67. }
  68. template < class Vertex, class Graph > void gray_target(Vertex, Graph&) {}
  69. template < class Vertex, class Graph > void black_target(Vertex, Graph&) {}
  70. template < class Edge, class Graph > void tree_edge(Edge, Graph&) {}
  71. template < class Edge, class Graph > void non_tree_edge(Edge, Graph&) {}
  72. };
  73. template < class Visitors >
  74. core_numbers_visitor< Visitors > make_core_numbers_visitor(Visitors vis)
  75. {
  76. return core_numbers_visitor< Visitors >(vis);
  77. }
  78. typedef core_numbers_visitor<> default_core_numbers_visitor;
  79. namespace detail
  80. {
  81. // implement a constant_property_map to simplify compute_in_degree
  82. // for the weighted and unweighted case
  83. // this is based on dummy property map
  84. template < typename ValueType >
  85. class constant_value_property_map
  86. : public boost::put_get_helper< ValueType,
  87. constant_value_property_map< ValueType > >
  88. {
  89. public:
  90. typedef void key_type;
  91. typedef ValueType value_type;
  92. typedef const ValueType& reference;
  93. typedef boost::readable_property_map_tag category;
  94. inline constant_value_property_map(ValueType cc) : c(cc) {}
  95. inline constant_value_property_map(
  96. const constant_value_property_map< ValueType >& x)
  97. : c(x.c)
  98. {
  99. }
  100. template < class Vertex > inline reference operator[](Vertex) const
  101. {
  102. return c;
  103. }
  104. protected:
  105. ValueType c;
  106. };
  107. // the core numbers start as the indegree or inweight. This function
  108. // will initialize these values
  109. template < typename Graph, typename CoreMap, typename EdgeWeightMap >
  110. void compute_in_degree_map(Graph& g, CoreMap d, EdgeWeightMap wm)
  111. {
  112. typename graph_traits< Graph >::vertex_iterator vi, vi_end;
  113. typename graph_traits< Graph >::out_edge_iterator ei, ei_end;
  114. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  115. {
  116. put(d, *vi, 0);
  117. }
  118. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  119. {
  120. for (boost::tie(ei, ei_end) = out_edges(*vi, g); ei != ei_end; ++ei)
  121. {
  122. put(d, target(*ei, g), get(d, target(*ei, g)) + get(wm, *ei));
  123. }
  124. }
  125. }
  126. // the version for weighted graphs is a little different
  127. template < typename Graph, typename CoreMap, typename EdgeWeightMap,
  128. typename MutableQueue, typename Visitor >
  129. typename property_traits< CoreMap >::value_type core_numbers_impl(
  130. Graph& g, CoreMap c, EdgeWeightMap wm, MutableQueue& Q, Visitor vis)
  131. {
  132. typename property_traits< CoreMap >::value_type v_cn = 0;
  133. typedef typename graph_traits< Graph >::vertex_descriptor vertex;
  134. while (!Q.empty())
  135. {
  136. // remove v from the Q, and then decrease the core numbers
  137. // of its successors
  138. vertex v = Q.top();
  139. vis.examine_vertex(v, g);
  140. Q.pop();
  141. v_cn = get(c, v);
  142. typename graph_traits< Graph >::out_edge_iterator oi, oi_end;
  143. for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi)
  144. {
  145. vis.examine_edge(*oi, g);
  146. vertex u = target(*oi, g);
  147. // if c[u] > c[v], then u is still in the graph,
  148. if (get(c, u) > v_cn)
  149. {
  150. // remove the edge
  151. put(c, u, get(c, u) - get(wm, *oi));
  152. if (Q.contains(u))
  153. Q.update(u);
  154. }
  155. }
  156. vis.finish_vertex(v, g);
  157. }
  158. return (v_cn);
  159. }
  160. template < typename Graph, typename CoreMap, typename EdgeWeightMap,
  161. typename IndexMap, typename CoreNumVisitor >
  162. typename property_traits< CoreMap >::value_type core_numbers_dispatch(
  163. Graph& g, CoreMap c, EdgeWeightMap wm, IndexMap im, CoreNumVisitor vis)
  164. {
  165. typedef typename property_traits< CoreMap >::value_type D;
  166. typedef std::less< D > Cmp;
  167. // build the mutable queue
  168. typedef typename graph_traits< Graph >::vertex_descriptor vertex;
  169. std::vector< std::size_t > index_in_heap_data(num_vertices(g));
  170. typedef iterator_property_map< std::vector< std::size_t >::iterator,
  171. IndexMap >
  172. index_in_heap_map_type;
  173. index_in_heap_map_type index_in_heap_map(
  174. index_in_heap_data.begin(), im);
  175. typedef d_ary_heap_indirect< vertex, 4, index_in_heap_map_type, CoreMap,
  176. Cmp >
  177. MutableQueue;
  178. MutableQueue Q(c, index_in_heap_map, Cmp());
  179. typename graph_traits< Graph >::vertex_iterator vi, vi_end;
  180. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  181. {
  182. Q.push(*vi);
  183. }
  184. return core_numbers_impl(g, c, wm, Q, vis);
  185. }
  186. // the version for the unweighted case
  187. // for this functions CoreMap must be initialized
  188. // with the in degree of each vertex
  189. template < typename Graph, typename CoreMap, typename PositionMap,
  190. typename Visitor >
  191. typename property_traits< CoreMap >::value_type core_numbers_impl(
  192. Graph& g, CoreMap c, PositionMap pos, Visitor vis)
  193. {
  194. typedef typename graph_traits< Graph >::vertices_size_type size_type;
  195. typedef typename graph_traits< Graph >::degree_size_type degree_type;
  196. typedef typename graph_traits< Graph >::vertex_descriptor vertex;
  197. typename graph_traits< Graph >::vertex_iterator vi, vi_end;
  198. // store the vertex core numbers
  199. typename property_traits< CoreMap >::value_type v_cn = 0;
  200. // compute the maximum degree (degrees are in the coremap)
  201. typename graph_traits< Graph >::degree_size_type max_deg = 0;
  202. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  203. {
  204. max_deg = (std::max<
  205. typename graph_traits< Graph >::degree_size_type >)(max_deg,
  206. get(c, *vi));
  207. }
  208. // store the vertices in bins by their degree
  209. // allocate two extra locations to ease boundary cases
  210. std::vector< size_type > bin(max_deg + 2);
  211. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  212. {
  213. ++bin[get(c, *vi)];
  214. }
  215. // this loop sets bin[d] to the starting position of vertices
  216. // with degree d in the vert array for the bucket sort
  217. size_type cur_pos = 0;
  218. for (degree_type cur_deg = 0; cur_deg < max_deg + 2; ++cur_deg)
  219. {
  220. degree_type tmp = bin[cur_deg];
  221. bin[cur_deg] = cur_pos;
  222. cur_pos += tmp;
  223. }
  224. // perform the bucket sort with pos and vert so that
  225. // pos[0] is the vertex of smallest degree
  226. std::vector< vertex > vert(num_vertices(g));
  227. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  228. {
  229. vertex v = *vi;
  230. size_type p = bin[get(c, v)];
  231. put(pos, v, p);
  232. vert[p] = v;
  233. ++bin[get(c, v)];
  234. }
  235. // we ``abused'' bin while placing the vertices, now,
  236. // we need to restore it
  237. std::copy(boost::make_reverse_iterator(bin.end() - 2),
  238. boost::make_reverse_iterator(bin.begin()),
  239. boost::make_reverse_iterator(bin.end() - 1));
  240. // now simulate removing the vertices
  241. for (size_type i = 0; i < num_vertices(g); ++i)
  242. {
  243. vertex v = vert[i];
  244. vis.examine_vertex(v, g);
  245. v_cn = get(c, v);
  246. typename graph_traits< Graph >::out_edge_iterator oi, oi_end;
  247. for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi)
  248. {
  249. vis.examine_edge(*oi, g);
  250. vertex u = target(*oi, g);
  251. // if c[u] > c[v], then u is still in the graph,
  252. if (get(c, u) > v_cn)
  253. {
  254. degree_type deg_u = get(c, u);
  255. degree_type pos_u = get(pos, u);
  256. // w is the first vertex with the same degree as u
  257. // (this is the resort operation!)
  258. degree_type pos_w = bin[deg_u];
  259. vertex w = vert[pos_w];
  260. if (u != v)
  261. {
  262. // swap u and w
  263. put(pos, u, pos_w);
  264. put(pos, w, pos_u);
  265. vert[pos_w] = u;
  266. vert[pos_u] = w;
  267. }
  268. // now, the vertices array is sorted assuming
  269. // we perform the following step
  270. // start the set of vertices with degree of u
  271. // one into the future (this now points at vertex
  272. // w which we swapped with u).
  273. ++bin[deg_u];
  274. // we are removing v from the graph, so u's degree
  275. // decreases
  276. put(c, u, get(c, u) - 1);
  277. }
  278. }
  279. vis.finish_vertex(v, g);
  280. }
  281. return v_cn;
  282. }
  283. } // namespace detail
  284. // non-named parameter version for the unweighted case
  285. template < typename Graph, typename CoreMap, typename CoreNumVisitor >
  286. typename property_traits< CoreMap >::value_type core_numbers(
  287. Graph& g, CoreMap c, CoreNumVisitor vis)
  288. {
  289. typedef typename graph_traits< Graph >::vertices_size_type size_type;
  290. detail::compute_in_degree_map(g, c,
  291. detail::constant_value_property_map<
  292. typename property_traits< CoreMap >::value_type >(1));
  293. return detail::core_numbers_impl(g, c,
  294. make_iterator_property_map(
  295. std::vector< size_type >(num_vertices(g)).begin(),
  296. get(vertex_index, g)),
  297. vis);
  298. }
  299. // non-named paramter version for the unweighted case
  300. template < typename Graph, typename CoreMap >
  301. typename property_traits< CoreMap >::value_type core_numbers(
  302. Graph& g, CoreMap c)
  303. {
  304. return core_numbers(g, c, make_core_numbers_visitor(null_visitor()));
  305. }
  306. // non-named parameter version for the weighted case
  307. template < typename Graph, typename CoreMap, typename EdgeWeightMap,
  308. typename VertexIndexMap, typename CoreNumVisitor >
  309. typename property_traits< CoreMap >::value_type core_numbers(Graph& g,
  310. CoreMap c, EdgeWeightMap wm, VertexIndexMap vim, CoreNumVisitor vis)
  311. {
  312. detail::compute_in_degree_map(g, c, wm);
  313. return detail::core_numbers_dispatch(g, c, wm, vim, vis);
  314. }
  315. // non-named parameter version for the weighted case
  316. // template <typename Graph, typename CoreMap, typename EdgeWeightMap>
  317. // typename property_traits<CoreMap>::value_type
  318. // core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm)
  319. // {
  320. // typedef typename graph_traits<Graph>::vertices_size_type size_type;
  321. // detail::compute_in_degree_map(g,c,wm);
  322. // return detail::core_numbers_dispatch(g,c,wm,get(vertex_index,g),
  323. // make_core_numbers_visitor(null_visitor()));
  324. // }
  325. template < typename Graph, typename CoreMap >
  326. typename property_traits< CoreMap >::value_type weighted_core_numbers(
  327. Graph& g, CoreMap c)
  328. {
  329. return weighted_core_numbers(
  330. g, c, make_core_numbers_visitor(null_visitor()));
  331. }
  332. template < typename Graph, typename CoreMap, typename CoreNumVisitor >
  333. typename property_traits< CoreMap >::value_type weighted_core_numbers(
  334. Graph& g, CoreMap c, CoreNumVisitor vis)
  335. {
  336. return core_numbers(g, c, get(edge_weight, g), get(vertex_index, g), vis);
  337. }
  338. } // namespace boost
  339. #endif // BOOST_GRAPH_CORE_NUMBERS_HPP