annotate DEPENDENCIES/generic/include/boost/graph/distributed/betweenness_centrality.hpp @ 118:770eb830ec19 emscripten

Typo fix
author Chris Cannam
date Wed, 18 May 2016 16:14:08 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Copyright 2004 The Trustees of Indiana University.
Chris@16 2
Chris@16 3 // Distributed under the Boost Software License, Version 1.0.
Chris@16 4 // (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 5 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 // Authors: Douglas Gregor
Chris@16 8 // Andrew Lumsdaine
Chris@16 9 #ifndef BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP
Chris@16 10 #define BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP
Chris@16 11
Chris@16 12 #ifndef BOOST_GRAPH_USE_MPI
Chris@16 13 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
Chris@16 14 #endif
Chris@16 15
Chris@16 16 // #define COMPUTE_PATH_COUNTS_INLINE
Chris@16 17
Chris@16 18 #include <boost/graph/betweenness_centrality.hpp>
Chris@16 19 #include <boost/graph/overloading.hpp>
Chris@16 20 #include <boost/graph/distributed/concepts.hpp>
Chris@16 21 #include <boost/graph/graph_traits.hpp>
Chris@16 22 #include <boost/config.hpp>
Chris@16 23 #include <boost/assert.hpp>
Chris@16 24
Chris@16 25 // For additive_reducer
Chris@16 26 #include <boost/graph/distributed/distributed_graph_utility.hpp>
Chris@16 27 #include <boost/type_traits/is_convertible.hpp>
Chris@16 28 #include <boost/type_traits/is_same.hpp>
Chris@16 29 #include <boost/property_map/property_map.hpp>
Chris@16 30 #include <boost/graph/named_function_params.hpp>
Chris@16 31
Chris@16 32 #include <boost/property_map/parallel/distributed_property_map.hpp>
Chris@16 33 #include <boost/graph/distributed/detail/dijkstra_shortest_paths.hpp>
Chris@16 34 #include <boost/tuple/tuple.hpp>
Chris@16 35
Chris@16 36 // NGE - Needed for minstd_rand at L807, should pass vertex list
Chris@16 37 // or generator instead
Chris@16 38 #include <boost/random/linear_congruential.hpp>
Chris@16 39
Chris@16 40 #include <algorithm>
Chris@16 41 #include <stack>
Chris@16 42 #include <vector>
Chris@16 43
Chris@16 44 // Appending reducer
Chris@16 45 template <typename T>
Chris@16 46 struct append_reducer {
Chris@16 47 BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
Chris@16 48
Chris@16 49 template<typename K>
Chris@16 50 T operator()(const K&) const { return T(); }
Chris@16 51
Chris@16 52 template<typename K>
Chris@16 53 T operator()(const K&, const T& x, const T& y) const
Chris@16 54 {
Chris@16 55 T z(x.begin(), x.end());
Chris@16 56 for (typename T::const_iterator iter = y.begin(); iter != y.end(); ++iter)
Chris@16 57 if (std::find(z.begin(), z.end(), *iter) == z.end())
Chris@16 58 z.push_back(*iter);
Chris@16 59
Chris@16 60 return z;
Chris@16 61 }
Chris@16 62 };
Chris@16 63
Chris@16 64 namespace boost {
Chris@16 65
Chris@16 66 namespace serialization {
Chris@16 67
Chris@16 68 // TODO(nge): Write generalized serialization for tuples
Chris@16 69 template<typename Archive, typename T1, typename T2, typename T3,
Chris@16 70 typename T4>
Chris@16 71 void serialize(Archive & ar,
Chris@16 72 boost::tuple<T1,T2,T3, T4>& t,
Chris@16 73 const unsigned int)
Chris@16 74 {
Chris@16 75 ar & boost::tuples::get<0>(t);
Chris@16 76 ar & boost::tuples::get<1>(t);
Chris@16 77 ar & boost::tuples::get<2>(t);
Chris@16 78 ar & boost::tuples::get<3>(t);
Chris@16 79 }
Chris@16 80
Chris@16 81 } // serialization
Chris@16 82
Chris@16 83 template <typename OwnerMap, typename Tuple>
Chris@16 84 class get_owner_of_first_tuple_element {
Chris@16 85
Chris@16 86 public:
Chris@16 87 typedef typename property_traits<OwnerMap>::value_type owner_type;
Chris@16 88
Chris@16 89 get_owner_of_first_tuple_element(OwnerMap owner) : owner(owner) { }
Chris@16 90
Chris@16 91 owner_type get_owner(Tuple t) { return get(owner, boost::tuples::get<0>(t)); }
Chris@16 92
Chris@16 93 private:
Chris@16 94 OwnerMap owner;
Chris@16 95 };
Chris@16 96
Chris@16 97 template <typename OwnerMap, typename Tuple>
Chris@16 98 typename get_owner_of_first_tuple_element<OwnerMap, Tuple>::owner_type
Chris@16 99 get(get_owner_of_first_tuple_element<OwnerMap, Tuple> o, Tuple t)
Chris@16 100 { return o.get_owner(t); }
Chris@16 101
Chris@16 102 template <typename OwnerMap>
Chris@16 103 class get_owner_of_first_pair_element {
Chris@16 104
Chris@16 105 public:
Chris@16 106 typedef typename property_traits<OwnerMap>::value_type owner_type;
Chris@16 107
Chris@16 108 get_owner_of_first_pair_element(OwnerMap owner) : owner(owner) { }
Chris@16 109
Chris@16 110 template <typename Vertex, typename T>
Chris@16 111 owner_type get_owner(std::pair<Vertex, T> p) { return get(owner, p.first); }
Chris@16 112
Chris@16 113 private:
Chris@16 114 OwnerMap owner;
Chris@16 115 };
Chris@16 116
Chris@16 117 template <typename OwnerMap, typename Vertex, typename T>
Chris@16 118 typename get_owner_of_first_pair_element<OwnerMap>::owner_type
Chris@16 119 get(get_owner_of_first_pair_element<OwnerMap> o, std::pair<Vertex, T> p)
Chris@16 120 { return o.get_owner(p); }
Chris@16 121
Chris@16 122 namespace graph { namespace parallel { namespace detail {
Chris@16 123
Chris@16 124 template<typename DistanceMap, typename IncomingMap>
Chris@16 125 class betweenness_centrality_msg_value
Chris@16 126 {
Chris@16 127 typedef typename property_traits<DistanceMap>::value_type distance_type;
Chris@16 128 typedef typename property_traits<IncomingMap>::value_type incoming_type;
Chris@16 129 typedef typename incoming_type::value_type incoming_value_type;
Chris@16 130
Chris@16 131 public:
Chris@16 132 typedef std::pair<distance_type, incoming_value_type> type;
Chris@16 133
Chris@16 134 static type create(distance_type dist, incoming_value_type source)
Chris@16 135 { return std::make_pair(dist, source); }
Chris@16 136 };
Chris@16 137
Chris@16 138
Chris@16 139 /************************************************************************/
Chris@16 140 /* Delta-stepping Betweenness Centrality */
Chris@16 141 /************************************************************************/
Chris@16 142
Chris@16 143 template<typename Graph, typename DistanceMap, typename IncomingMap,
Chris@16 144 typename EdgeWeightMap, typename PathCountMap
Chris@16 145 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 146 , typename IsSettledMap, typename VertexIndexMap
Chris@16 147 #endif
Chris@16 148 >
Chris@16 149 class betweenness_centrality_delta_stepping_impl {
Chris@16 150 // Could inherit from delta_stepping_impl to get run() method
Chris@16 151 // but for the time being it's just reproduced here
Chris@16 152
Chris@16 153 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 154 typedef typename graph_traits<Graph>::degree_size_type Degree;
Chris@16 155 typedef typename property_traits<EdgeWeightMap>::value_type Dist;
Chris@16 156 typedef typename property_traits<IncomingMap>::value_type IncomingType;
Chris@16 157 typedef typename boost::graph::parallel::process_group_type<Graph>::type
Chris@16 158 ProcessGroup;
Chris@16 159
Chris@16 160 typedef std::list<Vertex> Bucket;
Chris@16 161 typedef typename Bucket::iterator BucketIterator;
Chris@16 162 typedef typename std::vector<Bucket*>::size_type BucketIndex;
Chris@16 163
Chris@16 164 typedef betweenness_centrality_msg_value<DistanceMap, IncomingMap>
Chris@16 165 MessageValue;
Chris@16 166
Chris@16 167 enum {
Chris@16 168 // Relax a remote vertex. The message contains a pair<Vertex,
Chris@16 169 // MessageValue>, the first part of which is the vertex whose
Chris@16 170 // tentative distance is being relaxed and the second part
Chris@16 171 // contains either the new distance (if there is no predecessor
Chris@16 172 // map) or a pair with the distance and predecessor.
Chris@16 173 msg_relax
Chris@16 174 };
Chris@16 175
Chris@16 176 public:
Chris@16 177
Chris@16 178 // Must supply delta, ctor that guesses delta removed
Chris@16 179 betweenness_centrality_delta_stepping_impl(const Graph& g,
Chris@16 180 DistanceMap distance,
Chris@16 181 IncomingMap incoming,
Chris@16 182 EdgeWeightMap weight,
Chris@16 183 PathCountMap path_count,
Chris@16 184 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 185 IsSettledMap is_settled,
Chris@16 186 VertexIndexMap vertex_index,
Chris@16 187 #endif
Chris@16 188 Dist delta);
Chris@16 189
Chris@16 190 void run(Vertex s);
Chris@16 191
Chris@16 192 private:
Chris@16 193 // Relax the edge (u, v), creating a new best path of distance x.
Chris@16 194 void relax(Vertex u, Vertex v, Dist x);
Chris@16 195
Chris@16 196 // Synchronize all of the processes, by receiving all messages that
Chris@16 197 // have not yet been received.
Chris@16 198 void synchronize()
Chris@16 199 {
Chris@101 200 using boost::parallel::synchronize;
Chris@16 201 synchronize(pg);
Chris@16 202 }
Chris@16 203
Chris@16 204 // Setup triggers for msg_relax messages
Chris@16 205 void setup_triggers()
Chris@16 206 {
Chris@101 207 using boost::parallel::simple_trigger;
Chris@16 208 simple_trigger(pg, msg_relax, this,
Chris@16 209 &betweenness_centrality_delta_stepping_impl::handle_msg_relax);
Chris@16 210 }
Chris@16 211
Chris@16 212 void handle_msg_relax(int /*source*/, int /*tag*/,
Chris@16 213 const std::pair<Vertex, typename MessageValue::type>& data,
Chris@101 214 boost::parallel::trigger_receive_context)
Chris@16 215 { relax(data.second.second, data.first, data.second.first); }
Chris@16 216
Chris@16 217 const Graph& g;
Chris@16 218 IncomingMap incoming;
Chris@16 219 DistanceMap distance;
Chris@16 220 EdgeWeightMap weight;
Chris@16 221 PathCountMap path_count;
Chris@16 222 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 223 IsSettledMap is_settled;
Chris@16 224 VertexIndexMap vertex_index;
Chris@16 225 #endif
Chris@16 226 Dist delta;
Chris@16 227 ProcessGroup pg;
Chris@16 228 typename property_map<Graph, vertex_owner_t>::const_type owner;
Chris@16 229 typename property_map<Graph, vertex_local_t>::const_type local;
Chris@16 230
Chris@16 231 // A "property map" that contains the position of each vertex in
Chris@16 232 // whatever bucket it resides in.
Chris@16 233 std::vector<BucketIterator> position_in_bucket;
Chris@16 234
Chris@16 235 // Bucket data structure. The ith bucket contains all local vertices
Chris@16 236 // with (tentative) distance in the range [i*delta,
Chris@16 237 // (i+1)*delta).
Chris@16 238 std::vector<Bucket*> buckets;
Chris@16 239
Chris@16 240 // This "dummy" list is used only so that we can initialize the
Chris@16 241 // position_in_bucket property map with non-singular iterators. This
Chris@16 242 // won't matter for most implementations of the C++ Standard
Chris@16 243 // Library, but it avoids undefined behavior and allows us to run
Chris@16 244 // with library "debug modes".
Chris@16 245 std::list<Vertex> dummy_list;
Chris@16 246
Chris@16 247 // A "property map" that states which vertices have been deleted
Chris@16 248 // from the bucket in this iteration.
Chris@16 249 std::vector<bool> vertex_was_deleted;
Chris@16 250 };
Chris@16 251
Chris@16 252 template<typename Graph, typename DistanceMap, typename IncomingMap,
Chris@16 253 typename EdgeWeightMap, typename PathCountMap
Chris@16 254 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 255 , typename IsSettledMap, typename VertexIndexMap
Chris@16 256 #endif
Chris@16 257 >
Chris@16 258 betweenness_centrality_delta_stepping_impl<
Chris@16 259 Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
Chris@16 260 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 261 , IsSettledMap, VertexIndexMap
Chris@16 262 #endif
Chris@16 263 >::
Chris@16 264 betweenness_centrality_delta_stepping_impl(const Graph& g,
Chris@16 265 DistanceMap distance,
Chris@16 266 IncomingMap incoming,
Chris@16 267 EdgeWeightMap weight,
Chris@16 268 PathCountMap path_count,
Chris@16 269 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 270 IsSettledMap is_settled,
Chris@16 271 VertexIndexMap vertex_index,
Chris@16 272 #endif
Chris@16 273 Dist delta)
Chris@16 274 : g(g),
Chris@16 275 incoming(incoming),
Chris@16 276 distance(distance),
Chris@16 277 weight(weight),
Chris@16 278 path_count(path_count),
Chris@16 279 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 280 is_settled(is_settled),
Chris@16 281 vertex_index(vertex_index),
Chris@16 282 #endif
Chris@16 283 delta(delta),
Chris@101 284 pg(boost::graph::parallel::process_group_adl(g), boost::parallel::attach_distributed_object()),
Chris@16 285 owner(get(vertex_owner, g)),
Chris@16 286 local(get(vertex_local, g))
Chris@16 287
Chris@16 288 { setup_triggers(); }
Chris@16 289
Chris@16 290 template<typename Graph, typename DistanceMap, typename IncomingMap,
Chris@16 291 typename EdgeWeightMap, typename PathCountMap
Chris@16 292 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 293 , typename IsSettledMap, typename VertexIndexMap
Chris@16 294 #endif
Chris@16 295 >
Chris@16 296 void
Chris@16 297 betweenness_centrality_delta_stepping_impl<
Chris@16 298 Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
Chris@16 299 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 300 , IsSettledMap, VertexIndexMap
Chris@16 301 #endif
Chris@16 302 >::
Chris@16 303 run(Vertex s)
Chris@16 304 {
Chris@16 305 typedef typename boost::graph::parallel::process_group_type<Graph>::type
Chris@16 306 process_group_type;
Chris@16 307 typename process_group_type::process_id_type id = process_id(pg);
Chris@16 308
Chris@16 309 Dist inf = (std::numeric_limits<Dist>::max)();
Chris@16 310
Chris@16 311 // None of the vertices are stored in the bucket.
Chris@16 312 position_in_bucket.clear();
Chris@16 313 position_in_bucket.resize(num_vertices(g), dummy_list.end());
Chris@16 314
Chris@16 315 // None of the vertices have been deleted
Chris@16 316 vertex_was_deleted.clear();
Chris@16 317 vertex_was_deleted.resize(num_vertices(g), false);
Chris@16 318
Chris@16 319 // No path from s to any other vertex, yet
Chris@16 320 BGL_FORALL_VERTICES_T(v, g, Graph)
Chris@16 321 put(distance, v, inf);
Chris@16 322
Chris@16 323 // The distance to the starting node is zero
Chris@16 324 if (get(owner, s) == id)
Chris@16 325 // Put "s" into its bucket (bucket 0)
Chris@16 326 relax(s, s, 0);
Chris@16 327 else
Chris@16 328 // Note that we know the distance to s is zero
Chris@16 329 cache(distance, s, 0);
Chris@16 330
Chris@16 331 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 332 // Synchronize here to deliver initial relaxation since we don't
Chris@16 333 // synchronize at the beginning of the inner loop any more
Chris@16 334 synchronize();
Chris@16 335
Chris@16 336 // Incoming edge count map is an implementation detail and should
Chris@16 337 // be freed as soon as possible so build it here
Chris@16 338 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
Chris@16 339
Chris@16 340 std::vector<edges_size_type> incoming_edge_countS(num_vertices(g));
Chris@16 341 iterator_property_map<typename std::vector<edges_size_type>::iterator, VertexIndexMap>
Chris@16 342 incoming_edge_count(incoming_edge_countS.begin(), vertex_index);
Chris@16 343 #endif
Chris@16 344
Chris@16 345 BucketIndex max_bucket = (std::numeric_limits<BucketIndex>::max)();
Chris@16 346 BucketIndex current_bucket = 0;
Chris@16 347 do {
Chris@16 348 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 349 // We need to clear the outgoing map after every bucket so just build it here
Chris@16 350 std::vector<IncomingType> outgoingS(num_vertices(g));
Chris@16 351 IncomingMap outgoing(outgoingS.begin(), vertex_index);
Chris@16 352
Chris@16 353 outgoing.set_reduce(append_reducer<IncomingType>());
Chris@16 354 #else
Chris@16 355 // Synchronize with all of the other processes.
Chris@16 356 synchronize();
Chris@16 357 #endif
Chris@16 358
Chris@16 359 // Find the next bucket that has something in it.
Chris@16 360 while (current_bucket < buckets.size()
Chris@16 361 && (!buckets[current_bucket] || buckets[current_bucket]->empty()))
Chris@16 362 ++current_bucket;
Chris@16 363 if (current_bucket >= buckets.size())
Chris@16 364 current_bucket = max_bucket;
Chris@16 365
Chris@16 366 // Find the smallest bucket (over all processes) that has vertices
Chris@16 367 // that need to be processed.
Chris@16 368 using boost::parallel::all_reduce;
Chris@16 369 using boost::parallel::minimum;
Chris@16 370 current_bucket = all_reduce(pg, current_bucket, minimum<BucketIndex>());
Chris@16 371
Chris@16 372 if (current_bucket == max_bucket)
Chris@16 373 // There are no non-empty buckets in any process; exit.
Chris@16 374 break;
Chris@16 375
Chris@16 376 // Contains the set of vertices that have been deleted in the
Chris@16 377 // relaxation of "light" edges. Note that we keep track of which
Chris@16 378 // vertices were deleted with the property map
Chris@16 379 // "vertex_was_deleted".
Chris@16 380 std::vector<Vertex> deleted_vertices;
Chris@16 381
Chris@16 382 // Repeatedly relax light edges
Chris@16 383 bool nonempty_bucket;
Chris@16 384 do {
Chris@16 385 // Someone has work to do in this bucket.
Chris@16 386
Chris@16 387 if (current_bucket < buckets.size() && buckets[current_bucket]) {
Chris@16 388 Bucket& bucket = *buckets[current_bucket];
Chris@16 389 // For each element in the bucket
Chris@16 390 while (!bucket.empty()) {
Chris@16 391 Vertex u = bucket.front();
Chris@16 392
Chris@16 393 // Remove u from the front of the bucket
Chris@16 394 bucket.pop_front();
Chris@16 395
Chris@16 396 // Insert u into the set of deleted vertices, if it hasn't
Chris@16 397 // been done already.
Chris@16 398 if (!vertex_was_deleted[get(local, u)]) {
Chris@16 399 vertex_was_deleted[get(local, u)] = true;
Chris@16 400 deleted_vertices.push_back(u);
Chris@16 401 }
Chris@16 402
Chris@16 403 // Relax each light edge.
Chris@16 404 Dist u_dist = get(distance, u);
Chris@16 405 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
Chris@16 406 if (get(weight, e) <= delta) // light edge
Chris@16 407 relax(u, target(e, g), u_dist + get(weight, e));
Chris@16 408 }
Chris@16 409 }
Chris@16 410
Chris@16 411 // Synchronize with all of the other processes.
Chris@16 412 synchronize();
Chris@16 413
Chris@16 414 // Is the bucket empty now?
Chris@16 415 nonempty_bucket = (current_bucket < buckets.size()
Chris@16 416 && buckets[current_bucket]
Chris@16 417 && !buckets[current_bucket]->empty());
Chris@16 418 } while (all_reduce(pg, nonempty_bucket, std::logical_or<bool>()));
Chris@16 419
Chris@16 420 // Relax heavy edges for each of the vertices that we previously
Chris@16 421 // deleted.
Chris@16 422 for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
Chris@16 423 iter != deleted_vertices.end(); ++iter) {
Chris@16 424 // Relax each heavy edge.
Chris@16 425 Vertex u = *iter;
Chris@16 426 Dist u_dist = get(distance, u);
Chris@16 427 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
Chris@16 428 if (get(weight, e) > delta) // heavy edge
Chris@16 429 relax(u, target(e, g), u_dist + get(weight, e));
Chris@16 430
Chris@16 431 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 432 // Set outgoing paths
Chris@16 433 IncomingType in = get(incoming, u);
Chris@16 434 for (typename IncomingType::iterator pred = in.begin(); pred != in.end(); ++pred)
Chris@16 435 if (get(owner, *pred) == id) {
Chris@16 436 IncomingType x = get(outgoing, *pred);
Chris@16 437 if (std::find(x.begin(), x.end(), u) == x.end())
Chris@16 438 x.push_back(u);
Chris@16 439 put(outgoing, *pred, x);
Chris@16 440 } else {
Chris@16 441 IncomingType in;
Chris@16 442 in.push_back(u);
Chris@16 443 put(outgoing, *pred, in);
Chris@16 444 }
Chris@16 445
Chris@16 446 // Set incoming edge counts
Chris@16 447 put(incoming_edge_count, u, in.size());
Chris@16 448 #endif
Chris@16 449 }
Chris@16 450
Chris@16 451 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 452 synchronize(); // Deliver heavy edge relaxations and outgoing paths
Chris@16 453
Chris@16 454 // Build Queue
Chris@16 455 typedef typename property_traits<PathCountMap>::value_type PathCountType;
Chris@16 456 typedef std::pair<Vertex, PathCountType> queue_value_type;
Chris@16 457 typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
Chris@16 458 typedef typename get_owner_of_first_pair_element<OwnerMap> IndirectOwnerMap;
Chris@16 459
Chris@16 460 typedef boost::queue<queue_value_type> local_queue_type;
Chris@16 461 typedef boost::graph::distributed::distributed_queue<process_group_type,
Chris@16 462 IndirectOwnerMap,
Chris@16 463 local_queue_type> dist_queue_type;
Chris@16 464
Chris@16 465 IndirectOwnerMap indirect_owner(owner);
Chris@16 466 dist_queue_type Q(pg, indirect_owner);
Chris@16 467
Chris@16 468 // Find sources to initialize queue
Chris@16 469 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 470 if (get(is_settled, v) && !(get(outgoing, v).empty())) {
Chris@16 471 put(incoming_edge_count, v, 1);
Chris@16 472 Q.push(std::make_pair(v, 0)); // Push this vertex with no additional path count
Chris@16 473 }
Chris@16 474 }
Chris@16 475
Chris@16 476 // Set path counts for vertices in this bucket
Chris@16 477 while (!Q.empty()) {
Chris@16 478 queue_value_type t = Q.top(); Q.pop();
Chris@16 479 Vertex v = t.first;
Chris@16 480 PathCountType p = t.second;
Chris@16 481
Chris@16 482 put(path_count, v, get(path_count, v) + p);
Chris@16 483 put(incoming_edge_count, v, get(incoming_edge_count, v) - 1);
Chris@16 484
Chris@16 485 if (get(incoming_edge_count, v) == 0) {
Chris@16 486 IncomingType out = get(outgoing, v);
Chris@16 487 for (typename IncomingType::iterator iter = out.begin(); iter != out.end(); ++iter)
Chris@16 488 Q.push(std::make_pair(*iter, get(path_count, v)));
Chris@16 489 }
Chris@16 490 }
Chris@16 491
Chris@16 492 // Mark the vertices in this bucket settled
Chris@16 493 for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
Chris@16 494 iter != deleted_vertices.end(); ++iter)
Chris@16 495 put(is_settled, *iter, true);
Chris@16 496
Chris@16 497 // No need to clear path count map as it is never read/written remotely
Chris@16 498 // No need to clear outgoing map as it is re-alloced every bucket
Chris@16 499 #endif
Chris@16 500
Chris@16 501 // Go to the next bucket: the current bucket must already be empty.
Chris@16 502 ++current_bucket;
Chris@16 503 } while (true);
Chris@16 504
Chris@16 505 // Delete all of the buckets.
Chris@16 506 for (typename std::vector<Bucket*>::iterator iter = buckets.begin();
Chris@16 507 iter != buckets.end(); ++iter) {
Chris@16 508 if (*iter) {
Chris@16 509 delete *iter;
Chris@16 510 *iter = 0;
Chris@16 511 }
Chris@16 512 }
Chris@16 513 }
Chris@16 514
Chris@16 515 template<typename Graph, typename DistanceMap, typename IncomingMap,
Chris@16 516 typename EdgeWeightMap, typename PathCountMap
Chris@16 517 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 518 , typename IsSettledMap, typename VertexIndexMap
Chris@16 519 #endif
Chris@16 520 >
Chris@16 521 void
Chris@16 522 betweenness_centrality_delta_stepping_impl<
Chris@16 523 Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
Chris@16 524 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 525 , IsSettledMap, VertexIndexMap
Chris@16 526 #endif
Chris@16 527 >::
Chris@16 528 relax(Vertex u, Vertex v, Dist x)
Chris@16 529 {
Chris@16 530
Chris@16 531 if (x <= get(distance, v)) {
Chris@16 532
Chris@16 533 // We're relaxing the edge to vertex v.
Chris@16 534 if (get(owner, v) == process_id(pg)) {
Chris@16 535 if (x < get(distance, v)) {
Chris@16 536 // Compute the new bucket index for v
Chris@16 537 BucketIndex new_index = static_cast<BucketIndex>(x / delta);
Chris@16 538
Chris@16 539 // Make sure there is enough room in the buckets data structure.
Chris@16 540 if (new_index >= buckets.size()) buckets.resize(new_index + 1, 0);
Chris@16 541
Chris@16 542 // Make sure that we have allocated the bucket itself.
Chris@16 543 if (!buckets[new_index]) buckets[new_index] = new Bucket;
Chris@16 544
Chris@16 545 if (get(distance, v) != (std::numeric_limits<Dist>::max)()
Chris@16 546 && !vertex_was_deleted[get(local, v)]) {
Chris@16 547 // We're moving v from an old bucket into a new one. Compute
Chris@16 548 // the old index, then splice it in.
Chris@16 549 BucketIndex old_index
Chris@16 550 = static_cast<BucketIndex>(get(distance, v) / delta);
Chris@16 551 buckets[new_index]->splice(buckets[new_index]->end(),
Chris@16 552 *buckets[old_index],
Chris@16 553 position_in_bucket[get(local, v)]);
Chris@16 554 } else {
Chris@16 555 // We're inserting v into a bucket for the first time. Put it
Chris@16 556 // at the end.
Chris@16 557 buckets[new_index]->push_back(v);
Chris@16 558 }
Chris@16 559
Chris@16 560 // v is now at the last position in the new bucket
Chris@16 561 position_in_bucket[get(local, v)] = buckets[new_index]->end();
Chris@16 562 --position_in_bucket[get(local, v)];
Chris@16 563
Chris@16 564 // Update tentative distance information and incoming, path_count
Chris@16 565 if (u != v) put(incoming, v, IncomingType(1, u));
Chris@16 566 put(distance, v, x);
Chris@16 567 } // u != v covers initial source relaxation and self-loops
Chris@16 568 else if (x == get(distance, v) && u != v) {
Chris@16 569
Chris@16 570 // Add incoming edge if it's not already in the list
Chris@16 571 IncomingType in = get(incoming, v);
Chris@16 572 if (std::find(in.begin(), in.end(), u) == in.end()) {
Chris@16 573 in.push_back(u);
Chris@16 574 put(incoming, v, in);
Chris@16 575 }
Chris@16 576 }
Chris@16 577 } else {
Chris@16 578 // The vertex is remote: send a request to the vertex's owner
Chris@16 579 send(pg, get(owner, v), msg_relax,
Chris@16 580 std::make_pair(v, MessageValue::create(x, u)));
Chris@16 581
Chris@16 582 // Cache tentative distance information
Chris@16 583 cache(distance, v, x);
Chris@16 584 }
Chris@16 585 }
Chris@16 586 }
Chris@16 587
Chris@16 588 /************************************************************************/
Chris@16 589 /* Shortest Paths function object for betweenness centrality */
Chris@16 590 /************************************************************************/
Chris@16 591
Chris@16 592 template<typename WeightMap>
Chris@16 593 struct brandes_shortest_paths {
Chris@16 594 typedef typename property_traits<WeightMap>::value_type weight_type;
Chris@16 595
Chris@16 596 brandes_shortest_paths()
Chris@16 597 : weight(1), delta(0) { }
Chris@16 598 brandes_shortest_paths(weight_type delta)
Chris@16 599 : weight(1), delta(delta) { }
Chris@16 600 brandes_shortest_paths(WeightMap w)
Chris@16 601 : weight(w), delta(0) { }
Chris@16 602 brandes_shortest_paths(WeightMap w, weight_type delta)
Chris@16 603 : weight(w), delta(delta) { }
Chris@16 604
Chris@16 605 template<typename Graph, typename IncomingMap, typename DistanceMap,
Chris@16 606 typename PathCountMap
Chris@16 607 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 608 , typename IsSettledMap, typename VertexIndexMap
Chris@16 609 #endif
Chris@16 610
Chris@16 611 >
Chris@16 612 void
Chris@16 613 operator()(Graph& g,
Chris@16 614 typename graph_traits<Graph>::vertex_descriptor s,
Chris@16 615 IncomingMap incoming,
Chris@16 616 DistanceMap distance,
Chris@16 617 PathCountMap path_count
Chris@16 618 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 619 , IsSettledMap is_settled,
Chris@16 620 VertexIndexMap vertex_index
Chris@16 621 #endif
Chris@16 622 )
Chris@16 623 {
Chris@16 624 // The "distance" map needs to act like one, retrieving the default
Chris@16 625 // value of infinity.
Chris@16 626 set_property_map_role(vertex_distance, distance);
Chris@16 627
Chris@16 628 // Only calculate delta the first time operator() is called
Chris@16 629 // This presumes g is the same every time, but so does the fact
Chris@16 630 // that we're reusing the weight map
Chris@16 631 if (delta == 0)
Chris@16 632 set_delta(g);
Chris@16 633
Chris@16 634 // TODO (NGE): Restructure the code so we don't have to construct
Chris@16 635 // impl every time?
Chris@16 636 betweenness_centrality_delta_stepping_impl<
Chris@16 637 Graph, DistanceMap, IncomingMap, WeightMap, PathCountMap
Chris@16 638 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 639 , IsSettledMap, VertexIndexMap
Chris@16 640 #endif
Chris@16 641 >
Chris@16 642 impl(g, distance, incoming, weight, path_count,
Chris@16 643 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 644 is_settled, vertex_index,
Chris@16 645 #endif
Chris@16 646 delta);
Chris@16 647
Chris@16 648 impl.run(s);
Chris@16 649 }
Chris@16 650
Chris@16 651 private:
Chris@16 652
Chris@16 653 template <typename Graph>
Chris@16 654 void
Chris@16 655 set_delta(const Graph& g)
Chris@16 656 {
Chris@16 657 using boost::parallel::all_reduce;
Chris@16 658 using boost::parallel::maximum;
Chris@16 659 using std::max;
Chris@16 660
Chris@16 661 typedef typename graph_traits<Graph>::degree_size_type Degree;
Chris@16 662 typedef weight_type Dist;
Chris@16 663
Chris@16 664 // Compute the maximum edge weight and degree
Chris@16 665 Dist max_edge_weight = 0;
Chris@16 666 Degree max_degree = 0;
Chris@16 667 BGL_FORALL_VERTICES_T(u, g, Graph) {
Chris@16 668 max_degree = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_degree, out_degree(u, g));
Chris@16 669 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
Chris@16 670 max_edge_weight = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_edge_weight, get(weight, e));
Chris@16 671 }
Chris@16 672
Chris@16 673 max_edge_weight = all_reduce(process_group(g), max_edge_weight, maximum<Dist>());
Chris@16 674 max_degree = all_reduce(process_group(g), max_degree, maximum<Degree>());
Chris@16 675
Chris@16 676 // Take a guess at delta, based on what works well for random
Chris@16 677 // graphs.
Chris@16 678 delta = max_edge_weight / max_degree;
Chris@16 679 if (delta == 0)
Chris@16 680 delta = 1;
Chris@16 681 }
Chris@16 682
Chris@16 683 WeightMap weight;
Chris@16 684 weight_type delta;
Chris@16 685 };
Chris@16 686
Chris@16 687 // Perform a single SSSP from the specified vertex and update the centrality map(s)
Chris@16 688 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 689 typename IncomingMap, typename DistanceMap, typename DependencyMap,
Chris@16 690 typename PathCountMap,
Chris@16 691 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 692 typename IsSettledMap,
Chris@16 693 #endif
Chris@16 694 typename VertexIndexMap, typename ShortestPaths>
Chris@16 695 void
Chris@16 696 do_brandes_sssp(const Graph& g,
Chris@16 697 CentralityMap centrality,
Chris@16 698 EdgeCentralityMap edge_centrality_map,
Chris@16 699 IncomingMap incoming,
Chris@16 700 DistanceMap distance,
Chris@16 701 DependencyMap dependency,
Chris@16 702 PathCountMap path_count,
Chris@16 703 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 704 IsSettledMap is_settled,
Chris@16 705 #endif
Chris@16 706 VertexIndexMap vertex_index,
Chris@16 707 ShortestPaths shortest_paths,
Chris@16 708 typename graph_traits<Graph>::vertex_descriptor s)
Chris@16 709 {
Chris@16 710 using boost::detail::graph::update_centrality;
Chris@16 711 using boost::graph::parallel::process_group;
Chris@16 712
Chris@16 713 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 714 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
Chris@16 715
Chris@16 716 typedef typename property_traits<IncomingMap>::value_type incoming_type;
Chris@16 717 typedef typename property_traits<DistanceMap>::value_type distance_type;
Chris@16 718 typedef typename property_traits<DependencyMap>::value_type dependency_type;
Chris@16 719 typedef typename property_traits<PathCountMap>::value_type path_count_type;
Chris@16 720
Chris@16 721 typedef typename incoming_type::iterator incoming_iterator;
Chris@16 722
Chris@16 723 typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
Chris@16 724 OwnerMap owner = get(vertex_owner, g);
Chris@16 725
Chris@16 726 typedef typename boost::graph::parallel::process_group_type<Graph>::type
Chris@16 727 process_group_type;
Chris@16 728 process_group_type pg = process_group(g);
Chris@16 729 typename process_group_type::process_id_type id = process_id(pg);
Chris@16 730
Chris@16 731 // TODO: Is it faster not to clear some of these maps?
Chris@16 732 // Initialize for this iteration
Chris@16 733 distance.clear();
Chris@16 734 incoming.clear();
Chris@16 735 path_count.clear();
Chris@16 736 dependency.clear();
Chris@16 737 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 738 put(path_count, v, 0);
Chris@16 739 put(dependency, v, 0);
Chris@16 740 }
Chris@16 741
Chris@16 742 if (get(owner, s) == id) {
Chris@16 743 put(incoming, s, incoming_type());
Chris@16 744 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 745 put(path_count, s, 1);
Chris@16 746 put(is_settled, s, true);
Chris@16 747 #endif
Chris@16 748 }
Chris@16 749
Chris@16 750 // Execute the shortest paths algorithm. This will be either
Chris@16 751 // a weighted or unweighted customized breadth-first search,
Chris@16 752 shortest_paths(g, s, incoming, distance, path_count
Chris@16 753 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 754 , is_settled, vertex_index
Chris@16 755 #endif
Chris@16 756 );
Chris@16 757
Chris@16 758 #ifndef COMPUTE_PATH_COUNTS_INLINE
Chris@16 759
Chris@16 760 //
Chris@16 761 // TODO: Optimize case where source has no out-edges
Chris@16 762 //
Chris@16 763
Chris@16 764 // Count of incoming edges to tell when all incoming edges have been relaxed in
Chris@16 765 // the induced shortest paths DAG
Chris@16 766 std::vector<edges_size_type> incoming_edge_countS(num_vertices(g));
Chris@16 767 iterator_property_map<typename std::vector<edges_size_type>::iterator, VertexIndexMap>
Chris@16 768 incoming_edge_count(incoming_edge_countS.begin(), vertex_index);
Chris@16 769
Chris@16 770 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 771 put(incoming_edge_count, v, get(incoming, v).size());
Chris@16 772 }
Chris@16 773
Chris@16 774 if (get(owner, s) == id) {
Chris@16 775 put(incoming_edge_count, s, 1);
Chris@16 776 put(incoming, s, incoming_type());
Chris@16 777 }
Chris@16 778
Chris@16 779 std::vector<incoming_type> outgoingS(num_vertices(g));
Chris@16 780 iterator_property_map<typename std::vector<incoming_type>::iterator, VertexIndexMap>
Chris@16 781 outgoing(outgoingS.begin(), vertex_index);
Chris@16 782
Chris@16 783 outgoing.set_reduce(append_reducer<incoming_type>());
Chris@16 784
Chris@16 785 // Mark forward adjacencies in DAG of shortest paths
Chris@16 786
Chris@16 787 // TODO: It's possible to do this using edge flags but it's not currently done this way
Chris@16 788 // because during traversal of the DAG we would have to examine all out edges
Chris@16 789 // which would lead to more memory accesses and a larger cache footprint.
Chris@16 790 //
Chris@16 791 // In the bidirectional graph case edge flags would be an excellent way of marking
Chris@16 792 // edges in the DAG of shortest paths
Chris@16 793 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 794 incoming_type i = get(incoming, v);
Chris@16 795 for (typename incoming_type::iterator iter = i.begin(); iter != i.end(); ++iter) {
Chris@16 796 if (get(owner, *iter) == id) {
Chris@16 797 incoming_type x = get(outgoing, *iter);
Chris@16 798 if (std::find(x.begin(), x.end(), v) == x.end())
Chris@16 799 x.push_back(v);
Chris@16 800 put(outgoing, *iter, x);
Chris@16 801 } else {
Chris@16 802 incoming_type in;
Chris@16 803 in.push_back(v);
Chris@16 804 put(outgoing, *iter, in);
Chris@16 805 }
Chris@16 806 }
Chris@16 807 }
Chris@16 808
Chris@16 809 synchronize(pg);
Chris@16 810
Chris@16 811 // Traverse DAG induced by forward edges in dependency order and compute path counts
Chris@16 812 {
Chris@16 813 typedef std::pair<vertex_descriptor, path_count_type> queue_value_type;
Chris@16 814 typedef get_owner_of_first_pair_element<OwnerMap> IndirectOwnerMap;
Chris@16 815
Chris@16 816 typedef boost::queue<queue_value_type> local_queue_type;
Chris@16 817 typedef boost::graph::distributed::distributed_queue<process_group_type,
Chris@16 818 IndirectOwnerMap,
Chris@16 819 local_queue_type> dist_queue_type;
Chris@16 820
Chris@16 821 IndirectOwnerMap indirect_owner(owner);
Chris@16 822 dist_queue_type Q(pg, indirect_owner);
Chris@16 823
Chris@16 824 if (get(owner, s) == id)
Chris@16 825 Q.push(std::make_pair(s, 1));
Chris@16 826
Chris@16 827 while (!Q.empty()) {
Chris@16 828 queue_value_type t = Q.top(); Q.pop();
Chris@16 829 vertex_descriptor v = t.first;
Chris@16 830 path_count_type p = t.second;
Chris@16 831
Chris@16 832 put(path_count, v, get(path_count, v) + p);
Chris@16 833 put(incoming_edge_count, v, get(incoming_edge_count, v) - 1);
Chris@16 834
Chris@16 835 if (get(incoming_edge_count, v) == 0) {
Chris@16 836 incoming_type out = get(outgoing, v);
Chris@16 837 for (typename incoming_type::iterator iter = out.begin(); iter != out.end(); ++iter)
Chris@16 838 Q.push(std::make_pair(*iter, get(path_count, v)));
Chris@16 839 }
Chris@16 840 }
Chris@16 841 }
Chris@16 842
Chris@16 843 #endif // COMPUTE_PATH_COUNTS_INLINE
Chris@16 844
Chris@16 845 //
Chris@16 846 // Compute dependencies
Chris@16 847 //
Chris@16 848
Chris@16 849
Chris@16 850 // Build the distributed_queue
Chris@16 851 // Value type consists of 1) target of update 2) source of update
Chris@16 852 // 3) dependency of source 4) path count of source
Chris@16 853 typedef boost::tuple<vertex_descriptor, vertex_descriptor, dependency_type, path_count_type>
Chris@16 854 queue_value_type;
Chris@16 855 typedef get_owner_of_first_tuple_element<OwnerMap, queue_value_type> IndirectOwnerMap;
Chris@16 856
Chris@16 857 typedef boost::queue<queue_value_type> local_queue_type;
Chris@16 858 typedef boost::graph::distributed::distributed_queue<process_group_type,
Chris@16 859 IndirectOwnerMap,
Chris@16 860 local_queue_type> dist_queue_type;
Chris@16 861
Chris@16 862 IndirectOwnerMap indirect_owner(owner);
Chris@16 863 dist_queue_type Q(pg, indirect_owner);
Chris@16 864
Chris@16 865 // Calculate number of vertices each vertex depends on, when a vertex has been pushed
Chris@16 866 // that number of times then we will update it
Chris@16 867 // AND Request path counts of sources of incoming edges
Chris@16 868 std::vector<dependency_type> dependency_countS(num_vertices(g), 0);
Chris@16 869 iterator_property_map<typename std::vector<dependency_type>::iterator, VertexIndexMap>
Chris@16 870 dependency_count(dependency_countS.begin(), vertex_index);
Chris@16 871
Chris@16 872 dependency_count.set_reduce(boost::graph::distributed::additive_reducer<dependency_type>());
Chris@16 873
Chris@16 874 path_count.set_max_ghost_cells(0);
Chris@16 875
Chris@16 876 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 877 if (get(distance, v) < (std::numeric_limits<distance_type>::max)()) {
Chris@16 878 incoming_type el = get(incoming, v);
Chris@16 879 for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw) {
Chris@16 880 if (get(owner, *vw) == id)
Chris@16 881 put(dependency_count, *vw, get(dependency_count, *vw) + 1);
Chris@16 882 else {
Chris@16 883 put(dependency_count, *vw, 1);
Chris@16 884
Chris@16 885 // Request path counts
Chris@16 886 get(path_count, *vw);
Chris@16 887 }
Chris@16 888
Chris@16 889 // request() doesn't work here, perhaps because we don't have a copy of this
Chris@16 890 // ghost cell already?
Chris@16 891 }
Chris@16 892 }
Chris@16 893 }
Chris@16 894
Chris@16 895 synchronize(pg);
Chris@16 896
Chris@16 897 // Push vertices with non-zero distance/path count and zero dependency count
Chris@16 898 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 899 if (get(distance, v) < (std::numeric_limits<distance_type>::max)()
Chris@16 900 && get(dependency_count, v) == 0)
Chris@16 901 Q.push(boost::make_tuple(v, v, get(dependency, v), get(path_count, v)));
Chris@16 902 }
Chris@16 903
Chris@16 904 dependency.set_max_ghost_cells(0);
Chris@16 905 while(!Q.empty()) {
Chris@16 906
Chris@16 907 queue_value_type x = Q.top(); Q.pop();
Chris@16 908 vertex_descriptor w = boost::tuples::get<0>(x);
Chris@16 909 vertex_descriptor source = boost::tuples::get<1>(x);
Chris@16 910 dependency_type dep = boost::tuples::get<2>(x);
Chris@16 911 path_count_type pc = boost::tuples::get<3>(x);
Chris@16 912
Chris@16 913 cache(dependency, source, dep);
Chris@16 914 cache(path_count, source, pc);
Chris@16 915
Chris@16 916 if (get(dependency_count, w) != 0)
Chris@16 917 put(dependency_count, w, get(dependency_count, w) - 1);
Chris@16 918
Chris@16 919 if (get(dependency_count, w) == 0) {
Chris@16 920
Chris@16 921 // Update dependency and centrality of sources of incoming edges
Chris@16 922 incoming_type el = get(incoming, w);
Chris@16 923 for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw) {
Chris@16 924 vertex_descriptor v = *vw;
Chris@16 925
Chris@16 926 BOOST_ASSERT(get(path_count, w) != 0);
Chris@16 927
Chris@16 928 dependency_type factor = dependency_type(get(path_count, v))
Chris@16 929 / dependency_type(get(path_count, w));
Chris@16 930 factor *= (dependency_type(1) + get(dependency, w));
Chris@16 931
Chris@16 932 if (get(owner, v) == id)
Chris@16 933 put(dependency, v, get(dependency, v) + factor);
Chris@16 934 else
Chris@16 935 put(dependency, v, factor);
Chris@16 936
Chris@16 937 update_centrality(edge_centrality_map, v, factor);
Chris@16 938 }
Chris@16 939
Chris@16 940 if (w != s)
Chris@16 941 update_centrality(centrality, w, get(dependency, w));
Chris@16 942
Chris@16 943 // Push sources of edges in incoming edge list
Chris@16 944 for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw)
Chris@16 945 Q.push(boost::make_tuple(*vw, w, get(dependency, w), get(path_count, w)));
Chris@16 946 }
Chris@16 947 }
Chris@16 948 }
Chris@16 949
Chris@16 950 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 951 typename IncomingMap, typename DistanceMap, typename DependencyMap,
Chris@16 952 typename PathCountMap, typename VertexIndexMap, typename ShortestPaths,
Chris@16 953 typename Buffer>
Chris@16 954 void
Chris@16 955 brandes_betweenness_centrality_impl(const Graph& g,
Chris@16 956 CentralityMap centrality,
Chris@16 957 EdgeCentralityMap edge_centrality_map,
Chris@16 958 IncomingMap incoming,
Chris@16 959 DistanceMap distance,
Chris@16 960 DependencyMap dependency,
Chris@16 961 PathCountMap path_count,
Chris@16 962 VertexIndexMap vertex_index,
Chris@16 963 ShortestPaths shortest_paths,
Chris@16 964 Buffer sources)
Chris@16 965 {
Chris@16 966 using boost::detail::graph::init_centrality_map;
Chris@16 967 using boost::detail::graph::divide_centrality_by_two;
Chris@16 968 using boost::graph::parallel::process_group;
Chris@16 969
Chris@16 970 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 971
Chris@16 972 typedef typename property_traits<DistanceMap>::value_type distance_type;
Chris@16 973 typedef typename property_traits<DependencyMap>::value_type dependency_type;
Chris@16 974
Chris@16 975 // Initialize centrality
Chris@16 976 init_centrality_map(vertices(g), centrality);
Chris@16 977 init_centrality_map(edges(g), edge_centrality_map);
Chris@16 978
Chris@16 979 // Set the reduction operation on the dependency map to be addition
Chris@16 980 dependency.set_reduce(boost::graph::distributed::additive_reducer<dependency_type>());
Chris@16 981 distance.set_reduce(boost::graph::distributed::choose_min_reducer<distance_type>());
Chris@16 982
Chris@16 983 // Don't allow remote procs to write incoming or path_count maps
Chris@16 984 // updating them is handled inside the betweenness_centrality_queue
Chris@16 985 incoming.set_consistency_model(0);
Chris@16 986 path_count.set_consistency_model(0);
Chris@16 987
Chris@16 988 typedef typename boost::graph::parallel::process_group_type<Graph>::type
Chris@16 989 process_group_type;
Chris@16 990 process_group_type pg = process_group(g);
Chris@16 991
Chris@16 992 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 993 // Build is_settled maps
Chris@16 994 std::vector<bool> is_settledS(num_vertices(g));
Chris@16 995 typedef iterator_property_map<std::vector<bool>::iterator, VertexIndexMap>
Chris@16 996 IsSettledMap;
Chris@16 997
Chris@16 998 IsSettledMap is_settled(is_settledS.begin(), vertex_index);
Chris@16 999 #endif
Chris@16 1000
Chris@16 1001 if (!sources.empty()) {
Chris@16 1002 // DO SSSPs
Chris@16 1003 while (!sources.empty()) {
Chris@16 1004 do_brandes_sssp(g, centrality, edge_centrality_map, incoming, distance,
Chris@16 1005 dependency, path_count,
Chris@16 1006 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 1007 is_settled,
Chris@16 1008 #endif
Chris@16 1009 vertex_index, shortest_paths, sources.top());
Chris@16 1010 sources.pop();
Chris@16 1011 }
Chris@16 1012 } else { // Exact Betweenness Centrality
Chris@16 1013 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
Chris@16 1014 vertices_size_type n = num_vertices(g);
Chris@16 1015 n = boost::parallel::all_reduce(pg, n, std::plus<vertices_size_type>());
Chris@16 1016
Chris@16 1017 for (vertices_size_type i = 0; i < n; ++i) {
Chris@16 1018 vertex_descriptor v = vertex(i, g);
Chris@16 1019
Chris@16 1020 do_brandes_sssp(g, centrality, edge_centrality_map, incoming, distance,
Chris@16 1021 dependency, path_count,
Chris@16 1022 #ifdef COMPUTE_PATH_COUNTS_INLINE
Chris@16 1023 is_settled,
Chris@16 1024 #endif
Chris@16 1025 vertex_index, shortest_paths, v);
Chris@16 1026 }
Chris@16 1027 }
Chris@16 1028
Chris@16 1029 typedef typename graph_traits<Graph>::directed_category directed_category;
Chris@16 1030 const bool is_undirected =
Chris@16 1031 is_convertible<directed_category*, undirected_tag*>::value;
Chris@16 1032 if (is_undirected) {
Chris@16 1033 divide_centrality_by_two(vertices(g), centrality);
Chris@16 1034 divide_centrality_by_two(edges(g), edge_centrality_map);
Chris@16 1035 }
Chris@16 1036 }
Chris@16 1037
Chris@16 1038 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1039 typename IncomingMap, typename DistanceMap, typename DependencyMap,
Chris@16 1040 typename PathCountMap, typename VertexIndexMap, typename ShortestPaths,
Chris@16 1041 typename Stack>
Chris@16 1042 void
Chris@16 1043 do_sequential_brandes_sssp(const Graph& g,
Chris@16 1044 CentralityMap centrality,
Chris@16 1045 EdgeCentralityMap edge_centrality_map,
Chris@16 1046 IncomingMap incoming,
Chris@16 1047 DistanceMap distance,
Chris@16 1048 DependencyMap dependency,
Chris@16 1049 PathCountMap path_count,
Chris@16 1050 VertexIndexMap vertex_index,
Chris@16 1051 ShortestPaths shortest_paths,
Chris@16 1052 Stack& ordered_vertices,
Chris@16 1053 typename graph_traits<Graph>::vertex_descriptor v)
Chris@16 1054 {
Chris@16 1055 using boost::detail::graph::update_centrality;
Chris@16 1056
Chris@16 1057 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 1058
Chris@16 1059 // Initialize for this iteration
Chris@16 1060 BGL_FORALL_VERTICES_T(w, g, Graph) {
Chris@16 1061 // put(path_count, w, 0);
Chris@16 1062 incoming[w].clear();
Chris@16 1063 put(dependency, w, 0);
Chris@16 1064 }
Chris@16 1065
Chris@16 1066 put(path_count, v, 1);
Chris@16 1067 incoming[v].clear();
Chris@16 1068
Chris@16 1069 // Execute the shortest paths algorithm. This will be either
Chris@16 1070 // Dijkstra's algorithm or a customized breadth-first search,
Chris@16 1071 // depending on whether the graph is weighted or unweighted.
Chris@16 1072 shortest_paths(g, v, ordered_vertices, incoming, distance,
Chris@16 1073 path_count, vertex_index);
Chris@16 1074
Chris@16 1075 while (!ordered_vertices.empty()) {
Chris@16 1076 vertex_descriptor w = ordered_vertices.top();
Chris@16 1077 ordered_vertices.pop();
Chris@16 1078
Chris@16 1079 typedef typename property_traits<IncomingMap>::value_type
Chris@16 1080 incoming_type;
Chris@16 1081 typedef typename incoming_type::iterator incoming_iterator;
Chris@16 1082 typedef typename property_traits<DependencyMap>::value_type
Chris@16 1083 dependency_type;
Chris@16 1084
Chris@16 1085 for (incoming_iterator vw = incoming[w].begin();
Chris@16 1086 vw != incoming[w].end(); ++vw) {
Chris@16 1087 vertex_descriptor v = source(*vw, g);
Chris@16 1088 dependency_type factor = dependency_type(get(path_count, v))
Chris@16 1089 / dependency_type(get(path_count, w));
Chris@16 1090 factor *= (dependency_type(1) + get(dependency, w));
Chris@16 1091 put(dependency, v, get(dependency, v) + factor);
Chris@16 1092 update_centrality(edge_centrality_map, *vw, factor);
Chris@16 1093 }
Chris@16 1094
Chris@16 1095 if (w != v) {
Chris@16 1096 update_centrality(centrality, w, get(dependency, w));
Chris@16 1097 }
Chris@16 1098 }
Chris@16 1099 }
Chris@16 1100
Chris@16 1101 // Betweenness Centrality variant that duplicates graph across processors
Chris@16 1102 // and parallizes SSSPs
Chris@16 1103 // This function expects a non-distributed graph and property-maps
Chris@16 1104 template<typename ProcessGroup, typename Graph,
Chris@16 1105 typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1106 typename IncomingMap, typename DistanceMap,
Chris@16 1107 typename DependencyMap, typename PathCountMap,
Chris@16 1108 typename VertexIndexMap, typename ShortestPaths,
Chris@16 1109 typename Buffer>
Chris@16 1110 void
Chris@16 1111 non_distributed_brandes_betweenness_centrality_impl(const ProcessGroup& pg,
Chris@16 1112 const Graph& g,
Chris@16 1113 CentralityMap centrality,
Chris@16 1114 EdgeCentralityMap edge_centrality_map,
Chris@16 1115 IncomingMap incoming, // P
Chris@16 1116 DistanceMap distance, // d
Chris@16 1117 DependencyMap dependency, // delta
Chris@16 1118 PathCountMap path_count, // sigma
Chris@16 1119 VertexIndexMap vertex_index,
Chris@16 1120 ShortestPaths shortest_paths,
Chris@16 1121 Buffer sources)
Chris@16 1122 {
Chris@16 1123 using boost::detail::graph::init_centrality_map;
Chris@16 1124 using boost::detail::graph::divide_centrality_by_two;
Chris@16 1125 using boost::graph::parallel::process_group;
Chris@16 1126
Chris@16 1127 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 1128
Chris@16 1129 typedef ProcessGroup process_group_type;
Chris@16 1130
Chris@16 1131 typename process_group_type::process_id_type id = process_id(pg);
Chris@16 1132 typename process_group_type::process_size_type p = num_processes(pg);
Chris@16 1133
Chris@16 1134 // Initialize centrality
Chris@16 1135 init_centrality_map(vertices(g), centrality);
Chris@16 1136 init_centrality_map(edges(g), edge_centrality_map);
Chris@16 1137
Chris@16 1138 std::stack<vertex_descriptor> ordered_vertices;
Chris@16 1139
Chris@16 1140 if (!sources.empty()) {
Chris@16 1141 std::vector<vertex_descriptor> local_sources;
Chris@16 1142
Chris@16 1143 for (int i = 0; i < id; ++i) if (!sources.empty()) sources.pop();
Chris@16 1144 while (!sources.empty()) {
Chris@16 1145 local_sources.push_back(sources.top());
Chris@16 1146
Chris@16 1147 for (int i = 0; i < p; ++i) if (!sources.empty()) sources.pop();
Chris@16 1148 }
Chris@16 1149
Chris@16 1150 // DO SSSPs
Chris@16 1151 for(size_t i = 0; i < local_sources.size(); ++i)
Chris@16 1152 do_sequential_brandes_sssp(g, centrality, edge_centrality_map, incoming,
Chris@16 1153 distance, dependency, path_count, vertex_index,
Chris@16 1154 shortest_paths, ordered_vertices, local_sources[i]);
Chris@16 1155
Chris@16 1156 } else { // Exact Betweenness Centrality
Chris@16 1157 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
Chris@16 1158 vertices_size_type n = num_vertices(g);
Chris@16 1159
Chris@16 1160 for (vertices_size_type i = id; i < n; i += p) {
Chris@16 1161 vertex_descriptor v = vertex(i, g);
Chris@16 1162
Chris@16 1163 do_sequential_brandes_sssp(g, centrality, edge_centrality_map, incoming,
Chris@16 1164 distance, dependency, path_count, vertex_index,
Chris@16 1165 shortest_paths, ordered_vertices, v);
Chris@16 1166 }
Chris@16 1167 }
Chris@16 1168
Chris@16 1169 typedef typename graph_traits<Graph>::directed_category directed_category;
Chris@16 1170 const bool is_undirected =
Chris@16 1171 is_convertible<directed_category*, undirected_tag*>::value;
Chris@16 1172 if (is_undirected) {
Chris@16 1173 divide_centrality_by_two(vertices(g), centrality);
Chris@16 1174 divide_centrality_by_two(edges(g), edge_centrality_map);
Chris@16 1175 }
Chris@16 1176
Chris@16 1177 // Merge the centrality maps by summing the values at each vertex)
Chris@16 1178 // TODO(nge): this copy-out, reduce, copy-in is lame
Chris@16 1179 typedef typename property_traits<CentralityMap>::value_type centrality_type;
Chris@16 1180 typedef typename property_traits<EdgeCentralityMap>::value_type edge_centrality_type;
Chris@16 1181
Chris@16 1182 std::vector<centrality_type> centrality_v(num_vertices(g));
Chris@16 1183 std::vector<edge_centrality_type> edge_centrality_v;
Chris@16 1184 edge_centrality_v.reserve(num_edges(g));
Chris@16 1185
Chris@16 1186 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 1187 centrality_v[get(vertex_index, v)] = get(centrality, v);
Chris@16 1188 }
Chris@16 1189
Chris@16 1190 // Skip when EdgeCentralityMap is a dummy_property_map
Chris@16 1191 if (!is_same<EdgeCentralityMap, dummy_property_map>::value) {
Chris@16 1192 BGL_FORALL_EDGES_T(e, g, Graph) {
Chris@16 1193 edge_centrality_v.push_back(get(edge_centrality_map, e));
Chris@16 1194 }
Chris@16 1195 // NGE: If we trust that the order of elements in the vector isn't changed in the
Chris@16 1196 // all_reduce below then this method avoids the need for an edge index map
Chris@16 1197 }
Chris@16 1198
Chris@16 1199 using boost::parallel::all_reduce;
Chris@16 1200
Chris@16 1201 all_reduce(pg, &centrality_v[0], &centrality_v[centrality_v.size()],
Chris@16 1202 &centrality_v[0], std::plus<centrality_type>());
Chris@16 1203
Chris@16 1204 if (edge_centrality_v.size())
Chris@16 1205 all_reduce(pg, &edge_centrality_v[0], &edge_centrality_v[edge_centrality_v.size()],
Chris@16 1206 &edge_centrality_v[0], std::plus<edge_centrality_type>());
Chris@16 1207
Chris@16 1208 BGL_FORALL_VERTICES_T(v, g, Graph) {
Chris@16 1209 put(centrality, v, centrality_v[get(vertex_index, v)]);
Chris@16 1210 }
Chris@16 1211
Chris@16 1212 // Skip when EdgeCentralityMap is a dummy_property_map
Chris@16 1213 if (!is_same<EdgeCentralityMap, dummy_property_map>::value) {
Chris@16 1214 int i = 0;
Chris@16 1215 BGL_FORALL_EDGES_T(e, g, Graph) {
Chris@16 1216 put(edge_centrality_map, e, edge_centrality_v[i]);
Chris@16 1217 ++i;
Chris@16 1218 }
Chris@16 1219 }
Chris@16 1220 }
Chris@16 1221
Chris@16 1222 } } } // end namespace graph::parallel::detail
Chris@16 1223
Chris@16 1224 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1225 typename IncomingMap, typename DistanceMap, typename DependencyMap,
Chris@16 1226 typename PathCountMap, typename VertexIndexMap, typename Buffer>
Chris@16 1227 void
Chris@16 1228 brandes_betweenness_centrality(const Graph& g,
Chris@16 1229 CentralityMap centrality,
Chris@16 1230 EdgeCentralityMap edge_centrality_map,
Chris@16 1231 IncomingMap incoming,
Chris@16 1232 DistanceMap distance,
Chris@16 1233 DependencyMap dependency,
Chris@16 1234 PathCountMap path_count,
Chris@16 1235 VertexIndexMap vertex_index,
Chris@16 1236 Buffer sources,
Chris@16 1237 typename property_traits<DistanceMap>::value_type delta
Chris@16 1238 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
Chris@16 1239 {
Chris@16 1240 typedef typename property_traits<DistanceMap>::value_type distance_type;
Chris@16 1241 typedef static_property_map<distance_type> WeightMap;
Chris@16 1242
Chris@16 1243 graph::parallel::detail::brandes_shortest_paths<WeightMap>
Chris@16 1244 shortest_paths(delta);
Chris@16 1245
Chris@16 1246 graph::parallel::detail::brandes_betweenness_centrality_impl(g, centrality,
Chris@16 1247 edge_centrality_map,
Chris@16 1248 incoming, distance,
Chris@16 1249 dependency, path_count,
Chris@16 1250 vertex_index,
Chris@16 1251 shortest_paths,
Chris@16 1252 sources);
Chris@16 1253 }
Chris@16 1254
Chris@16 1255 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1256 typename IncomingMap, typename DistanceMap, typename DependencyMap,
Chris@16 1257 typename PathCountMap, typename VertexIndexMap, typename WeightMap,
Chris@16 1258 typename Buffer>
Chris@16 1259 void
Chris@16 1260 brandes_betweenness_centrality(const Graph& g,
Chris@16 1261 CentralityMap centrality,
Chris@16 1262 EdgeCentralityMap edge_centrality_map,
Chris@16 1263 IncomingMap incoming,
Chris@16 1264 DistanceMap distance,
Chris@16 1265 DependencyMap dependency,
Chris@16 1266 PathCountMap path_count,
Chris@16 1267 VertexIndexMap vertex_index,
Chris@16 1268 Buffer sources,
Chris@16 1269 typename property_traits<WeightMap>::value_type delta,
Chris@16 1270 WeightMap weight_map
Chris@16 1271 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
Chris@16 1272 {
Chris@16 1273 graph::parallel::detail::brandes_shortest_paths<WeightMap> shortest_paths(weight_map, delta);
Chris@16 1274
Chris@16 1275 graph::parallel::detail::brandes_betweenness_centrality_impl(g, centrality,
Chris@16 1276 edge_centrality_map,
Chris@16 1277 incoming, distance,
Chris@16 1278 dependency, path_count,
Chris@16 1279 vertex_index,
Chris@16 1280 shortest_paths,
Chris@16 1281 sources);
Chris@16 1282 }
Chris@16 1283
Chris@16 1284 namespace graph { namespace parallel { namespace detail {
Chris@16 1285 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1286 typename WeightMap, typename VertexIndexMap, typename Buffer>
Chris@16 1287 void
Chris@16 1288 brandes_betweenness_centrality_dispatch2(const Graph& g,
Chris@16 1289 CentralityMap centrality,
Chris@16 1290 EdgeCentralityMap edge_centrality_map,
Chris@16 1291 WeightMap weight_map,
Chris@16 1292 VertexIndexMap vertex_index,
Chris@16 1293 Buffer sources,
Chris@16 1294 typename property_traits<WeightMap>::value_type delta)
Chris@16 1295 {
Chris@16 1296 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
Chris@16 1297 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 1298 typedef typename mpl::if_c<(is_same<CentralityMap,
Chris@16 1299 dummy_property_map>::value),
Chris@16 1300 EdgeCentralityMap,
Chris@16 1301 CentralityMap>::type a_centrality_map;
Chris@16 1302 typedef typename property_traits<a_centrality_map>::value_type
Chris@16 1303 centrality_type;
Chris@16 1304
Chris@16 1305 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
Chris@16 1306
Chris@16 1307 std::vector<std::vector<vertex_descriptor> > incoming(V);
Chris@16 1308 std::vector<centrality_type> distance(V);
Chris@16 1309 std::vector<centrality_type> dependency(V);
Chris@16 1310 std::vector<degree_size_type> path_count(V);
Chris@16 1311
Chris@16 1312 brandes_betweenness_centrality(
Chris@16 1313 g, centrality, edge_centrality_map,
Chris@16 1314 make_iterator_property_map(incoming.begin(), vertex_index),
Chris@16 1315 make_iterator_property_map(distance.begin(), vertex_index),
Chris@16 1316 make_iterator_property_map(dependency.begin(), vertex_index),
Chris@16 1317 make_iterator_property_map(path_count.begin(), vertex_index),
Chris@16 1318 vertex_index, unwrap_ref(sources), delta,
Chris@16 1319 weight_map);
Chris@16 1320 }
Chris@16 1321
Chris@16 1322 // TODO: Should the type of the distance and dependency map depend on the
Chris@16 1323 // value type of the centrality map?
Chris@16 1324 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1325 typename VertexIndexMap, typename Buffer>
Chris@16 1326 void
Chris@16 1327 brandes_betweenness_centrality_dispatch2(const Graph& g,
Chris@16 1328 CentralityMap centrality,
Chris@16 1329 EdgeCentralityMap edge_centrality_map,
Chris@16 1330 VertexIndexMap vertex_index,
Chris@16 1331 Buffer sources,
Chris@16 1332 typename graph_traits<Graph>::edges_size_type delta)
Chris@16 1333 {
Chris@16 1334 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
Chris@16 1335 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
Chris@16 1336 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 1337
Chris@16 1338 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
Chris@16 1339
Chris@16 1340 std::vector<std::vector<vertex_descriptor> > incoming(V);
Chris@16 1341 std::vector<edges_size_type> distance(V);
Chris@16 1342 std::vector<edges_size_type> dependency(V);
Chris@16 1343 std::vector<degree_size_type> path_count(V);
Chris@16 1344
Chris@16 1345 brandes_betweenness_centrality(
Chris@16 1346 g, centrality, edge_centrality_map,
Chris@16 1347 make_iterator_property_map(incoming.begin(), vertex_index),
Chris@16 1348 make_iterator_property_map(distance.begin(), vertex_index),
Chris@16 1349 make_iterator_property_map(dependency.begin(), vertex_index),
Chris@16 1350 make_iterator_property_map(path_count.begin(), vertex_index),
Chris@16 1351 vertex_index, unwrap_ref(sources), delta);
Chris@16 1352 }
Chris@16 1353
Chris@16 1354 template<typename WeightMap>
Chris@16 1355 struct brandes_betweenness_centrality_dispatch1
Chris@16 1356 {
Chris@16 1357 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1358 typename VertexIndexMap, typename Buffer>
Chris@16 1359 static void
Chris@16 1360 run(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map,
Chris@16 1361 VertexIndexMap vertex_index, Buffer sources,
Chris@16 1362 typename property_traits<WeightMap>::value_type delta, WeightMap weight_map)
Chris@16 1363 {
Chris@16 1364 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
Chris@16 1365 g, centrality, edge_centrality_map, weight_map, vertex_index, sources, delta);
Chris@16 1366 }
Chris@16 1367 };
Chris@16 1368
Chris@16 1369 template<>
Chris@16 1370 struct brandes_betweenness_centrality_dispatch1<boost::param_not_found>
Chris@16 1371 {
Chris@16 1372 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
Chris@16 1373 typename VertexIndexMap, typename Buffer>
Chris@16 1374 static void
Chris@16 1375 run(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map,
Chris@16 1376 VertexIndexMap vertex_index, Buffer sources,
Chris@16 1377 typename graph_traits<Graph>::edges_size_type delta,
Chris@16 1378 boost::param_not_found)
Chris@16 1379 {
Chris@16 1380 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
Chris@16 1381 g, centrality, edge_centrality_map, vertex_index, sources, delta);
Chris@16 1382 }
Chris@16 1383 };
Chris@16 1384
Chris@16 1385 } } } // end namespace graph::parallel::detail
Chris@16 1386
Chris@16 1387 template<typename Graph, typename Param, typename Tag, typename Rest>
Chris@16 1388 void
Chris@16 1389 brandes_betweenness_centrality(const Graph& g,
Chris@16 1390 const bgl_named_params<Param,Tag,Rest>& params
Chris@16 1391 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
Chris@16 1392 {
Chris@16 1393 typedef bgl_named_params<Param,Tag,Rest> named_params;
Chris@16 1394
Chris@16 1395 typedef queue<typename graph_traits<Graph>::vertex_descriptor> queue_t;
Chris@16 1396 queue_t q;
Chris@16 1397
Chris@16 1398 typedef typename get_param_type<edge_weight_t, named_params>::type ew_param;
Chris@16 1399 typedef typename detail::choose_impl_result<mpl::true_, Graph, ew_param, edge_weight_t>::type ew;
Chris@16 1400 graph::parallel::detail::brandes_betweenness_centrality_dispatch1<ew>::run(
Chris@16 1401 g,
Chris@16 1402 choose_param(get_param(params, vertex_centrality),
Chris@16 1403 dummy_property_map()),
Chris@16 1404 choose_param(get_param(params, edge_centrality),
Chris@16 1405 dummy_property_map()),
Chris@16 1406 choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
Chris@16 1407 choose_param(get_param(params, buffer_param_t()), boost::ref(q)),
Chris@16 1408 choose_param(get_param(params, lookahead_t()), 0),
Chris@16 1409 choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
Chris@16 1410 }
Chris@16 1411
Chris@16 1412 template<typename Graph, typename CentralityMap>
Chris@16 1413 void
Chris@16 1414 brandes_betweenness_centrality(const Graph& g, CentralityMap centrality
Chris@16 1415 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
Chris@16 1416 {
Chris@16 1417 typedef queue<typename graph_traits<Graph>::vertex_descriptor> queue_t;
Chris@16 1418 queue_t q;
Chris@16 1419
Chris@16 1420 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
Chris@16 1421 g, centrality, dummy_property_map(), get(vertex_index, g), boost::ref(q), 0);
Chris@16 1422 }
Chris@16 1423
Chris@16 1424 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap>
Chris@16 1425 void
Chris@16 1426 brandes_betweenness_centrality(const Graph& g, CentralityMap centrality,
Chris@16 1427 EdgeCentralityMap edge_centrality_map
Chris@16 1428 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
Chris@16 1429 {
Chris@16 1430 typedef queue<int> queue_t;
Chris@16 1431 queue_t q;
Chris@16 1432
Chris@16 1433 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
Chris@16 1434 g, centrality, edge_centrality_map, get(vertex_index, g), boost::ref(q), 0);
Chris@16 1435 }
Chris@16 1436
Chris@16 1437 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1438 typename EdgeCentralityMap, typename IncomingMap, typename DistanceMap,
Chris@16 1439 typename DependencyMap, typename PathCountMap, typename VertexIndexMap,
Chris@16 1440 typename Buffer>
Chris@16 1441 void
Chris@16 1442 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg,
Chris@16 1443 const Graph& g,
Chris@16 1444 CentralityMap centrality,
Chris@16 1445 EdgeCentralityMap edge_centrality_map,
Chris@16 1446 IncomingMap incoming,
Chris@16 1447 DistanceMap distance,
Chris@16 1448 DependencyMap dependency,
Chris@16 1449 PathCountMap path_count,
Chris@16 1450 VertexIndexMap vertex_index,
Chris@16 1451 Buffer sources)
Chris@16 1452 {
Chris@16 1453 detail::graph::brandes_unweighted_shortest_paths shortest_paths;
Chris@16 1454
Chris@16 1455 graph::parallel::detail::non_distributed_brandes_betweenness_centrality_impl(pg, g, centrality,
Chris@16 1456 edge_centrality_map,
Chris@16 1457 incoming, distance,
Chris@16 1458 dependency, path_count,
Chris@16 1459 vertex_index,
Chris@16 1460 shortest_paths,
Chris@16 1461 sources);
Chris@16 1462 }
Chris@16 1463
Chris@16 1464 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1465 typename EdgeCentralityMap, typename IncomingMap, typename DistanceMap,
Chris@16 1466 typename DependencyMap, typename PathCountMap, typename VertexIndexMap,
Chris@16 1467 typename WeightMap, typename Buffer>
Chris@16 1468 void
Chris@16 1469 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg,
Chris@16 1470 const Graph& g,
Chris@16 1471 CentralityMap centrality,
Chris@16 1472 EdgeCentralityMap edge_centrality_map,
Chris@16 1473 IncomingMap incoming,
Chris@16 1474 DistanceMap distance,
Chris@16 1475 DependencyMap dependency,
Chris@16 1476 PathCountMap path_count,
Chris@16 1477 VertexIndexMap vertex_index,
Chris@16 1478 WeightMap weight_map,
Chris@16 1479 Buffer sources)
Chris@16 1480 {
Chris@16 1481 detail::graph::brandes_dijkstra_shortest_paths<WeightMap> shortest_paths(weight_map);
Chris@16 1482
Chris@16 1483 graph::parallel::detail::non_distributed_brandes_betweenness_centrality_impl(pg, g, centrality,
Chris@16 1484 edge_centrality_map,
Chris@16 1485 incoming, distance,
Chris@16 1486 dependency, path_count,
Chris@16 1487 vertex_index,
Chris@16 1488 shortest_paths,
Chris@16 1489 sources);
Chris@16 1490 }
Chris@16 1491
Chris@16 1492 namespace detail { namespace graph {
Chris@16 1493 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1494 typename EdgeCentralityMap, typename WeightMap, typename VertexIndexMap,
Chris@16 1495 typename Buffer>
Chris@16 1496 void
Chris@16 1497 non_distributed_brandes_betweenness_centrality_dispatch2(const ProcessGroup& pg,
Chris@16 1498 const Graph& g,
Chris@16 1499 CentralityMap centrality,
Chris@16 1500 EdgeCentralityMap edge_centrality_map,
Chris@16 1501 WeightMap weight_map,
Chris@16 1502 VertexIndexMap vertex_index,
Chris@16 1503 Buffer sources)
Chris@16 1504 {
Chris@16 1505 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
Chris@16 1506 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
Chris@16 1507 typedef typename mpl::if_c<(is_same<CentralityMap,
Chris@16 1508 dummy_property_map>::value),
Chris@16 1509 EdgeCentralityMap,
Chris@16 1510 CentralityMap>::type a_centrality_map;
Chris@16 1511 typedef typename property_traits<a_centrality_map>::value_type
Chris@16 1512 centrality_type;
Chris@16 1513
Chris@16 1514 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
Chris@16 1515
Chris@16 1516 std::vector<std::vector<edge_descriptor> > incoming(V);
Chris@16 1517 std::vector<centrality_type> distance(V);
Chris@16 1518 std::vector<centrality_type> dependency(V);
Chris@16 1519 std::vector<degree_size_type> path_count(V);
Chris@16 1520
Chris@16 1521 non_distributed_brandes_betweenness_centrality(
Chris@16 1522 pg, g, centrality, edge_centrality_map,
Chris@16 1523 make_iterator_property_map(incoming.begin(), vertex_index),
Chris@16 1524 make_iterator_property_map(distance.begin(), vertex_index),
Chris@16 1525 make_iterator_property_map(dependency.begin(), vertex_index),
Chris@16 1526 make_iterator_property_map(path_count.begin(), vertex_index),
Chris@16 1527 vertex_index, weight_map, unwrap_ref(sources));
Chris@16 1528 }
Chris@16 1529
Chris@16 1530
Chris@16 1531 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1532 typename EdgeCentralityMap, typename VertexIndexMap, typename Buffer>
Chris@16 1533 void
Chris@16 1534 non_distributed_brandes_betweenness_centrality_dispatch2(const ProcessGroup& pg,
Chris@16 1535 const Graph& g,
Chris@16 1536 CentralityMap centrality,
Chris@16 1537 EdgeCentralityMap edge_centrality_map,
Chris@16 1538 VertexIndexMap vertex_index,
Chris@16 1539 Buffer sources)
Chris@16 1540 {
Chris@16 1541 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
Chris@16 1542 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
Chris@16 1543 typedef typename mpl::if_c<(is_same<CentralityMap,
Chris@16 1544 dummy_property_map>::value),
Chris@16 1545 EdgeCentralityMap,
Chris@16 1546 CentralityMap>::type a_centrality_map;
Chris@16 1547 typedef typename property_traits<a_centrality_map>::value_type
Chris@16 1548 centrality_type;
Chris@16 1549
Chris@16 1550 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
Chris@16 1551
Chris@16 1552 std::vector<std::vector<edge_descriptor> > incoming(V);
Chris@16 1553 std::vector<centrality_type> distance(V);
Chris@16 1554 std::vector<centrality_type> dependency(V);
Chris@16 1555 std::vector<degree_size_type> path_count(V);
Chris@16 1556
Chris@16 1557 non_distributed_brandes_betweenness_centrality(
Chris@16 1558 pg, g, centrality, edge_centrality_map,
Chris@16 1559 make_iterator_property_map(incoming.begin(), vertex_index),
Chris@16 1560 make_iterator_property_map(distance.begin(), vertex_index),
Chris@16 1561 make_iterator_property_map(dependency.begin(), vertex_index),
Chris@16 1562 make_iterator_property_map(path_count.begin(), vertex_index),
Chris@16 1563 vertex_index, unwrap_ref(sources));
Chris@16 1564 }
Chris@16 1565
Chris@16 1566 template<typename WeightMap>
Chris@16 1567 struct non_distributed_brandes_betweenness_centrality_dispatch1
Chris@16 1568 {
Chris@16 1569 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1570 typename EdgeCentralityMap, typename VertexIndexMap, typename Buffer>
Chris@16 1571 static void
Chris@16 1572 run(const ProcessGroup& pg, const Graph& g, CentralityMap centrality,
Chris@16 1573 EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
Chris@16 1574 Buffer sources, WeightMap weight_map)
Chris@16 1575 {
Chris@16 1576 non_distributed_brandes_betweenness_centrality_dispatch2(pg, g, centrality, edge_centrality_map,
Chris@16 1577 weight_map, vertex_index, sources);
Chris@16 1578 }
Chris@16 1579 };
Chris@16 1580
Chris@16 1581 template<>
Chris@16 1582 struct non_distributed_brandes_betweenness_centrality_dispatch1<param_not_found>
Chris@16 1583 {
Chris@16 1584 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1585 typename EdgeCentralityMap, typename VertexIndexMap, typename Buffer>
Chris@16 1586 static void
Chris@16 1587 run(const ProcessGroup& pg, const Graph& g, CentralityMap centrality,
Chris@16 1588 EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
Chris@16 1589 Buffer sources, param_not_found)
Chris@16 1590 {
Chris@16 1591 non_distributed_brandes_betweenness_centrality_dispatch2(pg, g, centrality, edge_centrality_map,
Chris@16 1592 vertex_index, sources);
Chris@16 1593 }
Chris@16 1594 };
Chris@16 1595
Chris@16 1596 } } // end namespace detail::graph
Chris@16 1597
Chris@16 1598 template<typename ProcessGroup, typename Graph, typename Param, typename Tag, typename Rest>
Chris@16 1599 void
Chris@16 1600 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
Chris@16 1601 const bgl_named_params<Param,Tag,Rest>& params)
Chris@16 1602 {
Chris@16 1603 typedef bgl_named_params<Param,Tag,Rest> named_params;
Chris@16 1604
Chris@16 1605 typedef queue<int> queue_t;
Chris@16 1606 queue_t q;
Chris@16 1607
Chris@16 1608 typedef typename get_param_type<edge_weight_t, named_params>::type ew_param;
Chris@16 1609 typedef typename detail::choose_impl_result<mpl::true_, Graph, ew_param, edge_weight_t>::type ew;
Chris@16 1610 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch1<ew>::run(
Chris@16 1611 pg, g,
Chris@16 1612 choose_param(get_param(params, vertex_centrality),
Chris@16 1613 dummy_property_map()),
Chris@16 1614 choose_param(get_param(params, edge_centrality),
Chris@16 1615 dummy_property_map()),
Chris@16 1616 choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
Chris@16 1617 choose_param(get_param(params, buffer_param_t()), boost::ref(q)),
Chris@16 1618 choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
Chris@16 1619 }
Chris@16 1620
Chris@16 1621 template<typename ProcessGroup, typename Graph, typename CentralityMap>
Chris@16 1622 void
Chris@16 1623 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
Chris@16 1624 CentralityMap centrality)
Chris@16 1625 {
Chris@16 1626 typedef queue<int> queue_t;
Chris@16 1627 queue_t q;
Chris@16 1628
Chris@16 1629 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch2(
Chris@16 1630 pg, g, centrality, dummy_property_map(), get(vertex_index, g), boost::ref(q));
Chris@16 1631 }
Chris@16 1632
Chris@16 1633 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1634 typename Buffer>
Chris@16 1635 void
Chris@16 1636 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
Chris@16 1637 CentralityMap centrality, Buffer sources)
Chris@16 1638 {
Chris@16 1639 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch2(
Chris@16 1640 pg, g, centrality, dummy_property_map(), get(vertex_index, g), sources);
Chris@16 1641 }
Chris@16 1642
Chris@16 1643 template<typename ProcessGroup, typename Graph, typename CentralityMap,
Chris@16 1644 typename EdgeCentralityMap, typename Buffer>
Chris@16 1645 void
Chris@16 1646 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
Chris@16 1647 CentralityMap centrality,
Chris@16 1648 EdgeCentralityMap edge_centrality_map,
Chris@16 1649 Buffer sources)
Chris@16 1650 {
Chris@16 1651 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch2(
Chris@16 1652 pg, g, centrality, edge_centrality_map, get(vertex_index, g), sources);
Chris@16 1653 }
Chris@16 1654
Chris@16 1655 // Compute the central point dominance of a graph.
Chris@16 1656 // TODO: Make sure central point dominance works in parallel case
Chris@16 1657 template<typename Graph, typename CentralityMap>
Chris@16 1658 typename property_traits<CentralityMap>::value_type
Chris@16 1659 central_point_dominance(const Graph& g, CentralityMap centrality
Chris@16 1660 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
Chris@16 1661 {
Chris@16 1662 using std::max;
Chris@16 1663
Chris@16 1664 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
Chris@16 1665 typedef typename property_traits<CentralityMap>::value_type centrality_type;
Chris@16 1666 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
Chris@16 1667
Chris@16 1668 typedef typename boost::graph::parallel::process_group_type<Graph>::type
Chris@16 1669 process_group_type;
Chris@16 1670 process_group_type pg = boost::graph::parallel::process_group(g);
Chris@16 1671
Chris@16 1672 vertices_size_type n = num_vertices(g);
Chris@16 1673
Chris@16 1674 using boost::parallel::all_reduce;
Chris@16 1675 n = all_reduce(pg, n, std::plus<vertices_size_type>());
Chris@16 1676
Chris@16 1677 // Find max centrality
Chris@16 1678 centrality_type max_centrality(0);
Chris@16 1679 vertex_iterator v, v_end;
Chris@16 1680 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) {
Chris@16 1681 max_centrality = (max)(max_centrality, get(centrality, *v));
Chris@16 1682 }
Chris@16 1683
Chris@16 1684 // All reduce to get global max centrality
Chris@16 1685 max_centrality = all_reduce(pg, max_centrality, boost::parallel::maximum<centrality_type>());
Chris@16 1686
Chris@16 1687 // Compute central point dominance
Chris@16 1688 centrality_type sum(0);
Chris@16 1689 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) {
Chris@16 1690 sum += (max_centrality - get(centrality, *v));
Chris@16 1691 }
Chris@16 1692
Chris@16 1693 sum = all_reduce(pg, sum, std::plus<centrality_type>());
Chris@16 1694
Chris@16 1695 return sum/(n-1);
Chris@16 1696 }
Chris@16 1697
Chris@16 1698 } // end namespace boost
Chris@16 1699
Chris@16 1700 #endif // BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP