/Src/Dependencies/Boost/boost/graph/distributed/betweenness_centrality.hpp

http://hadesmem.googlecode.com/ · C++ Header · 1725 lines · 1279 code · 277 blank · 169 comment · 135 complexity · 3c5cc5e53d9cdbd8c727a8a0edd8053e MD5 · raw file

Large files are truncated click here to view the full file

  1. // Copyright 2004 The Trustees of Indiana University.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP
  8. #define BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP
  9. #ifndef BOOST_GRAPH_USE_MPI
  10. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  11. #endif
  12. // #define COMPUTE_PATH_COUNTS_INLINE
  13. #include <boost/graph/betweenness_centrality.hpp>
  14. #include <boost/graph/overloading.hpp>
  15. #include <boost/graph/distributed/concepts.hpp>
  16. #include <boost/graph/graph_traits.hpp>
  17. #include <boost/config.hpp>
  18. #include <boost/assert.hpp>
  19. // For additive_reducer
  20. #include <boost/graph/distributed/distributed_graph_utility.hpp>
  21. #include <boost/type_traits/is_convertible.hpp>
  22. #include <boost/type_traits/is_same.hpp>
  23. #include <boost/property_map/property_map.hpp>
  24. #include <boost/graph/named_function_params.hpp>
  25. #include <boost/property_map/parallel/distributed_property_map.hpp>
  26. #include <boost/graph/distributed/detail/dijkstra_shortest_paths.hpp>
  27. #include <boost/tuple/tuple.hpp>
  28. // NGE - Needed for minstd_rand at L807, should pass vertex list
  29. // or generator instead
  30. #include <boost/random/linear_congruential.hpp>
  31. #include <algorithm>
  32. #include <stack>
  33. #include <vector>
  34. // Appending reducer
  35. template <typename T>
  36. struct append_reducer {
  37. BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
  38. template<typename K>
  39. T operator()(const K&) const { return T(); }
  40. template<typename K>
  41. T operator()(const K&, const T& x, const T& y) const
  42. {
  43. T z(x.begin(), x.end());
  44. for (typename T::const_iterator iter = y.begin(); iter != y.end(); ++iter)
  45. if (std::find(z.begin(), z.end(), *iter) == z.end())
  46. z.push_back(*iter);
  47. return z;
  48. }
  49. };
  50. namespace boost {
  51. namespace serialization {
  52. // TODO(nge): Write generalized serialization for tuples
  53. template<typename Archive, typename T1, typename T2, typename T3,
  54. typename T4>
  55. void serialize(Archive & ar,
  56. boost::tuple<T1,T2,T3, T4>& t,
  57. const unsigned int)
  58. {
  59. ar & boost::tuples::get<0>(t);
  60. ar & boost::tuples::get<1>(t);
  61. ar & boost::tuples::get<2>(t);
  62. ar & boost::tuples::get<3>(t);
  63. }
  64. } // serialization
  65. template <typename OwnerMap, typename Tuple>
  66. class get_owner_of_first_tuple_element {
  67. public:
  68. typedef typename property_traits<OwnerMap>::value_type owner_type;
  69. get_owner_of_first_tuple_element(OwnerMap owner) : owner(owner) { }
  70. owner_type get_owner(Tuple t) { return get(owner, boost::tuples::get<0>(t)); }
  71. private:
  72. OwnerMap owner;
  73. };
  74. template <typename OwnerMap, typename Tuple>
  75. typename get_owner_of_first_tuple_element<OwnerMap, Tuple>::owner_type
  76. get(get_owner_of_first_tuple_element<OwnerMap, Tuple> o, Tuple t)
  77. { return o.get_owner(t); }
  78. template <typename OwnerMap>
  79. class get_owner_of_first_pair_element {
  80. public:
  81. typedef typename property_traits<OwnerMap>::value_type owner_type;
  82. get_owner_of_first_pair_element(OwnerMap owner) : owner(owner) { }
  83. template <typename Vertex, typename T>
  84. owner_type get_owner(std::pair<Vertex, T> p) { return get(owner, p.first); }
  85. private:
  86. OwnerMap owner;
  87. };
  88. template <typename OwnerMap, typename Vertex, typename T>
  89. typename get_owner_of_first_pair_element<OwnerMap>::owner_type
  90. get(get_owner_of_first_pair_element<OwnerMap> o, std::pair<Vertex, T> p)
  91. { return o.get_owner(p); }
  92. namespace graph { namespace parallel { namespace detail {
  93. template<typename DistanceMap, typename IncomingMap>
  94. class betweenness_centrality_msg_value
  95. {
  96. typedef typename property_traits<DistanceMap>::value_type distance_type;
  97. typedef typename property_traits<IncomingMap>::value_type incoming_type;
  98. typedef typename incoming_type::value_type incoming_value_type;
  99. public:
  100. typedef std::pair<distance_type, incoming_value_type> type;
  101. static type create(distance_type dist, incoming_value_type source)
  102. { return std::make_pair(dist, source); }
  103. };
  104. /************************************************************************/
  105. /* Delta-stepping Betweenness Centrality */
  106. /************************************************************************/
  107. template<typename Graph, typename DistanceMap, typename IncomingMap,
  108. typename EdgeWeightMap, typename PathCountMap
  109. #ifdef COMPUTE_PATH_COUNTS_INLINE
  110. , typename IsSettledMap, typename VertexIndexMap
  111. #endif
  112. >
  113. class betweenness_centrality_delta_stepping_impl {
  114. // Could inherit from delta_stepping_impl to get run() method
  115. // but for the time being it's just reproduced here
  116. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  117. typedef typename graph_traits<Graph>::degree_size_type Degree;
  118. typedef typename property_traits<EdgeWeightMap>::value_type Dist;
  119. typedef typename property_traits<IncomingMap>::value_type IncomingType;
  120. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  121. ProcessGroup;
  122. typedef std::list<Vertex> Bucket;
  123. typedef typename Bucket::iterator BucketIterator;
  124. typedef typename std::vector<Bucket*>::size_type BucketIndex;
  125. typedef betweenness_centrality_msg_value<DistanceMap, IncomingMap>
  126. MessageValue;
  127. enum {
  128. // Relax a remote vertex. The message contains a pair<Vertex,
  129. // MessageValue>, the first part of which is the vertex whose
  130. // tentative distance is being relaxed and the second part
  131. // contains either the new distance (if there is no predecessor
  132. // map) or a pair with the distance and predecessor.
  133. msg_relax
  134. };
  135. public:
  136. // Must supply delta, ctor that guesses delta removed
  137. betweenness_centrality_delta_stepping_impl(const Graph& g,
  138. DistanceMap distance,
  139. IncomingMap incoming,
  140. EdgeWeightMap weight,
  141. PathCountMap path_count,
  142. #ifdef COMPUTE_PATH_COUNTS_INLINE
  143. IsSettledMap is_settled,
  144. VertexIndexMap vertex_index,
  145. #endif
  146. Dist delta);
  147. void run(Vertex s);
  148. private:
  149. // Relax the edge (u, v), creating a new best path of distance x.
  150. void relax(Vertex u, Vertex v, Dist x);
  151. // Synchronize all of the processes, by receiving all messages that
  152. // have not yet been received.
  153. void synchronize()
  154. {
  155. using boost::graph::parallel::synchronize;
  156. synchronize(pg);
  157. }
  158. // Setup triggers for msg_relax messages
  159. void setup_triggers()
  160. {
  161. using boost::graph::parallel::simple_trigger;
  162. simple_trigger(pg, msg_relax, this,
  163. &betweenness_centrality_delta_stepping_impl::handle_msg_relax);
  164. }
  165. void handle_msg_relax(int /*source*/, int /*tag*/,
  166. const std::pair<Vertex, typename MessageValue::type>& data,
  167. trigger_receive_context)
  168. { relax(data.second.second, data.first, data.second.first); }
  169. const Graph& g;
  170. IncomingMap incoming;
  171. DistanceMap distance;
  172. EdgeWeightMap weight;
  173. PathCountMap path_count;
  174. #ifdef COMPUTE_PATH_COUNTS_INLINE
  175. IsSettledMap is_settled;
  176. VertexIndexMap vertex_index;
  177. #endif
  178. Dist delta;
  179. ProcessGroup pg;
  180. typename property_map<Graph, vertex_owner_t>::const_type owner;
  181. typename property_map<Graph, vertex_local_t>::const_type local;
  182. // A "property map" that contains the position of each vertex in
  183. // whatever bucket it resides in.
  184. std::vector<BucketIterator> position_in_bucket;
  185. // Bucket data structure. The ith bucket contains all local vertices
  186. // with (tentative) distance in the range [i*delta,
  187. // (i+1)*delta).
  188. std::vector<Bucket*> buckets;
  189. // This "dummy" list is used only so that we can initialize the
  190. // position_in_bucket property map with non-singular iterators. This
  191. // won't matter for most implementations of the C++ Standard
  192. // Library, but it avoids undefined behavior and allows us to run
  193. // with library "debug modes".
  194. std::list<Vertex> dummy_list;
  195. // A "property map" that states which vertices have been deleted
  196. // from the bucket in this iteration.
  197. std::vector<bool> vertex_was_deleted;
  198. };
  199. template<typename Graph, typename DistanceMap, typename IncomingMap,
  200. typename EdgeWeightMap, typename PathCountMap
  201. #ifdef COMPUTE_PATH_COUNTS_INLINE
  202. , typename IsSettledMap, typename VertexIndexMap
  203. #endif
  204. >
  205. betweenness_centrality_delta_stepping_impl<
  206. Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
  207. #ifdef COMPUTE_PATH_COUNTS_INLINE
  208. , IsSettledMap, VertexIndexMap
  209. #endif
  210. >::
  211. betweenness_centrality_delta_stepping_impl(const Graph& g,
  212. DistanceMap distance,
  213. IncomingMap incoming,
  214. EdgeWeightMap weight,
  215. PathCountMap path_count,
  216. #ifdef COMPUTE_PATH_COUNTS_INLINE
  217. IsSettledMap is_settled,
  218. VertexIndexMap vertex_index,
  219. #endif
  220. Dist delta)
  221. : g(g),
  222. incoming(incoming),
  223. distance(distance),
  224. weight(weight),
  225. path_count(path_count),
  226. #ifdef COMPUTE_PATH_COUNTS_INLINE
  227. is_settled(is_settled),
  228. vertex_index(vertex_index),
  229. #endif
  230. delta(delta),
  231. pg(boost::graph::parallel::process_group_adl(g), attach_distributed_object()),
  232. owner(get(vertex_owner, g)),
  233. local(get(vertex_local, g))
  234. { setup_triggers(); }
  235. template<typename Graph, typename DistanceMap, typename IncomingMap,
  236. typename EdgeWeightMap, typename PathCountMap
  237. #ifdef COMPUTE_PATH_COUNTS_INLINE
  238. , typename IsSettledMap, typename VertexIndexMap
  239. #endif
  240. >
  241. void
  242. betweenness_centrality_delta_stepping_impl<
  243. Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
  244. #ifdef COMPUTE_PATH_COUNTS_INLINE
  245. , IsSettledMap, VertexIndexMap
  246. #endif
  247. >::
  248. run(Vertex s)
  249. {
  250. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  251. process_group_type;
  252. typename process_group_type::process_id_type id = process_id(pg);
  253. Dist inf = (std::numeric_limits<Dist>::max)();
  254. // None of the vertices are stored in the bucket.
  255. position_in_bucket.clear();
  256. position_in_bucket.resize(num_vertices(g), dummy_list.end());
  257. // None of the vertices have been deleted
  258. vertex_was_deleted.clear();
  259. vertex_was_deleted.resize(num_vertices(g), false);
  260. // No path from s to any other vertex, yet
  261. BGL_FORALL_VERTICES_T(v, g, Graph)
  262. put(distance, v, inf);
  263. // The distance to the starting node is zero
  264. if (get(owner, s) == id)
  265. // Put "s" into its bucket (bucket 0)
  266. relax(s, s, 0);
  267. else
  268. // Note that we know the distance to s is zero
  269. cache(distance, s, 0);
  270. #ifdef COMPUTE_PATH_COUNTS_INLINE
  271. // Synchronize here to deliver initial relaxation since we don't
  272. // synchronize at the beginning of the inner loop any more
  273. synchronize();
  274. // Incoming edge count map is an implementation detail and should
  275. // be freed as soon as possible so build it here
  276. typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
  277. std::vector<edges_size_type> incoming_edge_countS(num_vertices(g));
  278. iterator_property_map<typename std::vector<edges_size_type>::iterator, VertexIndexMap>
  279. incoming_edge_count(incoming_edge_countS.begin(), vertex_index);
  280. #endif
  281. BucketIndex max_bucket = (std::numeric_limits<BucketIndex>::max)();
  282. BucketIndex current_bucket = 0;
  283. do {
  284. #ifdef COMPUTE_PATH_COUNTS_INLINE
  285. // We need to clear the outgoing map after every bucket so just build it here
  286. std::vector<IncomingType> outgoingS(num_vertices(g));
  287. IncomingMap outgoing(outgoingS.begin(), vertex_index);
  288. outgoing.set_reduce(append_reducer<IncomingType>());
  289. #else
  290. // Synchronize with all of the other processes.
  291. synchronize();
  292. #endif
  293. // Find the next bucket that has something in it.
  294. while (current_bucket < buckets.size()
  295. && (!buckets[current_bucket] || buckets[current_bucket]->empty()))
  296. ++current_bucket;
  297. if (current_bucket >= buckets.size())
  298. current_bucket = max_bucket;
  299. // Find the smallest bucket (over all processes) that has vertices
  300. // that need to be processed.
  301. using boost::parallel::all_reduce;
  302. using boost::parallel::minimum;
  303. current_bucket = all_reduce(pg, current_bucket, minimum<BucketIndex>());
  304. if (current_bucket == max_bucket)
  305. // There are no non-empty buckets in any process; exit.
  306. break;
  307. // Contains the set of vertices that have been deleted in the
  308. // relaxation of "light" edges. Note that we keep track of which
  309. // vertices were deleted with the property map
  310. // "vertex_was_deleted".
  311. std::vector<Vertex> deleted_vertices;
  312. // Repeatedly relax light edges
  313. bool nonempty_bucket;
  314. do {
  315. // Someone has work to do in this bucket.
  316. if (current_bucket < buckets.size() && buckets[current_bucket]) {
  317. Bucket& bucket = *buckets[current_bucket];
  318. // For each element in the bucket
  319. while (!bucket.empty()) {
  320. Vertex u = bucket.front();
  321. // Remove u from the front of the bucket
  322. bucket.pop_front();
  323. // Insert u into the set of deleted vertices, if it hasn't
  324. // been done already.
  325. if (!vertex_was_deleted[get(local, u)]) {
  326. vertex_was_deleted[get(local, u)] = true;
  327. deleted_vertices.push_back(u);
  328. }
  329. // Relax each light edge.
  330. Dist u_dist = get(distance, u);
  331. BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
  332. if (get(weight, e) <= delta) // light edge
  333. relax(u, target(e, g), u_dist + get(weight, e));
  334. }
  335. }
  336. // Synchronize with all of the other processes.
  337. synchronize();
  338. // Is the bucket empty now?
  339. nonempty_bucket = (current_bucket < buckets.size()
  340. && buckets[current_bucket]
  341. && !buckets[current_bucket]->empty());
  342. } while (all_reduce(pg, nonempty_bucket, std::logical_or<bool>()));
  343. // Relax heavy edges for each of the vertices that we previously
  344. // deleted.
  345. for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
  346. iter != deleted_vertices.end(); ++iter) {
  347. // Relax each heavy edge.
  348. Vertex u = *iter;
  349. Dist u_dist = get(distance, u);
  350. BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
  351. if (get(weight, e) > delta) // heavy edge
  352. relax(u, target(e, g), u_dist + get(weight, e));
  353. #ifdef COMPUTE_PATH_COUNTS_INLINE
  354. // Set outgoing paths
  355. IncomingType in = get(incoming, u);
  356. for (typename IncomingType::iterator pred = in.begin(); pred != in.end(); ++pred)
  357. if (get(owner, *pred) == id) {
  358. IncomingType x = get(outgoing, *pred);
  359. if (std::find(x.begin(), x.end(), u) == x.end())
  360. x.push_back(u);
  361. put(outgoing, *pred, x);
  362. } else {
  363. IncomingType in;
  364. in.push_back(u);
  365. put(outgoing, *pred, in);
  366. }
  367. // Set incoming edge counts
  368. put(incoming_edge_count, u, in.size());
  369. #endif
  370. }
  371. #ifdef COMPUTE_PATH_COUNTS_INLINE
  372. synchronize(); // Deliver heavy edge relaxations and outgoing paths
  373. // Build Queue
  374. typedef typename property_traits<PathCountMap>::value_type PathCountType;
  375. typedef std::pair<Vertex, PathCountType> queue_value_type;
  376. typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
  377. typedef typename get_owner_of_first_pair_element<OwnerMap> IndirectOwnerMap;
  378. typedef boost::queue<queue_value_type> local_queue_type;
  379. typedef boost::graph::distributed::distributed_queue<process_group_type,
  380. IndirectOwnerMap,
  381. local_queue_type> dist_queue_type;
  382. IndirectOwnerMap indirect_owner(owner);
  383. dist_queue_type Q(pg, indirect_owner);
  384. // Find sources to initialize queue
  385. BGL_FORALL_VERTICES_T(v, g, Graph) {
  386. if (get(is_settled, v) && !(get(outgoing, v).empty())) {
  387. put(incoming_edge_count, v, 1);
  388. Q.push(std::make_pair(v, 0)); // Push this vertex with no additional path count
  389. }
  390. }
  391. // Set path counts for vertices in this bucket
  392. while (!Q.empty()) {
  393. queue_value_type t = Q.top(); Q.pop();
  394. Vertex v = t.first;
  395. PathCountType p = t.second;
  396. put(path_count, v, get(path_count, v) + p);
  397. put(incoming_edge_count, v, get(incoming_edge_count, v) - 1);
  398. if (get(incoming_edge_count, v) == 0) {
  399. IncomingType out = get(outgoing, v);
  400. for (typename IncomingType::iterator iter = out.begin(); iter != out.end(); ++iter)
  401. Q.push(std::make_pair(*iter, get(path_count, v)));
  402. }
  403. }
  404. // Mark the vertices in this bucket settled
  405. for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
  406. iter != deleted_vertices.end(); ++iter)
  407. put(is_settled, *iter, true);
  408. // No need to clear path count map as it is never read/written remotely
  409. // No need to clear outgoing map as it is re-alloced every bucket
  410. #endif
  411. // Go to the next bucket: the current bucket must already be empty.
  412. ++current_bucket;
  413. } while (true);
  414. // Delete all of the buckets.
  415. for (typename std::vector<Bucket*>::iterator iter = buckets.begin();
  416. iter != buckets.end(); ++iter) {
  417. if (*iter) {
  418. delete *iter;
  419. *iter = 0;
  420. }
  421. }
  422. }
  423. template<typename Graph, typename DistanceMap, typename IncomingMap,
  424. typename EdgeWeightMap, typename PathCountMap
  425. #ifdef COMPUTE_PATH_COUNTS_INLINE
  426. , typename IsSettledMap, typename VertexIndexMap
  427. #endif
  428. >
  429. void
  430. betweenness_centrality_delta_stepping_impl<
  431. Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
  432. #ifdef COMPUTE_PATH_COUNTS_INLINE
  433. , IsSettledMap, VertexIndexMap
  434. #endif
  435. >::
  436. relax(Vertex u, Vertex v, Dist x)
  437. {
  438. if (x <= get(distance, v)) {
  439. // We're relaxing the edge to vertex v.
  440. if (get(owner, v) == process_id(pg)) {
  441. if (x < get(distance, v)) {
  442. // Compute the new bucket index for v
  443. BucketIndex new_index = static_cast<BucketIndex>(x / delta);
  444. // Make sure there is enough room in the buckets data structure.
  445. if (new_index >= buckets.size()) buckets.resize(new_index + 1, 0);
  446. // Make sure that we have allocated the bucket itself.
  447. if (!buckets[new_index]) buckets[new_index] = new Bucket;
  448. if (get(distance, v) != (std::numeric_limits<Dist>::max)()
  449. && !vertex_was_deleted[get(local, v)]) {
  450. // We're moving v from an old bucket into a new one. Compute
  451. // the old index, then splice it in.
  452. BucketIndex old_index
  453. = static_cast<BucketIndex>(get(distance, v) / delta);
  454. buckets[new_index]->splice(buckets[new_index]->end(),
  455. *buckets[old_index],
  456. position_in_bucket[get(local, v)]);
  457. } else {
  458. // We're inserting v into a bucket for the first time. Put it
  459. // at the end.
  460. buckets[new_index]->push_back(v);
  461. }
  462. // v is now at the last position in the new bucket
  463. position_in_bucket[get(local, v)] = buckets[new_index]->end();
  464. --position_in_bucket[get(local, v)];
  465. // Update tentative distance information and incoming, path_count
  466. if (u != v) put(incoming, v, IncomingType(1, u));
  467. put(distance, v, x);
  468. } // u != v covers initial source relaxation and self-loops
  469. else if (x == get(distance, v) && u != v) {
  470. // Add incoming edge if it's not already in the list
  471. IncomingType in = get(incoming, v);
  472. if (std::find(in.begin(), in.end(), u) == in.end()) {
  473. in.push_back(u);
  474. put(incoming, v, in);
  475. }
  476. }
  477. } else {
  478. // The vertex is remote: send a request to the vertex's owner
  479. send(pg, get(owner, v), msg_relax,
  480. std::make_pair(v, MessageValue::create(x, u)));
  481. // Cache tentative distance information
  482. cache(distance, v, x);
  483. }
  484. }
  485. }
  486. /************************************************************************/
  487. /* Shortest Paths function object for betweenness centrality */
  488. /************************************************************************/
  489. template<typename WeightMap>
  490. struct brandes_shortest_paths {
  491. typedef typename property_traits<WeightMap>::value_type weight_type;
  492. brandes_shortest_paths()
  493. : weight(1), delta(0) { }
  494. brandes_shortest_paths(weight_type delta)
  495. : weight(1), delta(delta) { }
  496. brandes_shortest_paths(WeightMap w)
  497. : weight(w), delta(0) { }
  498. brandes_shortest_paths(WeightMap w, weight_type delta)
  499. : weight(w), delta(delta) { }
  500. template<typename Graph, typename IncomingMap, typename DistanceMap,
  501. typename PathCountMap
  502. #ifdef COMPUTE_PATH_COUNTS_INLINE
  503. , typename IsSettledMap, typename VertexIndexMap
  504. #endif
  505. >
  506. void
  507. operator()(Graph& g,
  508. typename graph_traits<Graph>::vertex_descriptor s,
  509. IncomingMap incoming,
  510. DistanceMap distance,
  511. PathCountMap path_count
  512. #ifdef COMPUTE_PATH_COUNTS_INLINE
  513. , IsSettledMap is_settled,
  514. VertexIndexMap vertex_index
  515. #endif
  516. )
  517. {
  518. typedef typename property_traits<DistanceMap>::value_type
  519. distance_type;
  520. typedef std::plus<distance_type> Combine;
  521. typedef std::less<distance_type> Compare;
  522. // The "distance" map needs to act like one, retrieving the default
  523. // value of infinity.
  524. set_property_map_role(vertex_distance, distance);
  525. // Only calculate delta the first time operator() is called
  526. // This presumes g is the same every time, but so does the fact
  527. // that we're reusing the weight map
  528. if (delta == 0)
  529. set_delta(g);
  530. // TODO (NGE): Restructure the code so we don't have to construct
  531. // impl every time?
  532. betweenness_centrality_delta_stepping_impl<
  533. Graph, DistanceMap, IncomingMap, WeightMap, PathCountMap
  534. #ifdef COMPUTE_PATH_COUNTS_INLINE
  535. , IsSettledMap, VertexIndexMap
  536. #endif
  537. >
  538. impl(g, distance, incoming, weight, path_count,
  539. #ifdef COMPUTE_PATH_COUNTS_INLINE
  540. is_settled, vertex_index,
  541. #endif
  542. delta);
  543. impl.run(s);
  544. }
  545. private:
  546. template <typename Graph>
  547. void
  548. set_delta(const Graph& g)
  549. {
  550. using boost::parallel::all_reduce;
  551. using boost::parallel::maximum;
  552. using std::max;
  553. typedef typename graph_traits<Graph>::degree_size_type Degree;
  554. typedef weight_type Dist;
  555. // Compute the maximum edge weight and degree
  556. Dist max_edge_weight = 0;
  557. Degree max_degree = 0;
  558. BGL_FORALL_VERTICES_T(u, g, Graph) {
  559. max_degree = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_degree, out_degree(u, g));
  560. BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
  561. max_edge_weight = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_edge_weight, get(weight, e));
  562. }
  563. max_edge_weight = all_reduce(process_group(g), max_edge_weight, maximum<Dist>());
  564. max_degree = all_reduce(process_group(g), max_degree, maximum<Degree>());
  565. // Take a guess at delta, based on what works well for random
  566. // graphs.
  567. delta = max_edge_weight / max_degree;
  568. if (delta == 0)
  569. delta = 1;
  570. }
  571. WeightMap weight;
  572. weight_type delta;
  573. };
  574. // Perform a single SSSP from the specified vertex and update the centrality map(s)
  575. template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
  576. typename IncomingMap, typename DistanceMap, typename DependencyMap,
  577. typename PathCountMap,
  578. #ifdef COMPUTE_PATH_COUNTS_INLINE
  579. typename IsSettledMap,
  580. #endif
  581. typename VertexIndexMap, typename ShortestPaths>
  582. void
  583. do_brandes_sssp(const Graph& g,
  584. CentralityMap centrality,
  585. EdgeCentralityMap edge_centrality_map,
  586. IncomingMap incoming,
  587. DistanceMap distance,
  588. DependencyMap dependency,
  589. PathCountMap path_count,
  590. #ifdef COMPUTE_PATH_COUNTS_INLINE
  591. IsSettledMap is_settled,
  592. #endif
  593. VertexIndexMap vertex_index,
  594. ShortestPaths shortest_paths,
  595. typename graph_traits<Graph>::vertex_descriptor s)
  596. {
  597. using boost::detail::graph::update_centrality;
  598. using boost::graph::parallel::process_group;
  599. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  600. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
  601. typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
  602. typedef typename property_traits<IncomingMap>::value_type incoming_type;
  603. typedef typename property_traits<DistanceMap>::value_type distance_type;
  604. typedef typename property_traits<DependencyMap>::value_type dependency_type;
  605. typedef typename property_traits<PathCountMap>::value_type path_count_type;
  606. typedef typename incoming_type::iterator incoming_iterator;
  607. typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
  608. OwnerMap owner = get(vertex_owner, g);
  609. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  610. process_group_type;
  611. process_group_type pg = process_group(g);
  612. typename process_group_type::process_id_type id = process_id(pg);
  613. // TODO: Is it faster not to clear some of these maps?
  614. // Initialize for this iteration
  615. distance.clear();
  616. incoming.clear();
  617. path_count.clear();
  618. dependency.clear();
  619. BGL_FORALL_VERTICES_T(v, g, Graph) {
  620. put(path_count, v, 0);
  621. put(dependency, v, 0);
  622. }
  623. if (get(owner, s) == id) {
  624. put(incoming, s, incoming_type());
  625. #ifdef COMPUTE_PATH_COUNTS_INLINE
  626. put(path_count, s, 1);
  627. put(is_settled, s, true);
  628. #endif
  629. }
  630. // Execute the shortest paths algorithm. This will be either
  631. // a weighted or unweighted customized breadth-first search,
  632. shortest_paths(g, s, incoming, distance, path_count
  633. #ifdef COMPUTE_PATH_COUNTS_INLINE
  634. , is_settled, vertex_index
  635. #endif
  636. );
  637. #ifndef COMPUTE_PATH_COUNTS_INLINE
  638. //
  639. // TODO: Optimize case where source has no out-edges
  640. //
  641. // Count of incoming edges to tell when all incoming edges have been relaxed in
  642. // the induced shortest paths DAG
  643. std::vector<edges_size_type> incoming_edge_countS(num_vertices(g));
  644. iterator_property_map<typename std::vector<edges_size_type>::iterator, VertexIndexMap>
  645. incoming_edge_count(incoming_edge_countS.begin(), vertex_index);
  646. BGL_FORALL_VERTICES_T(v, g, Graph) {
  647. put(incoming_edge_count, v, get(incoming, v).size());
  648. }
  649. if (get(owner, s) == id) {
  650. put(incoming_edge_count, s, 1);
  651. put(incoming, s, incoming_type());
  652. }
  653. std::vector<incoming_type> outgoingS(num_vertices(g));
  654. iterator_property_map<typename std::vector<incoming_type>::iterator, VertexIndexMap>
  655. outgoing(outgoingS.begin(), vertex_index);
  656. outgoing.set_reduce(append_reducer<incoming_type>());
  657. // Mark forward adjacencies in DAG of shortest paths
  658. // TODO: It's possible to do this using edge flags but it's not currently done this way
  659. // because during traversal of the DAG we would have to examine all out edges
  660. // which would lead to more memory accesses and a larger cache footprint.
  661. //
  662. // In the bidirectional graph case edge flags would be an excellent way of marking
  663. // edges in the DAG of shortest paths
  664. BGL_FORALL_VERTICES_T(v, g, Graph) {
  665. incoming_type i = get(incoming, v);
  666. for (typename incoming_type::iterator iter = i.begin(); iter != i.end(); ++iter) {
  667. if (get(owner, *iter) == id) {
  668. incoming_type x = get(outgoing, *iter);
  669. if (std::find(x.begin(), x.end(), v) == x.end())
  670. x.push_back(v);
  671. put(outgoing, *iter, x);
  672. } else {
  673. incoming_type in;
  674. in.push_back(v);
  675. put(outgoing, *iter, in);
  676. }
  677. }
  678. }
  679. synchronize(pg);
  680. // Traverse DAG induced by forward edges in dependency order and compute path counts
  681. {
  682. typedef std::pair<vertex_descriptor, path_count_type> queue_value_type;
  683. typedef get_owner_of_first_pair_element<OwnerMap> IndirectOwnerMap;
  684. typedef boost::queue<queue_value_type> local_queue_type;
  685. typedef boost::graph::distributed::distributed_queue<process_group_type,
  686. IndirectOwnerMap,
  687. local_queue_type> dist_queue_type;
  688. IndirectOwnerMap indirect_owner(owner);
  689. dist_queue_type Q(pg, indirect_owner);
  690. if (get(owner, s) == id)
  691. Q.push(std::make_pair(s, 1));
  692. while (!Q.empty()) {
  693. queue_value_type t = Q.top(); Q.pop();
  694. vertex_descriptor v = t.first;
  695. path_count_type p = t.second;
  696. put(path_count, v, get(path_count, v) + p);
  697. put(incoming_edge_count, v, get(incoming_edge_count, v) - 1);
  698. if (get(incoming_edge_count, v) == 0) {
  699. incoming_type out = get(outgoing, v);
  700. for (typename incoming_type::iterator iter = out.begin(); iter != out.end(); ++iter)
  701. Q.push(std::make_pair(*iter, get(path_count, v)));
  702. }
  703. }
  704. }
  705. #endif // COMPUTE_PATH_COUNTS_INLINE
  706. //
  707. // Compute dependencies
  708. //
  709. // Build the distributed_queue
  710. // Value type consists of 1) target of update 2) source of update
  711. // 3) dependency of source 4) path count of source
  712. typedef boost::tuple<vertex_descriptor, vertex_descriptor, dependency_type, path_count_type>
  713. queue_value_type;
  714. typedef get_owner_of_first_tuple_element<OwnerMap, queue_value_type> IndirectOwnerMap;
  715. typedef boost::queue<queue_value_type> local_queue_type;
  716. typedef boost::graph::distributed::distributed_queue<process_group_type,
  717. IndirectOwnerMap,
  718. local_queue_type> dist_queue_type;
  719. IndirectOwnerMap indirect_owner(owner);
  720. dist_queue_type Q(pg, indirect_owner);
  721. // Calculate number of vertices each vertex depends on, when a vertex has been pushed
  722. // that number of times then we will update it
  723. // AND Request path counts of sources of incoming edges
  724. std::vector<dependency_type> dependency_countS(num_vertices(g), 0);
  725. iterator_property_map<typename std::vector<dependency_type>::iterator, VertexIndexMap>
  726. dependency_count(dependency_countS.begin(), vertex_index);
  727. dependency_count.set_reduce(boost::graph::distributed::additive_reducer<dependency_type>());
  728. path_count.set_max_ghost_cells(0);
  729. BGL_FORALL_VERTICES_T(v, g, Graph) {
  730. if (get(distance, v) < (std::numeric_limits<distance_type>::max)()) {
  731. incoming_type el = get(incoming, v);
  732. for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw) {
  733. if (get(owner, *vw) == id)
  734. put(dependency_count, *vw, get(dependency_count, *vw) + 1);
  735. else {
  736. put(dependency_count, *vw, 1);
  737. // Request path counts
  738. get(path_count, *vw);
  739. }
  740. // request() doesn't work here, perhaps because we don't have a copy of this
  741. // ghost cell already?
  742. }
  743. }
  744. }
  745. synchronize(pg);
  746. // Push vertices with non-zero distance/path count and zero dependency count
  747. BGL_FORALL_VERTICES_T(v, g, Graph) {
  748. if (get(distance, v) < (std::numeric_limits<distance_type>::max)()
  749. && get(dependency_count, v) == 0)
  750. Q.push(boost::make_tuple(v, v, get(dependency, v), get(path_count, v)));
  751. }
  752. dependency.set_max_ghost_cells(0);
  753. while(!Q.empty()) {
  754. queue_value_type x = Q.top(); Q.pop();
  755. vertex_descriptor w = boost::tuples::get<0>(x);
  756. vertex_descriptor source = boost::tuples::get<1>(x);
  757. dependency_type dep = boost::tuples::get<2>(x);
  758. path_count_type pc = boost::tuples::get<3>(x);
  759. cache(dependency, source, dep);
  760. cache(path_count, source, pc);
  761. if (get(dependency_count, w) != 0)
  762. put(dependency_count, w, get(dependency_count, w) - 1);
  763. if (get(dependency_count, w) == 0) {
  764. // Update dependency and centrality of sources of incoming edges
  765. incoming_type el = get(incoming, w);
  766. for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw) {
  767. vertex_descriptor v = *vw;
  768. BOOST_ASSERT(get(path_count, w) != 0);
  769. dependency_type factor = dependency_type(get(path_count, v))
  770. / dependency_type(get(path_count, w));
  771. factor *= (dependency_type(1) + get(dependency, w));
  772. if (get(owner, v) == id)
  773. put(dependency, v, get(dependency, v) + factor);
  774. else
  775. put(dependency, v, factor);
  776. update_centrality(edge_centrality_map, v, factor);
  777. }
  778. if (w != s)
  779. update_centrality(centrality, w, get(dependency, w));
  780. // Push sources of edges in incoming edge list
  781. for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw)
  782. Q.push(boost::make_tuple(*vw, w, get(dependency, w), get(path_count, w)));
  783. }
  784. }
  785. }
  786. template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
  787. typename IncomingMap, typename DistanceMap, typename DependencyMap,
  788. typename PathCountMap, typename VertexIndexMap, typename ShortestPaths,
  789. typename Buffer>
  790. void
  791. brandes_betweenness_centrality_impl(const Graph& g,
  792. CentralityMap centrality,
  793. EdgeCentralityMap edge_centrality_map,
  794. IncomingMap incoming,
  795. DistanceMap distance,
  796. DependencyMap dependency,
  797. PathCountMap path_count,
  798. VertexIndexMap vertex_index,
  799. ShortestPaths shortest_paths,
  800. Buffer sources)
  801. {
  802. using boost::detail::graph::init_centrality_map;
  803. using boost::detail::graph::divide_centrality_by_two;
  804. using boost::graph::parallel::process_group;
  805. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
  806. typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
  807. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  808. typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
  809. typedef typename property_traits<DistanceMap>::value_type distance_type;
  810. typedef typename property_traits<DependencyMap>::value_type dependency_type;
  811. // Initialize centrality
  812. init_centrality_map(vertices(g), centrality);
  813. init_centrality_map(edges(g), edge_centrality_map);
  814. // Set the reduction operation on the dependency map to be addition
  815. dependency.set_reduce(boost::graph::distributed::additive_reducer<dependency_type>());
  816. distance.set_reduce(boost::graph::distributed::choose_min_reducer<distance_type>());
  817. // Don't allow remote procs to write incoming or path_count maps
  818. // updating them is handled inside the betweenness_centrality_queue
  819. incoming.set_consistency_model(0);
  820. path_count.set_consistency_model(0);
  821. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  822. process_group_type;
  823. process_group_type pg = process_group(g);
  824. #ifdef COMPUTE_PATH_COUNTS_INLINE
  825. // Build is_settled maps
  826. std::vector<bool> is_settledS(num_vertices(g));
  827. typedef iterator_property_map<std::vector<bool>::iterator, VertexIndexMap>
  828. IsSettledMap;
  829. IsSettledMap is_settled(is_settledS.begin(), vertex_index);
  830. #endif
  831. if (!sources.empty()) {
  832. // DO SSSPs
  833. while (!sources.empty()) {
  834. do_brandes_sssp(g, centrality, edge_centrality_map, incoming, distance,
  835. dependency, path_count,
  836. #ifdef COMPUTE_PATH_COUNTS_INLINE
  837. is_settled,
  838. #endif
  839. vertex_index, shortest_paths, sources.top());
  840. sources.pop();
  841. }
  842. } else { // Exact Betweenness Centrality
  843. typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
  844. vertices_size_type n = num_vertices(g);
  845. n = boost::parallel::all_reduce(pg, n, std::plus<vertices_size_type>());
  846. for (vertices_size_type i = 0; i < n; ++i) {
  847. vertex_descriptor v = vertex(i, g);
  848. do_brandes_sssp(g, centrality, edge_centrality_map, incoming, distance,
  849. dependency, path_count,
  850. #ifdef COMPUTE_PATH_COUNTS_INLINE
  851. is_settled,
  852. #endif
  853. vertex_index, shortest_paths, v);
  854. }
  855. }
  856. typedef typename graph_traits<Graph>::directed_category directed_category;
  857. const bool is_undirected =
  858. is_convertible<directed_category*, undirected_tag*>::value;
  859. if (is_undirected) {
  860. divide_centrality_by_two(vertices(g), centrality);
  861. divide_centrality_by_two(edges(g), edge_centrality_map);
  862. }
  863. }
  864. template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
  865. typename IncomingMap, typename DistanceMap, typename DependencyMap,
  866. typename PathCountMap, typename VertexIndexMap, typename ShortestPaths,
  867. typename Stack>
  868. void
  869. do_sequential_brandes_sssp(const Graph& g,
  870. CentralityMap centrality,
  871. EdgeCentralityMap edge_centrality_map,
  872. IncomingMap incoming,
  873. DistanceMap distance,
  874. DependencyMap dependency,
  875. PathCountMap path_count,
  876. VertexIndexMap vertex_index,
  877. ShortestPaths shortest_paths,
  878. Stack& ordered_vertices,
  879. typename graph_traits<Graph>::vertex_descriptor v)
  880. {
  881. using boost::detail::graph::update_centrality;
  882. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
  883. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  884. typedef typename property_traits<IncomingMap>::value_type incoming_type;
  885. // Initialize for this iteration
  886. BGL_FORALL_VERTICES_T(w, g, Graph) {
  887. // put(path_count, w, 0);
  888. incoming[w].clear();
  889. put(dependency, w, 0);
  890. }
  891. put(path_count, v, 1);
  892. incoming[v].clear();
  893. // Execute the shortest paths algorithm. This will be either
  894. // Dijkstra's algorithm or a customized breadth-first search,
  895. // depending on whether the graph is weighted or unweighted.
  896. shortest_paths(g, v, ordered_vertices, incoming, distance,
  897. path_count, vertex_index);
  898. while (!ordered_vertices.empty()) {
  899. vertex_descriptor w = ordered_vertices.top();
  900. ordered_vertices.pop();
  901. typedef typename property_traits<IncomingMap>::value_type
  902. incoming_type;
  903. typedef typename incoming_type::iterator incoming_iterator;
  904. typedef typename property_traits<DependencyMap>::value_type
  905. dependency_type;
  906. for (incoming_iterator vw = incoming[w].begin();
  907. vw != incoming[w].end(); ++vw) {
  908. vertex_descriptor v = source(*vw, g);
  909. dependency_type factor = dependency_type(get(path_count, v))
  910. / dependency_type(get(path_count, w));
  911. factor *= (dependency_type(1) + get(dependency, w));
  912. put(dependency, v, get(dependency, v) + factor);
  913. update_centrality(edge_centrality_map, *vw, factor);
  914. }
  915. if (w != v) {
  916. update_centrality(centrality, w, get(dependency, w));
  917. }
  918. }
  919. }
  920. // Betweenness Centrality variant that duplicates graph across processors
  921. // and parallizes SSSPs
  922. // This function expects a non-distributed graph and property-maps
  923. template<typename ProcessGroup, typename Graph,
  924. typename CentralityMap, typename EdgeCentralityMap,
  925. typename IncomingMap, typename DistanceMap,
  926. typename DependencyMap, typename PathCountMap,
  927. typename VertexIndexMap, typename ShortestPaths,
  928. typename Buffer>
  929. void
  930. non_distributed_brandes_betweenness_centrality_impl(const ProcessGroup& pg,
  931. const Graph& g,
  932. CentralityMap centrality,
  933. EdgeCentralityMap edge_centrality_map,
  934. IncomingMap incoming, // P
  935. DistanceMap distance, // d
  936. DependencyMap dependency, // delta
  937. PathCountMap path_count, // sigma
  938. VertexIndexMap vertex_index,
  939. ShortestPaths shortest_paths,
  940. Buffer sources)
  941. {
  942. using boost::detail::graph::init_centrality_map;
  943. using boost::detail::graph::divide_centrality_by_two;
  944. using boost::graph::parallel::process_group;
  945. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
  946. typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
  947. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  948. typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
  949. typedef typename property_traits<DistanceMap>::value_type distance_type;
  950. typedef ProcessGroup process_group_type;
  951. typename process_group_type::process_id_type id = process_id(pg);
  952. typename process_group_type::process_size_type p = num_processes(pg);
  953. // Initialize centrality
  954. init_centrality_map(vertices(g), centrality);
  955. init_centrality_map(edges(g), edge_centrality_map);
  956. std::stack<vertex_descriptor> ordered_vertices;
  957. if (!sources.empty()) {
  958. std::vector<vertex_descriptor> local_sources;
  959. for (int i = 0; i < id; ++i) if (!sources.empty()) sources.pop();
  960. while (!sources.empty()) {
  961. local_sources.push_back(sources.top());
  962. for (int i = 0; i < p; ++i) if (!sources.empty()) sources.pop();
  963. }
  964. // DO SSSPs
  965. for(size_t i = 0; i < local_sources.size(); ++i)
  966. do_sequential_brandes_sssp(g, centrality, edge_centrality_map, incoming,
  967. distance, dependency, path_count, vertex_index,
  968. shortest_paths, ordered_vertices, local_sources[i]);
  969. } else { // Exact Betweenness Centrality
  970. typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
  971. vertices_size_type n = num_vertices(g);
  972. for (vertices_size_type i = id; i < n; i += p) {
  973. vertex_descriptor v = vertex(i, g);
  974. do_sequential_brandes_sssp(g, centrality, edge_centrality_map, incoming,
  975. distance, dependency, path_count, vertex_index,
  976. shortest_paths, ordered_vertices, v);
  977. }
  978. }
  979. typedef typename graph_traits<Graph>::directed_category directed_category;
  980. const bool is_undirected =
  981. is_convertible<directed_category*, undirected_tag*>::value;
  982. if (is_undirected) {
  983. divide_centrality_by_two(vertices(g), centrality);
  984. divide_centrality_by_two(edges(g), edge_centrality_map);
  985. }
  986. // Merge the centrality maps by summing the values at each vertex)
  987. // TODO(nge): this copy-out, reduce, copy-in is lame
  988. typedef typename property_traits<CentralityMap>::value_type centrality_type;
  989. typedef typename property_traits<EdgeCentralityMap>::value_type edge_centrality_type;
  990. std::vector<centrality_type> centrality_v(num_vertices(g));
  991. std::vector<edge_centrality_type> edge_centrality_v;
  992. edge_centrality_v.reserve(num_edges(g));
  993. BGL_FORALL_VERTICES_T(v, g, Graph) {
  994. centrality_v[get(vertex_index, v)] = get(centrality, v);
  995. }
  996. // Skip when EdgeCentralityMap is a dummy_property_map
  997. if (!is_same<EdgeCentralityMap, dummy_property_map>::value) {
  998. BGL_FORALL_EDGES_T(e, g, Graph) {
  999. edge_centrality_v.push_back(get(edge_centrality_map, e));
  1000. }
  1001. // NGE: If we trust that the order of elements in the vector isn't changed in the
  1002. // all_reduce below then this method avoids the need for an edge index map
  1003. }
  1004. using boost::parallel::all_reduce;
  1005. all_reduce(pg, &centrality_v[0], &centrality_v[centrality_v.size()],
  1006. &centrality_v[0], std::plus<centrality_type>());
  1007. if (edge_centrality_v.size())
  1008. all_reduce(pg, &edge_centrality_v[0], &edge_centrality_v[edge_centrality_v.size()],
  1009. &edge_centrality_v[0], std::plus<edge_centrality_type>());
  1010. BGL_FORALL_VERTICES_T(v, g, Graph) {
  1011. put(centrality, v, centrality_v[get(vertex_index, v)]);
  1012. }
  1013. // Skip when EdgeCentralityMap is a dummy_property_map
  1014. if (!is_same<EdgeCentralityMap, dummy_property_map>::value) {
  1015. int i = 0;
  1016. BGL_FORALL_EDGES_T(e, g, Graph) {
  1017. put(edge_centrality_map, e, edge_centrality_v[i]);
  1018. ++i;
  1019. }
  1020. }
  1021. }
  1022. } } } // end namespace graph::parallel::detail
  1023. template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
  1024. typename IncomingMap, typename DistanceMap, typename DependencyMap,
  1025. typename PathCountMap, typename VertexIndexMap, typename Buffer>
  1026. void
  1027. brandes_betweenness_centrality(const Graph& g,
  1028. CentralityMap centrality,
  1029. EdgeCentralityMap edge_centrality_map,
  1030. IncomingMap incoming,
  1031. DistanceMap distance,
  1032. DependencyMap dependency,
  1033. PathCountMap path_count,
  1034. VertexIndexMap vertex_index,
  1035. Buffer sources,
  1036. typename property_traits<DistanceMap>::value_type delta
  1037. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  1038. {
  1039. typedef typename property_traits<DistanceMap>::value_type distance_type;
  1040. typedef static_property_map<distance_type> WeightMap;
  1041. graph::parallel::detail::brandes_shortest_paths<WeightMap>
  1042. shortest_paths(delta);
  1043. graph::parallel::detail::brandes_betweenness_centrality_impl(g, centrality,
  1044. edge_centrality_map,
  1045. incoming, distance,
  1046. dependency, path_count,
  1047. vertex_index,
  1048. shortest_paths,
  1049. sources);
  1050. }
  1051. template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
  1052. typename IncomingMap, typename DistanceMap, typename DependencyMap,
  1053. typename PathCountMap, typename VertexIndexMap, typename WeightMap,
  1054. typename Buffer>
  1055. void
  1056. brandes_betweenness_centrality(const Graph& g,
  1057. CentralityMap centrality,
  1058. EdgeCentralityMap edge_centrality_map,
  1059. IncomingMap incoming,
  1060. DistanceMap distance,
  1061. DependencyMap dependency,
  1062. PathCountMap path_count,
  1063. VertexIndexMap vertex_index,
  1064. Buffer sources,
  1065. typename p