File indexing completed on 2025-01-30 09:42:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP
0010 #define BOOST_GRAPH_PARALLEL_BRANDES_BETWEENNESS_CENTRALITY_HPP
0011
0012 #ifndef BOOST_GRAPH_USE_MPI
0013 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0014 #endif
0015
0016
0017
0018 #include <boost/graph/betweenness_centrality.hpp>
0019 #include <boost/graph/overloading.hpp>
0020 #include <boost/graph/distributed/concepts.hpp>
0021 #include <boost/graph/graph_traits.hpp>
0022 #include <boost/config.hpp>
0023 #include <boost/assert.hpp>
0024
0025
0026 #include <boost/graph/distributed/distributed_graph_utility.hpp>
0027 #include <boost/type_traits/is_convertible.hpp>
0028 #include <boost/type_traits/is_same.hpp>
0029 #include <boost/property_map/property_map.hpp>
0030 #include <boost/graph/named_function_params.hpp>
0031
0032 #include <boost/property_map/parallel/distributed_property_map.hpp>
0033 #include <boost/graph/distributed/detail/dijkstra_shortest_paths.hpp>
0034 #include <boost/tuple/tuple.hpp>
0035
0036
0037
0038 #include <boost/random/linear_congruential.hpp>
0039
0040 #include <algorithm>
0041 #include <stack>
0042 #include <vector>
0043
0044
0045 template <typename T>
0046 struct append_reducer {
0047 BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
0048
0049 template<typename K>
0050 T operator()(const K&) const { return T(); }
0051
0052 template<typename K>
0053 T operator()(const K&, const T& x, const T& y) const
0054 {
0055 T z(x.begin(), x.end());
0056 for (typename T::const_iterator iter = y.begin(); iter != y.end(); ++iter)
0057 if (std::find(z.begin(), z.end(), *iter) == z.end())
0058 z.push_back(*iter);
0059
0060 return z;
0061 }
0062 };
0063
0064 namespace boost {
0065
0066 namespace serialization {
0067
0068
0069 template<typename Archive, typename T1, typename T2, typename T3,
0070 typename T4>
0071 void serialize(Archive & ar,
0072 boost::tuple<T1,T2,T3, T4>& t,
0073 const unsigned int)
0074 {
0075 ar & boost::tuples::get<0>(t);
0076 ar & boost::tuples::get<1>(t);
0077 ar & boost::tuples::get<2>(t);
0078 ar & boost::tuples::get<3>(t);
0079 }
0080
0081 }
0082
0083 template <typename OwnerMap, typename Tuple>
0084 class get_owner_of_first_tuple_element {
0085
0086 public:
0087 typedef typename property_traits<OwnerMap>::value_type owner_type;
0088
0089 get_owner_of_first_tuple_element(OwnerMap owner) : owner(owner) { }
0090
0091 owner_type get_owner(Tuple t) { return get(owner, boost::tuples::get<0>(t)); }
0092
0093 private:
0094 OwnerMap owner;
0095 };
0096
0097 template <typename OwnerMap, typename Tuple>
0098 typename get_owner_of_first_tuple_element<OwnerMap, Tuple>::owner_type
0099 get(get_owner_of_first_tuple_element<OwnerMap, Tuple> o, Tuple t)
0100 { return o.get_owner(t); }
0101
0102 template <typename OwnerMap>
0103 class get_owner_of_first_pair_element {
0104
0105 public:
0106 typedef typename property_traits<OwnerMap>::value_type owner_type;
0107
0108 get_owner_of_first_pair_element(OwnerMap owner) : owner(owner) { }
0109
0110 template <typename Vertex, typename T>
0111 owner_type get_owner(std::pair<Vertex, T> p) { return get(owner, p.first); }
0112
0113 private:
0114 OwnerMap owner;
0115 };
0116
0117 template <typename OwnerMap, typename Vertex, typename T>
0118 typename get_owner_of_first_pair_element<OwnerMap>::owner_type
0119 get(get_owner_of_first_pair_element<OwnerMap> o, std::pair<Vertex, T> p)
0120 { return o.get_owner(p); }
0121
0122 namespace graph { namespace parallel { namespace detail {
0123
0124 template<typename DistanceMap, typename IncomingMap>
0125 class betweenness_centrality_msg_value
0126 {
0127 typedef typename property_traits<DistanceMap>::value_type distance_type;
0128 typedef typename property_traits<IncomingMap>::value_type incoming_type;
0129 typedef typename incoming_type::value_type incoming_value_type;
0130
0131 public:
0132 typedef std::pair<distance_type, incoming_value_type> type;
0133
0134 static type create(distance_type dist, incoming_value_type source)
0135 { return std::make_pair(dist, source); }
0136 };
0137
0138
0139
0140
0141
0142
0143 template<typename Graph, typename DistanceMap, typename IncomingMap,
0144 typename EdgeWeightMap, typename PathCountMap
0145 #ifdef COMPUTE_PATH_COUNTS_INLINE
0146 , typename IsSettledMap, typename VertexIndexMap
0147 #endif
0148 >
0149 class betweenness_centrality_delta_stepping_impl {
0150
0151
0152
0153 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0154 typedef typename graph_traits<Graph>::degree_size_type Degree;
0155 typedef typename property_traits<EdgeWeightMap>::value_type Dist;
0156 typedef typename property_traits<IncomingMap>::value_type IncomingType;
0157 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0158 ProcessGroup;
0159
0160 typedef std::list<Vertex> Bucket;
0161 typedef typename Bucket::iterator BucketIterator;
0162 typedef typename std::vector<Bucket*>::size_type BucketIndex;
0163
0164 typedef betweenness_centrality_msg_value<DistanceMap, IncomingMap>
0165 MessageValue;
0166
0167 enum {
0168
0169
0170
0171
0172
0173 msg_relax
0174 };
0175
0176 public:
0177
0178
0179 betweenness_centrality_delta_stepping_impl(const Graph& g,
0180 DistanceMap distance,
0181 IncomingMap incoming,
0182 EdgeWeightMap weight,
0183 PathCountMap path_count,
0184 #ifdef COMPUTE_PATH_COUNTS_INLINE
0185 IsSettledMap is_settled,
0186 VertexIndexMap vertex_index,
0187 #endif
0188 Dist delta);
0189
0190 void run(Vertex s);
0191
0192 private:
0193
0194 void relax(Vertex u, Vertex v, Dist x);
0195
0196
0197
0198 void synchronize()
0199 {
0200 using boost::parallel::synchronize;
0201 synchronize(pg);
0202 }
0203
0204
0205 void setup_triggers()
0206 {
0207 using boost::parallel::simple_trigger;
0208 simple_trigger(pg, msg_relax, this,
0209 &betweenness_centrality_delta_stepping_impl::handle_msg_relax);
0210 }
0211
0212 void handle_msg_relax(int , int ,
0213 const std::pair<Vertex, typename MessageValue::type>& data,
0214 boost::parallel::trigger_receive_context)
0215 { relax(data.second.second, data.first, data.second.first); }
0216
0217 const Graph& g;
0218 IncomingMap incoming;
0219 DistanceMap distance;
0220 EdgeWeightMap weight;
0221 PathCountMap path_count;
0222 #ifdef COMPUTE_PATH_COUNTS_INLINE
0223 IsSettledMap is_settled;
0224 VertexIndexMap vertex_index;
0225 #endif
0226 Dist delta;
0227 ProcessGroup pg;
0228 typename property_map<Graph, vertex_owner_t>::const_type owner;
0229 typename property_map<Graph, vertex_local_t>::const_type local;
0230
0231
0232
0233 std::vector<BucketIterator> position_in_bucket;
0234
0235
0236
0237
0238 std::vector<Bucket*> buckets;
0239
0240
0241
0242
0243
0244
0245 std::list<Vertex> dummy_list;
0246
0247
0248
0249 std::vector<bool> vertex_was_deleted;
0250 };
0251
0252 template<typename Graph, typename DistanceMap, typename IncomingMap,
0253 typename EdgeWeightMap, typename PathCountMap
0254 #ifdef COMPUTE_PATH_COUNTS_INLINE
0255 , typename IsSettledMap, typename VertexIndexMap
0256 #endif
0257 >
0258 betweenness_centrality_delta_stepping_impl<
0259 Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
0260 #ifdef COMPUTE_PATH_COUNTS_INLINE
0261 , IsSettledMap, VertexIndexMap
0262 #endif
0263 >::
0264 betweenness_centrality_delta_stepping_impl(const Graph& g,
0265 DistanceMap distance,
0266 IncomingMap incoming,
0267 EdgeWeightMap weight,
0268 PathCountMap path_count,
0269 #ifdef COMPUTE_PATH_COUNTS_INLINE
0270 IsSettledMap is_settled,
0271 VertexIndexMap vertex_index,
0272 #endif
0273 Dist delta)
0274 : g(g),
0275 incoming(incoming),
0276 distance(distance),
0277 weight(weight),
0278 path_count(path_count),
0279 #ifdef COMPUTE_PATH_COUNTS_INLINE
0280 is_settled(is_settled),
0281 vertex_index(vertex_index),
0282 #endif
0283 delta(delta),
0284 pg(boost::graph::parallel::process_group_adl(g), boost::parallel::attach_distributed_object()),
0285 owner(get(vertex_owner, g)),
0286 local(get(vertex_local, g))
0287
0288 { setup_triggers(); }
0289
0290 template<typename Graph, typename DistanceMap, typename IncomingMap,
0291 typename EdgeWeightMap, typename PathCountMap
0292 #ifdef COMPUTE_PATH_COUNTS_INLINE
0293 , typename IsSettledMap, typename VertexIndexMap
0294 #endif
0295 >
0296 void
0297 betweenness_centrality_delta_stepping_impl<
0298 Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
0299 #ifdef COMPUTE_PATH_COUNTS_INLINE
0300 , IsSettledMap, VertexIndexMap
0301 #endif
0302 >::
0303 run(Vertex s)
0304 {
0305 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0306 process_group_type;
0307 typename process_group_type::process_id_type id = process_id(pg);
0308
0309 Dist inf = (std::numeric_limits<Dist>::max)();
0310
0311
0312 position_in_bucket.clear();
0313 position_in_bucket.resize(num_vertices(g), dummy_list.end());
0314
0315
0316 vertex_was_deleted.clear();
0317 vertex_was_deleted.resize(num_vertices(g), false);
0318
0319
0320 BGL_FORALL_VERTICES_T(v, g, Graph)
0321 put(distance, v, inf);
0322
0323
0324 if (get(owner, s) == id)
0325
0326 relax(s, s, 0);
0327 else
0328
0329 cache(distance, s, 0);
0330
0331 #ifdef COMPUTE_PATH_COUNTS_INLINE
0332
0333
0334 synchronize();
0335
0336
0337
0338 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
0339
0340 std::vector<edges_size_type> incoming_edge_countS(num_vertices(g));
0341 iterator_property_map<typename std::vector<edges_size_type>::iterator, VertexIndexMap>
0342 incoming_edge_count(incoming_edge_countS.begin(), vertex_index);
0343 #endif
0344
0345 BucketIndex max_bucket = (std::numeric_limits<BucketIndex>::max)();
0346 BucketIndex current_bucket = 0;
0347 do {
0348 #ifdef COMPUTE_PATH_COUNTS_INLINE
0349
0350 std::vector<IncomingType> outgoingS(num_vertices(g));
0351 IncomingMap outgoing(outgoingS.begin(), vertex_index);
0352
0353 outgoing.set_reduce(append_reducer<IncomingType>());
0354 #else
0355
0356 synchronize();
0357 #endif
0358
0359
0360 while (current_bucket < buckets.size()
0361 && (!buckets[current_bucket] || buckets[current_bucket]->empty()))
0362 ++current_bucket;
0363 if (current_bucket >= buckets.size())
0364 current_bucket = max_bucket;
0365
0366
0367
0368 using boost::parallel::all_reduce;
0369 using boost::parallel::minimum;
0370 current_bucket = all_reduce(pg, current_bucket, minimum<BucketIndex>());
0371
0372 if (current_bucket == max_bucket)
0373
0374 break;
0375
0376
0377
0378
0379
0380 std::vector<Vertex> deleted_vertices;
0381
0382
0383 bool nonempty_bucket;
0384 do {
0385
0386
0387 if (current_bucket < buckets.size() && buckets[current_bucket]) {
0388 Bucket& bucket = *buckets[current_bucket];
0389
0390 while (!bucket.empty()) {
0391 Vertex u = bucket.front();
0392
0393
0394 bucket.pop_front();
0395
0396
0397
0398 if (!vertex_was_deleted[get(local, u)]) {
0399 vertex_was_deleted[get(local, u)] = true;
0400 deleted_vertices.push_back(u);
0401 }
0402
0403
0404 Dist u_dist = get(distance, u);
0405 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
0406 if (get(weight, e) <= delta)
0407 relax(u, target(e, g), u_dist + get(weight, e));
0408 }
0409 }
0410
0411
0412 synchronize();
0413
0414
0415 nonempty_bucket = (current_bucket < buckets.size()
0416 && buckets[current_bucket]
0417 && !buckets[current_bucket]->empty());
0418 } while (all_reduce(pg, nonempty_bucket, std::logical_or<bool>()));
0419
0420
0421
0422 for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
0423 iter != deleted_vertices.end(); ++iter) {
0424
0425 Vertex u = *iter;
0426 Dist u_dist = get(distance, u);
0427 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
0428 if (get(weight, e) > delta)
0429 relax(u, target(e, g), u_dist + get(weight, e));
0430
0431 #ifdef COMPUTE_PATH_COUNTS_INLINE
0432
0433 IncomingType in = get(incoming, u);
0434 for (typename IncomingType::iterator pred = in.begin(); pred != in.end(); ++pred)
0435 if (get(owner, *pred) == id) {
0436 IncomingType x = get(outgoing, *pred);
0437 if (std::find(x.begin(), x.end(), u) == x.end())
0438 x.push_back(u);
0439 put(outgoing, *pred, x);
0440 } else {
0441 IncomingType in;
0442 in.push_back(u);
0443 put(outgoing, *pred, in);
0444 }
0445
0446
0447 put(incoming_edge_count, u, in.size());
0448 #endif
0449 }
0450
0451 #ifdef COMPUTE_PATH_COUNTS_INLINE
0452 synchronize();
0453
0454
0455 typedef typename property_traits<PathCountMap>::value_type PathCountType;
0456 typedef std::pair<Vertex, PathCountType> queue_value_type;
0457 typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
0458 typedef typename get_owner_of_first_pair_element<OwnerMap> IndirectOwnerMap;
0459
0460 typedef boost::queue<queue_value_type> local_queue_type;
0461 typedef boost::graph::distributed::distributed_queue<process_group_type,
0462 IndirectOwnerMap,
0463 local_queue_type> dist_queue_type;
0464
0465 IndirectOwnerMap indirect_owner(owner);
0466 dist_queue_type Q(pg, indirect_owner);
0467
0468
0469 BGL_FORALL_VERTICES_T(v, g, Graph) {
0470 if (get(is_settled, v) && !(get(outgoing, v).empty())) {
0471 put(incoming_edge_count, v, 1);
0472 Q.push(std::make_pair(v, 0));
0473 }
0474 }
0475
0476
0477 while (!Q.empty()) {
0478 queue_value_type t = Q.top(); Q.pop();
0479 Vertex v = t.first;
0480 PathCountType p = t.second;
0481
0482 put(path_count, v, get(path_count, v) + p);
0483 put(incoming_edge_count, v, get(incoming_edge_count, v) - 1);
0484
0485 if (get(incoming_edge_count, v) == 0) {
0486 IncomingType out = get(outgoing, v);
0487 for (typename IncomingType::iterator iter = out.begin(); iter != out.end(); ++iter)
0488 Q.push(std::make_pair(*iter, get(path_count, v)));
0489 }
0490 }
0491
0492
0493 for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
0494 iter != deleted_vertices.end(); ++iter)
0495 put(is_settled, *iter, true);
0496
0497
0498
0499 #endif
0500
0501
0502 ++current_bucket;
0503 } while (true);
0504
0505
0506 for (typename std::vector<Bucket*>::iterator iter = buckets.begin();
0507 iter != buckets.end(); ++iter) {
0508 if (*iter) {
0509 delete *iter;
0510 *iter = 0;
0511 }
0512 }
0513 }
0514
0515 template<typename Graph, typename DistanceMap, typename IncomingMap,
0516 typename EdgeWeightMap, typename PathCountMap
0517 #ifdef COMPUTE_PATH_COUNTS_INLINE
0518 , typename IsSettledMap, typename VertexIndexMap
0519 #endif
0520 >
0521 void
0522 betweenness_centrality_delta_stepping_impl<
0523 Graph, DistanceMap, IncomingMap, EdgeWeightMap, PathCountMap
0524 #ifdef COMPUTE_PATH_COUNTS_INLINE
0525 , IsSettledMap, VertexIndexMap
0526 #endif
0527 >::
0528 relax(Vertex u, Vertex v, Dist x)
0529 {
0530
0531 if (x <= get(distance, v)) {
0532
0533
0534 if (get(owner, v) == process_id(pg)) {
0535 if (x < get(distance, v)) {
0536
0537 BucketIndex new_index = static_cast<BucketIndex>(x / delta);
0538
0539
0540 if (new_index >= buckets.size()) buckets.resize(new_index + 1, 0);
0541
0542
0543 if (!buckets[new_index]) buckets[new_index] = new Bucket;
0544
0545 if (get(distance, v) != (std::numeric_limits<Dist>::max)()
0546 && !vertex_was_deleted[get(local, v)]) {
0547
0548
0549 BucketIndex old_index
0550 = static_cast<BucketIndex>(get(distance, v) / delta);
0551 buckets[new_index]->splice(buckets[new_index]->end(),
0552 *buckets[old_index],
0553 position_in_bucket[get(local, v)]);
0554 } else {
0555
0556
0557 buckets[new_index]->push_back(v);
0558 }
0559
0560
0561 position_in_bucket[get(local, v)] = buckets[new_index]->end();
0562 --position_in_bucket[get(local, v)];
0563
0564
0565 if (u != v) put(incoming, v, IncomingType(1, u));
0566 put(distance, v, x);
0567 }
0568 else if (x == get(distance, v) && u != v) {
0569
0570
0571 IncomingType in = get(incoming, v);
0572 if (std::find(in.begin(), in.end(), u) == in.end()) {
0573 in.push_back(u);
0574 put(incoming, v, in);
0575 }
0576 }
0577 } else {
0578
0579 send(pg, get(owner, v), msg_relax,
0580 std::make_pair(v, MessageValue::create(x, u)));
0581
0582
0583 cache(distance, v, x);
0584 }
0585 }
0586 }
0587
0588
0589
0590
0591
0592 template<typename WeightMap>
0593 struct brandes_shortest_paths {
0594 typedef typename property_traits<WeightMap>::value_type weight_type;
0595
0596 brandes_shortest_paths()
0597 : weight(1), delta(0) { }
0598 brandes_shortest_paths(weight_type delta)
0599 : weight(1), delta(delta) { }
0600 brandes_shortest_paths(WeightMap w)
0601 : weight(w), delta(0) { }
0602 brandes_shortest_paths(WeightMap w, weight_type delta)
0603 : weight(w), delta(delta) { }
0604
0605 template<typename Graph, typename IncomingMap, typename DistanceMap,
0606 typename PathCountMap
0607 #ifdef COMPUTE_PATH_COUNTS_INLINE
0608 , typename IsSettledMap, typename VertexIndexMap
0609 #endif
0610
0611 >
0612 void
0613 operator()(Graph& g,
0614 typename graph_traits<Graph>::vertex_descriptor s,
0615 IncomingMap incoming,
0616 DistanceMap distance,
0617 PathCountMap path_count
0618 #ifdef COMPUTE_PATH_COUNTS_INLINE
0619 , IsSettledMap is_settled,
0620 VertexIndexMap vertex_index
0621 #endif
0622 )
0623 {
0624
0625
0626 set_property_map_role(vertex_distance, distance);
0627
0628
0629
0630
0631 if (delta == 0)
0632 set_delta(g);
0633
0634
0635
0636 betweenness_centrality_delta_stepping_impl<
0637 Graph, DistanceMap, IncomingMap, WeightMap, PathCountMap
0638 #ifdef COMPUTE_PATH_COUNTS_INLINE
0639 , IsSettledMap, VertexIndexMap
0640 #endif
0641 >
0642 impl(g, distance, incoming, weight, path_count,
0643 #ifdef COMPUTE_PATH_COUNTS_INLINE
0644 is_settled, vertex_index,
0645 #endif
0646 delta);
0647
0648 impl.run(s);
0649 }
0650
0651 private:
0652
0653 template <typename Graph>
0654 void
0655 set_delta(const Graph& g)
0656 {
0657 using boost::parallel::all_reduce;
0658 using boost::parallel::maximum;
0659 using std::max;
0660
0661 typedef typename graph_traits<Graph>::degree_size_type Degree;
0662 typedef weight_type Dist;
0663
0664
0665 Dist max_edge_weight = 0;
0666 Degree max_degree = 0;
0667 BGL_FORALL_VERTICES_T(u, g, Graph) {
0668 max_degree = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_degree, out_degree(u, g));
0669 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
0670 max_edge_weight = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_edge_weight, get(weight, e));
0671 }
0672
0673 max_edge_weight = all_reduce(process_group(g), max_edge_weight, maximum<Dist>());
0674 max_degree = all_reduce(process_group(g), max_degree, maximum<Degree>());
0675
0676
0677
0678 delta = max_edge_weight / max_degree;
0679 if (delta == 0)
0680 delta = 1;
0681 }
0682
0683 WeightMap weight;
0684 weight_type delta;
0685 };
0686
0687
0688 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
0689 typename IncomingMap, typename DistanceMap, typename DependencyMap,
0690 typename PathCountMap,
0691 #ifdef COMPUTE_PATH_COUNTS_INLINE
0692 typename IsSettledMap,
0693 #endif
0694 typename VertexIndexMap, typename ShortestPaths>
0695 void
0696 do_brandes_sssp(const Graph& g,
0697 CentralityMap centrality,
0698 EdgeCentralityMap edge_centrality_map,
0699 IncomingMap incoming,
0700 DistanceMap distance,
0701 DependencyMap dependency,
0702 PathCountMap path_count,
0703 #ifdef COMPUTE_PATH_COUNTS_INLINE
0704 IsSettledMap is_settled,
0705 #endif
0706 VertexIndexMap vertex_index,
0707 ShortestPaths shortest_paths,
0708 typename graph_traits<Graph>::vertex_descriptor s)
0709 {
0710 using boost::detail::graph::update_centrality;
0711 using boost::graph::parallel::process_group;
0712
0713 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0714 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
0715
0716 typedef typename property_traits<IncomingMap>::value_type incoming_type;
0717 typedef typename property_traits<DistanceMap>::value_type distance_type;
0718 typedef typename property_traits<DependencyMap>::value_type dependency_type;
0719 typedef typename property_traits<PathCountMap>::value_type path_count_type;
0720
0721 typedef typename incoming_type::iterator incoming_iterator;
0722
0723 typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
0724 OwnerMap owner = get(vertex_owner, g);
0725
0726 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0727 process_group_type;
0728 process_group_type pg = process_group(g);
0729 typename process_group_type::process_id_type id = process_id(pg);
0730
0731
0732
0733 distance.clear();
0734 incoming.clear();
0735 path_count.clear();
0736 dependency.clear();
0737 BGL_FORALL_VERTICES_T(v, g, Graph) {
0738 put(path_count, v, 0);
0739 put(dependency, v, 0);
0740 }
0741
0742 if (get(owner, s) == id) {
0743 put(incoming, s, incoming_type());
0744 #ifdef COMPUTE_PATH_COUNTS_INLINE
0745 put(path_count, s, 1);
0746 put(is_settled, s, true);
0747 #endif
0748 }
0749
0750
0751
0752 shortest_paths(g, s, incoming, distance, path_count
0753 #ifdef COMPUTE_PATH_COUNTS_INLINE
0754 , is_settled, vertex_index
0755 #endif
0756 );
0757
0758 #ifndef COMPUTE_PATH_COUNTS_INLINE
0759
0760
0761
0762
0763
0764
0765
0766 std::vector<edges_size_type> incoming_edge_countS(num_vertices(g));
0767 iterator_property_map<typename std::vector<edges_size_type>::iterator, VertexIndexMap>
0768 incoming_edge_count(incoming_edge_countS.begin(), vertex_index);
0769
0770 BGL_FORALL_VERTICES_T(v, g, Graph) {
0771 put(incoming_edge_count, v, get(incoming, v).size());
0772 }
0773
0774 if (get(owner, s) == id) {
0775 put(incoming_edge_count, s, 1);
0776 put(incoming, s, incoming_type());
0777 }
0778
0779 std::vector<incoming_type> outgoingS(num_vertices(g));
0780 iterator_property_map<typename std::vector<incoming_type>::iterator, VertexIndexMap>
0781 outgoing(outgoingS.begin(), vertex_index);
0782
0783 outgoing.set_reduce(append_reducer<incoming_type>());
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793 BGL_FORALL_VERTICES_T(v, g, Graph) {
0794 incoming_type i = get(incoming, v);
0795 for (typename incoming_type::iterator iter = i.begin(); iter != i.end(); ++iter) {
0796 if (get(owner, *iter) == id) {
0797 incoming_type x = get(outgoing, *iter);
0798 if (std::find(x.begin(), x.end(), v) == x.end())
0799 x.push_back(v);
0800 put(outgoing, *iter, x);
0801 } else {
0802 incoming_type in;
0803 in.push_back(v);
0804 put(outgoing, *iter, in);
0805 }
0806 }
0807 }
0808
0809 synchronize(pg);
0810
0811
0812 {
0813 typedef std::pair<vertex_descriptor, path_count_type> queue_value_type;
0814 typedef get_owner_of_first_pair_element<OwnerMap> IndirectOwnerMap;
0815
0816 typedef boost::queue<queue_value_type> local_queue_type;
0817 typedef boost::graph::distributed::distributed_queue<process_group_type,
0818 IndirectOwnerMap,
0819 local_queue_type> dist_queue_type;
0820
0821 IndirectOwnerMap indirect_owner(owner);
0822 dist_queue_type Q(pg, indirect_owner);
0823
0824 if (get(owner, s) == id)
0825 Q.push(std::make_pair(s, 1));
0826
0827 while (!Q.empty()) {
0828 queue_value_type t = Q.top(); Q.pop();
0829 vertex_descriptor v = t.first;
0830 path_count_type p = t.second;
0831
0832 put(path_count, v, get(path_count, v) + p);
0833 put(incoming_edge_count, v, get(incoming_edge_count, v) - 1);
0834
0835 if (get(incoming_edge_count, v) == 0) {
0836 incoming_type out = get(outgoing, v);
0837 for (typename incoming_type::iterator iter = out.begin(); iter != out.end(); ++iter)
0838 Q.push(std::make_pair(*iter, get(path_count, v)));
0839 }
0840 }
0841 }
0842
0843 #endif
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853 typedef boost::tuple<vertex_descriptor, vertex_descriptor, dependency_type, path_count_type>
0854 queue_value_type;
0855 typedef get_owner_of_first_tuple_element<OwnerMap, queue_value_type> IndirectOwnerMap;
0856
0857 typedef boost::queue<queue_value_type> local_queue_type;
0858 typedef boost::graph::distributed::distributed_queue<process_group_type,
0859 IndirectOwnerMap,
0860 local_queue_type> dist_queue_type;
0861
0862 IndirectOwnerMap indirect_owner(owner);
0863 dist_queue_type Q(pg, indirect_owner);
0864
0865
0866
0867
0868 std::vector<dependency_type> dependency_countS(num_vertices(g), 0);
0869 iterator_property_map<typename std::vector<dependency_type>::iterator, VertexIndexMap>
0870 dependency_count(dependency_countS.begin(), vertex_index);
0871
0872 dependency_count.set_reduce(boost::graph::distributed::additive_reducer<dependency_type>());
0873
0874 path_count.set_max_ghost_cells(0);
0875
0876 BGL_FORALL_VERTICES_T(v, g, Graph) {
0877 if (get(distance, v) < (std::numeric_limits<distance_type>::max)()) {
0878 incoming_type el = get(incoming, v);
0879 for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw) {
0880 if (get(owner, *vw) == id)
0881 put(dependency_count, *vw, get(dependency_count, *vw) + 1);
0882 else {
0883 put(dependency_count, *vw, 1);
0884
0885
0886 get(path_count, *vw);
0887 }
0888
0889
0890
0891 }
0892 }
0893 }
0894
0895 synchronize(pg);
0896
0897
0898 BGL_FORALL_VERTICES_T(v, g, Graph) {
0899 if (get(distance, v) < (std::numeric_limits<distance_type>::max)()
0900 && get(dependency_count, v) == 0)
0901 Q.push(boost::make_tuple(v, v, get(dependency, v), get(path_count, v)));
0902 }
0903
0904 dependency.set_max_ghost_cells(0);
0905 while(!Q.empty()) {
0906
0907 queue_value_type x = Q.top(); Q.pop();
0908 vertex_descriptor w = boost::tuples::get<0>(x);
0909 vertex_descriptor source = boost::tuples::get<1>(x);
0910 dependency_type dep = boost::tuples::get<2>(x);
0911 path_count_type pc = boost::tuples::get<3>(x);
0912
0913 cache(dependency, source, dep);
0914 cache(path_count, source, pc);
0915
0916 if (get(dependency_count, w) != 0)
0917 put(dependency_count, w, get(dependency_count, w) - 1);
0918
0919 if (get(dependency_count, w) == 0) {
0920
0921
0922 incoming_type el = get(incoming, w);
0923 for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw) {
0924 vertex_descriptor v = *vw;
0925
0926 BOOST_ASSERT(get(path_count, w) != 0);
0927
0928 dependency_type factor = dependency_type(get(path_count, v))
0929 / dependency_type(get(path_count, w));
0930 factor *= (dependency_type(1) + get(dependency, w));
0931
0932 if (get(owner, v) == id)
0933 put(dependency, v, get(dependency, v) + factor);
0934 else
0935 put(dependency, v, factor);
0936
0937 update_centrality(edge_centrality_map, v, factor);
0938 }
0939
0940 if (w != s)
0941 update_centrality(centrality, w, get(dependency, w));
0942
0943
0944 for (incoming_iterator vw = el.begin(); vw != el.end(); ++vw)
0945 Q.push(boost::make_tuple(*vw, w, get(dependency, w), get(path_count, w)));
0946 }
0947 }
0948 }
0949
0950 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
0951 typename IncomingMap, typename DistanceMap, typename DependencyMap,
0952 typename PathCountMap, typename VertexIndexMap, typename ShortestPaths,
0953 typename Buffer>
0954 void
0955 brandes_betweenness_centrality_impl(const Graph& g,
0956 CentralityMap centrality,
0957 EdgeCentralityMap edge_centrality_map,
0958 IncomingMap incoming,
0959 DistanceMap distance,
0960 DependencyMap dependency,
0961 PathCountMap path_count,
0962 VertexIndexMap vertex_index,
0963 ShortestPaths shortest_paths,
0964 Buffer sources)
0965 {
0966 using boost::detail::graph::init_centrality_map;
0967 using boost::detail::graph::divide_centrality_by_two;
0968 using boost::graph::parallel::process_group;
0969
0970 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0971
0972 typedef typename property_traits<DistanceMap>::value_type distance_type;
0973 typedef typename property_traits<DependencyMap>::value_type dependency_type;
0974
0975
0976 init_centrality_map(vertices(g), centrality);
0977 init_centrality_map(edges(g), edge_centrality_map);
0978
0979
0980 dependency.set_reduce(boost::graph::distributed::additive_reducer<dependency_type>());
0981 distance.set_reduce(boost::graph::distributed::choose_min_reducer<distance_type>());
0982
0983
0984
0985 incoming.set_consistency_model(0);
0986 path_count.set_consistency_model(0);
0987
0988 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0989 process_group_type;
0990 process_group_type pg = process_group(g);
0991
0992 #ifdef COMPUTE_PATH_COUNTS_INLINE
0993
0994 std::vector<bool> is_settledS(num_vertices(g));
0995 typedef iterator_property_map<std::vector<bool>::iterator, VertexIndexMap>
0996 IsSettledMap;
0997
0998 IsSettledMap is_settled(is_settledS.begin(), vertex_index);
0999 #endif
1000
1001 if (!sources.empty()) {
1002
1003 while (!sources.empty()) {
1004 do_brandes_sssp(g, centrality, edge_centrality_map, incoming, distance,
1005 dependency, path_count,
1006 #ifdef COMPUTE_PATH_COUNTS_INLINE
1007 is_settled,
1008 #endif
1009 vertex_index, shortest_paths, sources.top());
1010 sources.pop();
1011 }
1012 } else {
1013 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
1014 vertices_size_type n = num_vertices(g);
1015 n = boost::parallel::all_reduce(pg, n, std::plus<vertices_size_type>());
1016
1017 for (vertices_size_type i = 0; i < n; ++i) {
1018 vertex_descriptor v = vertex(i, g);
1019
1020 do_brandes_sssp(g, centrality, edge_centrality_map, incoming, distance,
1021 dependency, path_count,
1022 #ifdef COMPUTE_PATH_COUNTS_INLINE
1023 is_settled,
1024 #endif
1025 vertex_index, shortest_paths, v);
1026 }
1027 }
1028
1029 typedef typename graph_traits<Graph>::directed_category directed_category;
1030 const bool is_undirected =
1031 is_convertible<directed_category*, undirected_tag*>::value;
1032 if (is_undirected) {
1033 divide_centrality_by_two(vertices(g), centrality);
1034 divide_centrality_by_two(edges(g), edge_centrality_map);
1035 }
1036 }
1037
1038 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1039 typename IncomingMap, typename DistanceMap, typename DependencyMap,
1040 typename PathCountMap, typename VertexIndexMap, typename ShortestPaths,
1041 typename Stack>
1042 void
1043 do_sequential_brandes_sssp(const Graph& g,
1044 CentralityMap centrality,
1045 EdgeCentralityMap edge_centrality_map,
1046 IncomingMap incoming,
1047 DistanceMap distance,
1048 DependencyMap dependency,
1049 PathCountMap path_count,
1050 VertexIndexMap vertex_index,
1051 ShortestPaths shortest_paths,
1052 Stack& ordered_vertices,
1053 typename graph_traits<Graph>::vertex_descriptor v)
1054 {
1055 using boost::detail::graph::update_centrality;
1056
1057 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
1058
1059
1060 BGL_FORALL_VERTICES_T(w, g, Graph) {
1061
1062 incoming[w].clear();
1063 put(dependency, w, 0);
1064 }
1065
1066 put(path_count, v, 1);
1067 incoming[v].clear();
1068
1069
1070
1071
1072 shortest_paths(g, v, ordered_vertices, incoming, distance,
1073 path_count, vertex_index);
1074
1075 while (!ordered_vertices.empty()) {
1076 vertex_descriptor w = ordered_vertices.top();
1077 ordered_vertices.pop();
1078
1079 typedef typename property_traits<IncomingMap>::value_type
1080 incoming_type;
1081 typedef typename incoming_type::iterator incoming_iterator;
1082 typedef typename property_traits<DependencyMap>::value_type
1083 dependency_type;
1084
1085 for (incoming_iterator vw = incoming[w].begin();
1086 vw != incoming[w].end(); ++vw) {
1087 vertex_descriptor v = source(*vw, g);
1088 dependency_type factor = dependency_type(get(path_count, v))
1089 / dependency_type(get(path_count, w));
1090 factor *= (dependency_type(1) + get(dependency, w));
1091 put(dependency, v, get(dependency, v) + factor);
1092 update_centrality(edge_centrality_map, *vw, factor);
1093 }
1094
1095 if (w != v) {
1096 update_centrality(centrality, w, get(dependency, w));
1097 }
1098 }
1099 }
1100
1101
1102
1103
1104 template<typename ProcessGroup, typename Graph,
1105 typename CentralityMap, typename EdgeCentralityMap,
1106 typename IncomingMap, typename DistanceMap,
1107 typename DependencyMap, typename PathCountMap,
1108 typename VertexIndexMap, typename ShortestPaths,
1109 typename Buffer>
1110 void
1111 non_distributed_brandes_betweenness_centrality_impl(const ProcessGroup& pg,
1112 const Graph& g,
1113 CentralityMap centrality,
1114 EdgeCentralityMap edge_centrality_map,
1115 IncomingMap incoming,
1116 DistanceMap distance,
1117 DependencyMap dependency,
1118 PathCountMap path_count,
1119 VertexIndexMap vertex_index,
1120 ShortestPaths shortest_paths,
1121 Buffer sources)
1122 {
1123 using boost::detail::graph::init_centrality_map;
1124 using boost::detail::graph::divide_centrality_by_two;
1125 using boost::graph::parallel::process_group;
1126
1127 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
1128
1129 typedef ProcessGroup process_group_type;
1130
1131 typename process_group_type::process_id_type id = process_id(pg);
1132 typename process_group_type::process_size_type p = num_processes(pg);
1133
1134
1135 init_centrality_map(vertices(g), centrality);
1136 init_centrality_map(edges(g), edge_centrality_map);
1137
1138 std::stack<vertex_descriptor> ordered_vertices;
1139
1140 if (!sources.empty()) {
1141 std::vector<vertex_descriptor> local_sources;
1142
1143 for (int i = 0; i < id; ++i) if (!sources.empty()) sources.pop();
1144 while (!sources.empty()) {
1145 local_sources.push_back(sources.top());
1146
1147 for (int i = 0; i < p; ++i) if (!sources.empty()) sources.pop();
1148 }
1149
1150
1151 for(size_t i = 0; i < local_sources.size(); ++i)
1152 do_sequential_brandes_sssp(g, centrality, edge_centrality_map, incoming,
1153 distance, dependency, path_count, vertex_index,
1154 shortest_paths, ordered_vertices, local_sources[i]);
1155
1156 } else {
1157 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
1158 vertices_size_type n = num_vertices(g);
1159
1160 for (vertices_size_type i = id; i < n; i += p) {
1161 vertex_descriptor v = vertex(i, g);
1162
1163 do_sequential_brandes_sssp(g, centrality, edge_centrality_map, incoming,
1164 distance, dependency, path_count, vertex_index,
1165 shortest_paths, ordered_vertices, v);
1166 }
1167 }
1168
1169 typedef typename graph_traits<Graph>::directed_category directed_category;
1170 const bool is_undirected =
1171 is_convertible<directed_category*, undirected_tag*>::value;
1172 if (is_undirected) {
1173 divide_centrality_by_two(vertices(g), centrality);
1174 divide_centrality_by_two(edges(g), edge_centrality_map);
1175 }
1176
1177
1178
1179 typedef typename property_traits<CentralityMap>::value_type centrality_type;
1180 typedef typename property_traits<EdgeCentralityMap>::value_type edge_centrality_type;
1181
1182 std::vector<centrality_type> centrality_v(num_vertices(g));
1183 std::vector<edge_centrality_type> edge_centrality_v;
1184 edge_centrality_v.reserve(num_edges(g));
1185
1186 BGL_FORALL_VERTICES_T(v, g, Graph) {
1187 centrality_v[get(vertex_index, v)] = get(centrality, v);
1188 }
1189
1190
1191 if (!is_same<EdgeCentralityMap, dummy_property_map>::value) {
1192 BGL_FORALL_EDGES_T(e, g, Graph) {
1193 edge_centrality_v.push_back(get(edge_centrality_map, e));
1194 }
1195
1196
1197 }
1198
1199 using boost::parallel::all_reduce;
1200
1201 all_reduce(pg, ¢rality_v[0], ¢rality_v[centrality_v.size()],
1202 ¢rality_v[0], std::plus<centrality_type>());
1203
1204 if (edge_centrality_v.size())
1205 all_reduce(pg, &edge_centrality_v[0], &edge_centrality_v[edge_centrality_v.size()],
1206 &edge_centrality_v[0], std::plus<edge_centrality_type>());
1207
1208 BGL_FORALL_VERTICES_T(v, g, Graph) {
1209 put(centrality, v, centrality_v[get(vertex_index, v)]);
1210 }
1211
1212
1213 if (!is_same<EdgeCentralityMap, dummy_property_map>::value) {
1214 int i = 0;
1215 BGL_FORALL_EDGES_T(e, g, Graph) {
1216 put(edge_centrality_map, e, edge_centrality_v[i]);
1217 ++i;
1218 }
1219 }
1220 }
1221
1222 } } }
1223
1224 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1225 typename IncomingMap, typename DistanceMap, typename DependencyMap,
1226 typename PathCountMap, typename VertexIndexMap, typename Buffer>
1227 void
1228 brandes_betweenness_centrality(const Graph& g,
1229 CentralityMap centrality,
1230 EdgeCentralityMap edge_centrality_map,
1231 IncomingMap incoming,
1232 DistanceMap distance,
1233 DependencyMap dependency,
1234 PathCountMap path_count,
1235 VertexIndexMap vertex_index,
1236 Buffer sources,
1237 typename property_traits<DistanceMap>::value_type delta
1238 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
1239 {
1240 typedef typename property_traits<DistanceMap>::value_type distance_type;
1241 typedef static_property_map<distance_type> WeightMap;
1242
1243 graph::parallel::detail::brandes_shortest_paths<WeightMap>
1244 shortest_paths(delta);
1245
1246 graph::parallel::detail::brandes_betweenness_centrality_impl(g, centrality,
1247 edge_centrality_map,
1248 incoming, distance,
1249 dependency, path_count,
1250 vertex_index,
1251 shortest_paths,
1252 sources);
1253 }
1254
1255 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1256 typename IncomingMap, typename DistanceMap, typename DependencyMap,
1257 typename PathCountMap, typename VertexIndexMap, typename WeightMap,
1258 typename Buffer>
1259 void
1260 brandes_betweenness_centrality(const Graph& g,
1261 CentralityMap centrality,
1262 EdgeCentralityMap edge_centrality_map,
1263 IncomingMap incoming,
1264 DistanceMap distance,
1265 DependencyMap dependency,
1266 PathCountMap path_count,
1267 VertexIndexMap vertex_index,
1268 Buffer sources,
1269 typename property_traits<WeightMap>::value_type delta,
1270 WeightMap weight_map
1271 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
1272 {
1273 graph::parallel::detail::brandes_shortest_paths<WeightMap> shortest_paths(weight_map, delta);
1274
1275 graph::parallel::detail::brandes_betweenness_centrality_impl(g, centrality,
1276 edge_centrality_map,
1277 incoming, distance,
1278 dependency, path_count,
1279 vertex_index,
1280 shortest_paths,
1281 sources);
1282 }
1283
1284 namespace graph { namespace parallel { namespace detail {
1285 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1286 typename WeightMap, typename VertexIndexMap, typename Buffer>
1287 void
1288 brandes_betweenness_centrality_dispatch2(const Graph& g,
1289 CentralityMap centrality,
1290 EdgeCentralityMap edge_centrality_map,
1291 WeightMap weight_map,
1292 VertexIndexMap vertex_index,
1293 Buffer sources,
1294 typename property_traits<WeightMap>::value_type delta)
1295 {
1296 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
1297 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
1298 typedef typename mpl::if_c<(is_same<CentralityMap,
1299 dummy_property_map>::value),
1300 EdgeCentralityMap,
1301 CentralityMap>::type a_centrality_map;
1302 typedef typename property_traits<a_centrality_map>::value_type
1303 centrality_type;
1304
1305 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
1306
1307 std::vector<std::vector<vertex_descriptor> > incoming(V);
1308 std::vector<centrality_type> distance(V);
1309 std::vector<centrality_type> dependency(V);
1310 std::vector<degree_size_type> path_count(V);
1311
1312 brandes_betweenness_centrality(
1313 g, centrality, edge_centrality_map,
1314 make_iterator_property_map(incoming.begin(), vertex_index),
1315 make_iterator_property_map(distance.begin(), vertex_index),
1316 make_iterator_property_map(dependency.begin(), vertex_index),
1317 make_iterator_property_map(path_count.begin(), vertex_index),
1318 vertex_index, unwrap_ref(sources), delta,
1319 weight_map);
1320 }
1321
1322
1323
1324 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1325 typename VertexIndexMap, typename Buffer>
1326 void
1327 brandes_betweenness_centrality_dispatch2(const Graph& g,
1328 CentralityMap centrality,
1329 EdgeCentralityMap edge_centrality_map,
1330 VertexIndexMap vertex_index,
1331 Buffer sources,
1332 typename graph_traits<Graph>::edges_size_type delta)
1333 {
1334 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
1335 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
1336 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
1337
1338 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
1339
1340 std::vector<std::vector<vertex_descriptor> > incoming(V);
1341 std::vector<edges_size_type> distance(V);
1342 std::vector<edges_size_type> dependency(V);
1343 std::vector<degree_size_type> path_count(V);
1344
1345 brandes_betweenness_centrality(
1346 g, centrality, edge_centrality_map,
1347 make_iterator_property_map(incoming.begin(), vertex_index),
1348 make_iterator_property_map(distance.begin(), vertex_index),
1349 make_iterator_property_map(dependency.begin(), vertex_index),
1350 make_iterator_property_map(path_count.begin(), vertex_index),
1351 vertex_index, unwrap_ref(sources), delta);
1352 }
1353
1354 template<typename WeightMap>
1355 struct brandes_betweenness_centrality_dispatch1
1356 {
1357 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1358 typename VertexIndexMap, typename Buffer>
1359 static void
1360 run(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map,
1361 VertexIndexMap vertex_index, Buffer sources,
1362 typename property_traits<WeightMap>::value_type delta, WeightMap weight_map)
1363 {
1364 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
1365 g, centrality, edge_centrality_map, weight_map, vertex_index, sources, delta);
1366 }
1367 };
1368
1369 template<>
1370 struct brandes_betweenness_centrality_dispatch1<boost::param_not_found>
1371 {
1372 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
1373 typename VertexIndexMap, typename Buffer>
1374 static void
1375 run(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map,
1376 VertexIndexMap vertex_index, Buffer sources,
1377 typename graph_traits<Graph>::edges_size_type delta,
1378 boost::param_not_found)
1379 {
1380 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
1381 g, centrality, edge_centrality_map, vertex_index, sources, delta);
1382 }
1383 };
1384
1385 } } }
1386
1387 template<typename Graph, typename Param, typename Tag, typename Rest>
1388 void
1389 brandes_betweenness_centrality(const Graph& g,
1390 const bgl_named_params<Param,Tag,Rest>& params
1391 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
1392 {
1393 typedef bgl_named_params<Param,Tag,Rest> named_params;
1394
1395 typedef queue<typename graph_traits<Graph>::vertex_descriptor> queue_t;
1396 queue_t q;
1397
1398 typedef typename get_param_type<edge_weight_t, named_params>::type ew_param;
1399 typedef typename detail::choose_impl_result<mpl::true_, Graph, ew_param, edge_weight_t>::type ew;
1400 graph::parallel::detail::brandes_betweenness_centrality_dispatch1<ew>::run(
1401 g,
1402 choose_param(get_param(params, vertex_centrality),
1403 dummy_property_map()),
1404 choose_param(get_param(params, edge_centrality),
1405 dummy_property_map()),
1406 choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
1407 choose_param(get_param(params, buffer_param_t()), boost::ref(q)),
1408 choose_param(get_param(params, lookahead_t()), 0),
1409 choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
1410 }
1411
1412 template<typename Graph, typename CentralityMap>
1413 void
1414 brandes_betweenness_centrality(const Graph& g, CentralityMap centrality
1415 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
1416 {
1417 typedef queue<typename graph_traits<Graph>::vertex_descriptor> queue_t;
1418 queue_t q;
1419
1420 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
1421 g, centrality, dummy_property_map(), get(vertex_index, g), boost::ref(q), 0);
1422 }
1423
1424 template<typename Graph, typename CentralityMap, typename EdgeCentralityMap>
1425 void
1426 brandes_betweenness_centrality(const Graph& g, CentralityMap centrality,
1427 EdgeCentralityMap edge_centrality_map
1428 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
1429 {
1430 typedef queue<int> queue_t;
1431 queue_t q;
1432
1433 boost::graph::parallel::detail::brandes_betweenness_centrality_dispatch2(
1434 g, centrality, edge_centrality_map, get(vertex_index, g), boost::ref(q), 0);
1435 }
1436
1437 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1438 typename EdgeCentralityMap, typename IncomingMap, typename DistanceMap,
1439 typename DependencyMap, typename PathCountMap, typename VertexIndexMap,
1440 typename Buffer>
1441 void
1442 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg,
1443 const Graph& g,
1444 CentralityMap centrality,
1445 EdgeCentralityMap edge_centrality_map,
1446 IncomingMap incoming,
1447 DistanceMap distance,
1448 DependencyMap dependency,
1449 PathCountMap path_count,
1450 VertexIndexMap vertex_index,
1451 Buffer sources)
1452 {
1453 detail::graph::brandes_unweighted_shortest_paths shortest_paths;
1454
1455 graph::parallel::detail::non_distributed_brandes_betweenness_centrality_impl(pg, g, centrality,
1456 edge_centrality_map,
1457 incoming, distance,
1458 dependency, path_count,
1459 vertex_index,
1460 shortest_paths,
1461 sources);
1462 }
1463
1464 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1465 typename EdgeCentralityMap, typename IncomingMap, typename DistanceMap,
1466 typename DependencyMap, typename PathCountMap, typename VertexIndexMap,
1467 typename WeightMap, typename Buffer>
1468 void
1469 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg,
1470 const Graph& g,
1471 CentralityMap centrality,
1472 EdgeCentralityMap edge_centrality_map,
1473 IncomingMap incoming,
1474 DistanceMap distance,
1475 DependencyMap dependency,
1476 PathCountMap path_count,
1477 VertexIndexMap vertex_index,
1478 WeightMap weight_map,
1479 Buffer sources)
1480 {
1481 detail::graph::brandes_dijkstra_shortest_paths<WeightMap> shortest_paths(weight_map);
1482
1483 graph::parallel::detail::non_distributed_brandes_betweenness_centrality_impl(pg, g, centrality,
1484 edge_centrality_map,
1485 incoming, distance,
1486 dependency, path_count,
1487 vertex_index,
1488 shortest_paths,
1489 sources);
1490 }
1491
1492 namespace detail { namespace graph {
1493 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1494 typename EdgeCentralityMap, typename WeightMap, typename VertexIndexMap,
1495 typename Buffer>
1496 void
1497 non_distributed_brandes_betweenness_centrality_dispatch2(const ProcessGroup& pg,
1498 const Graph& g,
1499 CentralityMap centrality,
1500 EdgeCentralityMap edge_centrality_map,
1501 WeightMap weight_map,
1502 VertexIndexMap vertex_index,
1503 Buffer sources)
1504 {
1505 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
1506 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
1507 typedef typename mpl::if_c<(is_same<CentralityMap,
1508 dummy_property_map>::value),
1509 EdgeCentralityMap,
1510 CentralityMap>::type a_centrality_map;
1511 typedef typename property_traits<a_centrality_map>::value_type
1512 centrality_type;
1513
1514 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
1515
1516 std::vector<std::vector<edge_descriptor> > incoming(V);
1517 std::vector<centrality_type> distance(V);
1518 std::vector<centrality_type> dependency(V);
1519 std::vector<degree_size_type> path_count(V);
1520
1521 non_distributed_brandes_betweenness_centrality(
1522 pg, g, centrality, edge_centrality_map,
1523 make_iterator_property_map(incoming.begin(), vertex_index),
1524 make_iterator_property_map(distance.begin(), vertex_index),
1525 make_iterator_property_map(dependency.begin(), vertex_index),
1526 make_iterator_property_map(path_count.begin(), vertex_index),
1527 vertex_index, weight_map, unwrap_ref(sources));
1528 }
1529
1530
1531 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1532 typename EdgeCentralityMap, typename VertexIndexMap, typename Buffer>
1533 void
1534 non_distributed_brandes_betweenness_centrality_dispatch2(const ProcessGroup& pg,
1535 const Graph& g,
1536 CentralityMap centrality,
1537 EdgeCentralityMap edge_centrality_map,
1538 VertexIndexMap vertex_index,
1539 Buffer sources)
1540 {
1541 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
1542 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
1543 typedef typename mpl::if_c<(is_same<CentralityMap,
1544 dummy_property_map>::value),
1545 EdgeCentralityMap,
1546 CentralityMap>::type a_centrality_map;
1547 typedef typename property_traits<a_centrality_map>::value_type
1548 centrality_type;
1549
1550 typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
1551
1552 std::vector<std::vector<edge_descriptor> > incoming(V);
1553 std::vector<centrality_type> distance(V);
1554 std::vector<centrality_type> dependency(V);
1555 std::vector<degree_size_type> path_count(V);
1556
1557 non_distributed_brandes_betweenness_centrality(
1558 pg, g, centrality, edge_centrality_map,
1559 make_iterator_property_map(incoming.begin(), vertex_index),
1560 make_iterator_property_map(distance.begin(), vertex_index),
1561 make_iterator_property_map(dependency.begin(), vertex_index),
1562 make_iterator_property_map(path_count.begin(), vertex_index),
1563 vertex_index, unwrap_ref(sources));
1564 }
1565
1566 template<typename WeightMap>
1567 struct non_distributed_brandes_betweenness_centrality_dispatch1
1568 {
1569 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1570 typename EdgeCentralityMap, typename VertexIndexMap, typename Buffer>
1571 static void
1572 run(const ProcessGroup& pg, const Graph& g, CentralityMap centrality,
1573 EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
1574 Buffer sources, WeightMap weight_map)
1575 {
1576 non_distributed_brandes_betweenness_centrality_dispatch2(pg, g, centrality, edge_centrality_map,
1577 weight_map, vertex_index, sources);
1578 }
1579 };
1580
1581 template<>
1582 struct non_distributed_brandes_betweenness_centrality_dispatch1<param_not_found>
1583 {
1584 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1585 typename EdgeCentralityMap, typename VertexIndexMap, typename Buffer>
1586 static void
1587 run(const ProcessGroup& pg, const Graph& g, CentralityMap centrality,
1588 EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
1589 Buffer sources, param_not_found)
1590 {
1591 non_distributed_brandes_betweenness_centrality_dispatch2(pg, g, centrality, edge_centrality_map,
1592 vertex_index, sources);
1593 }
1594 };
1595
1596 } }
1597
1598 template<typename ProcessGroup, typename Graph, typename Param, typename Tag, typename Rest>
1599 void
1600 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
1601 const bgl_named_params<Param,Tag,Rest>& params)
1602 {
1603 typedef bgl_named_params<Param,Tag,Rest> named_params;
1604
1605 typedef queue<int> queue_t;
1606 queue_t q;
1607
1608 typedef typename get_param_type<edge_weight_t, named_params>::type ew_param;
1609 typedef typename detail::choose_impl_result<mpl::true_, Graph, ew_param, edge_weight_t>::type ew;
1610 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch1<ew>::run(
1611 pg, g,
1612 choose_param(get_param(params, vertex_centrality),
1613 dummy_property_map()),
1614 choose_param(get_param(params, edge_centrality),
1615 dummy_property_map()),
1616 choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
1617 choose_param(get_param(params, buffer_param_t()), boost::ref(q)),
1618 choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
1619 }
1620
1621 template<typename ProcessGroup, typename Graph, typename CentralityMap>
1622 void
1623 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
1624 CentralityMap centrality)
1625 {
1626 typedef queue<int> queue_t;
1627 queue_t q;
1628
1629 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch2(
1630 pg, g, centrality, dummy_property_map(), get(vertex_index, g), boost::ref(q));
1631 }
1632
1633 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1634 typename Buffer>
1635 void
1636 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
1637 CentralityMap centrality, Buffer sources)
1638 {
1639 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch2(
1640 pg, g, centrality, dummy_property_map(), get(vertex_index, g), sources);
1641 }
1642
1643 template<typename ProcessGroup, typename Graph, typename CentralityMap,
1644 typename EdgeCentralityMap, typename Buffer>
1645 void
1646 non_distributed_brandes_betweenness_centrality(const ProcessGroup& pg, const Graph& g,
1647 CentralityMap centrality,
1648 EdgeCentralityMap edge_centrality_map,
1649 Buffer sources)
1650 {
1651 detail::graph::non_distributed_brandes_betweenness_centrality_dispatch2(
1652 pg, g, centrality, edge_centrality_map, get(vertex_index, g), sources);
1653 }
1654
1655
1656
1657 template<typename Graph, typename CentralityMap>
1658 typename property_traits<CentralityMap>::value_type
1659 central_point_dominance(const Graph& g, CentralityMap centrality
1660 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
1661 {
1662 using std::max;
1663
1664 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
1665 typedef typename property_traits<CentralityMap>::value_type centrality_type;
1666 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
1667
1668 typedef typename boost::graph::parallel::process_group_type<Graph>::type
1669 process_group_type;
1670 process_group_type pg = boost::graph::parallel::process_group(g);
1671
1672 vertices_size_type n = num_vertices(g);
1673
1674 using boost::parallel::all_reduce;
1675 n = all_reduce(pg, n, std::plus<vertices_size_type>());
1676
1677
1678 centrality_type max_centrality(0);
1679 vertex_iterator v, v_end;
1680 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) {
1681 max_centrality = (max)(max_centrality, get(centrality, *v));
1682 }
1683
1684
1685 max_centrality = all_reduce(pg, max_centrality, boost::parallel::maximum<centrality_type>());
1686
1687
1688 centrality_type sum(0);
1689 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) {
1690 sum += (max_centrality - get(centrality, *v));
1691 }
1692
1693 sum = all_reduce(pg, sum, std::plus<centrality_type>());
1694
1695 return sum/(n-1);
1696 }
1697
1698 }
1699
1700 #endif