File indexing completed on 2025-01-18 09:37:23
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
0010 #define BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
0011
0012 #include <stack>
0013 #include <vector>
0014 #include <boost/graph/overloading.hpp>
0015 #include <boost/graph/dijkstra_shortest_paths.hpp>
0016 #include <boost/graph/breadth_first_search.hpp>
0017 #include <boost/graph/relax.hpp>
0018 #include <boost/graph/graph_traits.hpp>
0019 #include <boost/tuple/tuple.hpp>
0020 #include <boost/type_traits/is_convertible.hpp>
0021 #include <boost/type_traits/is_same.hpp>
0022 #include <boost/mpl/if.hpp>
0023 #include <boost/property_map/property_map.hpp>
0024 #include <boost/graph/named_function_params.hpp>
0025 #include <algorithm>
0026
0027 namespace boost
0028 {
0029
0030 namespace detail
0031 {
0032 namespace graph
0033 {
0034
0035
0036
0037
0038
0039
0040
0041
0042 template < typename Graph, typename WeightMap, typename IncomingMap,
0043 typename DistanceMap, typename PathCountMap >
0044 struct brandes_dijkstra_visitor : public bfs_visitor<>
0045 {
0046 typedef typename graph_traits< Graph >::vertex_descriptor
0047 vertex_descriptor;
0048 typedef
0049 typename graph_traits< Graph >::edge_descriptor edge_descriptor;
0050
0051 brandes_dijkstra_visitor(
0052 std::stack< vertex_descriptor >& ordered_vertices,
0053 WeightMap weight, IncomingMap incoming, DistanceMap distance,
0054 PathCountMap path_count)
0055 : ordered_vertices(ordered_vertices)
0056 , weight(weight)
0057 , incoming(incoming)
0058 , distance(distance)
0059 , path_count(path_count)
0060 {
0061 }
0062
0063
0064
0065
0066
0067
0068 void edge_relaxed(edge_descriptor e, const Graph& g)
0069 {
0070 vertex_descriptor v = source(e, g), w = target(e, g);
0071 incoming[w].clear();
0072 incoming[w].push_back(e);
0073 put(path_count, w, get(path_count, v));
0074 }
0075
0076
0077
0078
0079
0080
0081
0082 void edge_not_relaxed(edge_descriptor e, const Graph& g)
0083 {
0084 typedef typename property_traits< WeightMap >::value_type
0085 weight_type;
0086 typedef typename property_traits< DistanceMap >::value_type
0087 distance_type;
0088 vertex_descriptor v = source(e, g), w = target(e, g);
0089 distance_type d_v = get(distance, v), d_w = get(distance, w);
0090 weight_type w_e = get(weight, e);
0091
0092 closed_plus< distance_type > combine;
0093 if (d_w == combine(d_v, w_e))
0094 {
0095 put(path_count, w, get(path_count, w) + get(path_count, v));
0096 incoming[w].push_back(e);
0097 }
0098 }
0099
0100
0101 void examine_vertex(vertex_descriptor w, const Graph&)
0102 {
0103 ordered_vertices.push(w);
0104 }
0105
0106 private:
0107 std::stack< vertex_descriptor >& ordered_vertices;
0108 WeightMap weight;
0109 IncomingMap incoming;
0110 DistanceMap distance;
0111 PathCountMap path_count;
0112 };
0113
0114
0115
0116
0117
0118
0119 template < typename WeightMap > struct brandes_dijkstra_shortest_paths
0120 {
0121 brandes_dijkstra_shortest_paths(WeightMap weight_map)
0122 : weight_map(weight_map)
0123 {
0124 }
0125
0126 template < typename Graph, typename IncomingMap,
0127 typename DistanceMap, typename PathCountMap,
0128 typename VertexIndexMap >
0129 void operator()(Graph& g,
0130 typename graph_traits< Graph >::vertex_descriptor s,
0131 std::stack< typename graph_traits< Graph >::vertex_descriptor >&
0132 ov,
0133 IncomingMap incoming, DistanceMap distance,
0134 PathCountMap path_count, VertexIndexMap vertex_index)
0135 {
0136 typedef brandes_dijkstra_visitor< Graph, WeightMap, IncomingMap,
0137 DistanceMap, PathCountMap >
0138 visitor_type;
0139 visitor_type visitor(
0140 ov, weight_map, incoming, distance, path_count);
0141
0142 dijkstra_shortest_paths(g, s,
0143 boost::weight_map(weight_map)
0144 .vertex_index_map(vertex_index)
0145 .distance_map(distance)
0146 .visitor(visitor));
0147 }
0148
0149 private:
0150 WeightMap weight_map;
0151 };
0152
0153
0154
0155
0156
0157 struct brandes_unweighted_shortest_paths
0158 {
0159
0160
0161
0162
0163
0164 template < typename Graph, typename IncomingMap,
0165 typename DistanceMap, typename PathCountMap >
0166 struct visitor_type : public bfs_visitor<>
0167 {
0168 typedef typename graph_traits< Graph >::edge_descriptor
0169 edge_descriptor;
0170 typedef typename graph_traits< Graph >::vertex_descriptor
0171 vertex_descriptor;
0172
0173 visitor_type(IncomingMap incoming, DistanceMap distance,
0174 PathCountMap path_count,
0175 std::stack< vertex_descriptor >& ordered_vertices)
0176 : incoming(incoming)
0177 , distance(distance)
0178 , path_count(path_count)
0179 , ordered_vertices(ordered_vertices)
0180 {
0181 }
0182
0183
0184 void examine_vertex(vertex_descriptor v, Graph&)
0185 {
0186 ordered_vertices.push(v);
0187 }
0188
0189
0190
0191
0192
0193
0194 void tree_edge(edge_descriptor e, Graph& g)
0195 {
0196 vertex_descriptor v = source(e, g);
0197 vertex_descriptor w = target(e, g);
0198 put(distance, w, get(distance, v) + 1);
0199
0200 put(path_count, w, get(path_count, v));
0201 incoming[w].push_back(e);
0202 }
0203
0204
0205
0206
0207
0208
0209
0210 void non_tree_edge(edge_descriptor e, Graph& g)
0211 {
0212 vertex_descriptor v = source(e, g);
0213 vertex_descriptor w = target(e, g);
0214 if (get(distance, w) == get(distance, v) + 1)
0215 {
0216 put(path_count, w,
0217 get(path_count, w) + get(path_count, v));
0218 incoming[w].push_back(e);
0219 }
0220 }
0221
0222 private:
0223 IncomingMap incoming;
0224 DistanceMap distance;
0225 PathCountMap path_count;
0226 std::stack< vertex_descriptor >& ordered_vertices;
0227 };
0228
0229 template < typename Graph, typename IncomingMap,
0230 typename DistanceMap, typename PathCountMap,
0231 typename VertexIndexMap >
0232 void operator()(Graph& g,
0233 typename graph_traits< Graph >::vertex_descriptor s,
0234 std::stack< typename graph_traits< Graph >::vertex_descriptor >&
0235 ov,
0236 IncomingMap incoming, DistanceMap distance,
0237 PathCountMap path_count, VertexIndexMap vertex_index)
0238 {
0239 typedef typename graph_traits< Graph >::vertex_descriptor
0240 vertex_descriptor;
0241
0242 visitor_type< Graph, IncomingMap, DistanceMap, PathCountMap >
0243 visitor(incoming, distance, path_count, ov);
0244
0245 std::vector< default_color_type > colors(num_vertices(g),
0246 color_traits< default_color_type >::white());
0247 boost::queue< vertex_descriptor > Q;
0248 breadth_first_visit(g, s, Q, visitor,
0249 make_iterator_property_map(colors.begin(), vertex_index));
0250 }
0251 };
0252
0253
0254
0255 template < typename Iter >
0256 inline void init_centrality_map(
0257 std::pair< Iter, Iter >, dummy_property_map)
0258 {
0259 }
0260
0261
0262
0263 template < typename Iter, typename Centrality >
0264 void init_centrality_map(
0265 std::pair< Iter, Iter > keys, Centrality centrality_map)
0266 {
0267 typedef typename property_traits< Centrality >::value_type
0268 centrality_type;
0269 while (keys.first != keys.second)
0270 {
0271 put(centrality_map, *keys.first, centrality_type(0));
0272 ++keys.first;
0273 }
0274 }
0275
0276
0277
0278 template < typename Key, typename T >
0279 inline void update_centrality(dummy_property_map, const Key&, const T&)
0280 {
0281 }
0282
0283
0284 template < typename CentralityMap, typename Key, typename T >
0285 inline void update_centrality(
0286 CentralityMap centrality_map, Key k, const T& x)
0287 {
0288 put(centrality_map, k, get(centrality_map, k) + x);
0289 }
0290
0291 template < typename Iter >
0292 inline void divide_centrality_by_two(
0293 std::pair< Iter, Iter >, dummy_property_map)
0294 {
0295 }
0296
0297 template < typename Iter, typename CentralityMap >
0298 inline void divide_centrality_by_two(
0299 std::pair< Iter, Iter > keys, CentralityMap centrality_map)
0300 {
0301 typename property_traits< CentralityMap >::value_type two(2);
0302 while (keys.first != keys.second)
0303 {
0304 put(centrality_map, *keys.first,
0305 get(centrality_map, *keys.first) / two);
0306 ++keys.first;
0307 }
0308 }
0309
0310 template < typename Graph, typename CentralityMap,
0311 typename EdgeCentralityMap, typename IncomingMap,
0312 typename DistanceMap, typename DependencyMap, typename PathCountMap,
0313 typename VertexIndexMap, typename ShortestPaths >
0314 void brandes_betweenness_centrality_impl(const Graph& g,
0315 CentralityMap centrality,
0316 EdgeCentralityMap edge_centrality_map,
0317 IncomingMap incoming,
0318 DistanceMap distance,
0319 DependencyMap dependency,
0320 PathCountMap path_count,
0321 VertexIndexMap vertex_index, ShortestPaths shortest_paths)
0322 {
0323 typedef
0324 typename graph_traits< Graph >::vertex_iterator vertex_iterator;
0325 typedef typename graph_traits< Graph >::vertex_descriptor
0326 vertex_descriptor;
0327
0328
0329 init_centrality_map(vertices(g), centrality);
0330 init_centrality_map(edges(g), edge_centrality_map);
0331
0332 std::stack< vertex_descriptor > ordered_vertices;
0333 vertex_iterator s, s_end;
0334 for (boost::tie(s, s_end) = vertices(g); s != s_end; ++s)
0335 {
0336
0337 vertex_iterator w, w_end;
0338 for (boost::tie(w, w_end) = vertices(g); w != w_end; ++w)
0339 {
0340 incoming[*w].clear();
0341 put(path_count, *w, 0);
0342 put(dependency, *w, 0);
0343 }
0344 put(path_count, *s, 1);
0345
0346
0347
0348
0349 shortest_paths(g, *s, ordered_vertices, incoming, distance,
0350 path_count, vertex_index);
0351
0352 while (!ordered_vertices.empty())
0353 {
0354 vertex_descriptor w = ordered_vertices.top();
0355 ordered_vertices.pop();
0356
0357 typedef typename property_traits< IncomingMap >::value_type
0358 incoming_type;
0359 typedef typename incoming_type::iterator incoming_iterator;
0360 typedef
0361 typename property_traits< DependencyMap >::value_type
0362 dependency_type;
0363
0364 for (incoming_iterator vw = incoming[w].begin();
0365 vw != incoming[w].end(); ++vw)
0366 {
0367 vertex_descriptor v = source(*vw, g);
0368 dependency_type factor
0369 = dependency_type(get(path_count, v))
0370 / dependency_type(get(path_count, w));
0371 factor *= (dependency_type(1) + get(dependency, w));
0372 put(dependency, v, get(dependency, v) + factor);
0373 update_centrality(edge_centrality_map, *vw, factor);
0374 }
0375
0376 if (w != *s)
0377 {
0378 update_centrality(centrality, w, get(dependency, w));
0379 }
0380 }
0381 }
0382
0383 typedef typename graph_traits< Graph >::directed_category
0384 directed_category;
0385 const bool is_undirected
0386 = is_convertible< directed_category*, undirected_tag* >::value;
0387 if (is_undirected)
0388 {
0389 divide_centrality_by_two(vertices(g), centrality);
0390 divide_centrality_by_two(edges(g), edge_centrality_map);
0391 }
0392 }
0393
0394 }
0395 }
0396
0397 template < typename Graph, typename CentralityMap, typename EdgeCentralityMap,
0398 typename IncomingMap, typename DistanceMap, typename DependencyMap,
0399 typename PathCountMap, typename VertexIndexMap >
0400 void brandes_betweenness_centrality(const Graph& g,
0401 CentralityMap centrality,
0402 EdgeCentralityMap edge_centrality_map,
0403 IncomingMap incoming,
0404 DistanceMap distance,
0405 DependencyMap dependency,
0406 PathCountMap path_count,
0407 VertexIndexMap vertex_index BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0408 Graph, vertex_list_graph_tag))
0409 {
0410 detail::graph::brandes_unweighted_shortest_paths shortest_paths;
0411
0412 detail::graph::brandes_betweenness_centrality_impl(g, centrality,
0413 edge_centrality_map, incoming, distance, dependency, path_count,
0414 vertex_index, shortest_paths);
0415 }
0416
0417 template < typename Graph, typename CentralityMap, typename EdgeCentralityMap,
0418 typename IncomingMap, typename DistanceMap, typename DependencyMap,
0419 typename PathCountMap, typename VertexIndexMap, typename WeightMap >
0420 void brandes_betweenness_centrality(const Graph& g,
0421 CentralityMap centrality,
0422 EdgeCentralityMap edge_centrality_map,
0423 IncomingMap incoming,
0424 DistanceMap distance,
0425 DependencyMap dependency,
0426 PathCountMap path_count,
0427 VertexIndexMap vertex_index,
0428 WeightMap weight_map BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0429 Graph, vertex_list_graph_tag))
0430 {
0431 detail::graph::brandes_dijkstra_shortest_paths< WeightMap > shortest_paths(
0432 weight_map);
0433
0434 detail::graph::brandes_betweenness_centrality_impl(g, centrality,
0435 edge_centrality_map, incoming, distance, dependency, path_count,
0436 vertex_index, shortest_paths);
0437 }
0438
0439 namespace detail
0440 {
0441 namespace graph
0442 {
0443 template < typename Graph, typename CentralityMap,
0444 typename EdgeCentralityMap, typename WeightMap,
0445 typename VertexIndexMap >
0446 void brandes_betweenness_centrality_dispatch2(const Graph& g,
0447 CentralityMap centrality, EdgeCentralityMap edge_centrality_map,
0448 WeightMap weight_map, VertexIndexMap vertex_index)
0449 {
0450 typedef typename graph_traits< Graph >::degree_size_type
0451 degree_size_type;
0452 typedef
0453 typename graph_traits< Graph >::edge_descriptor edge_descriptor;
0454 typedef typename mpl::if_c<
0455 (is_same< CentralityMap, dummy_property_map >::value),
0456 EdgeCentralityMap, CentralityMap >::type a_centrality_map;
0457 typedef typename property_traits< a_centrality_map >::value_type
0458 centrality_type;
0459
0460 typename graph_traits< Graph >::vertices_size_type V
0461 = num_vertices(g);
0462
0463 std::vector< std::vector< edge_descriptor > > incoming(V);
0464 std::vector< centrality_type > distance(V);
0465 std::vector< centrality_type > dependency(V);
0466 std::vector< degree_size_type > path_count(V);
0467
0468 brandes_betweenness_centrality(g, centrality, edge_centrality_map,
0469 make_iterator_property_map(incoming.begin(), vertex_index),
0470 make_iterator_property_map(distance.begin(), vertex_index),
0471 make_iterator_property_map(dependency.begin(), vertex_index),
0472 make_iterator_property_map(path_count.begin(), vertex_index),
0473 vertex_index, weight_map);
0474 }
0475
0476 template < typename Graph, typename CentralityMap,
0477 typename EdgeCentralityMap, typename VertexIndexMap >
0478 void brandes_betweenness_centrality_dispatch2(const Graph& g,
0479 CentralityMap centrality, EdgeCentralityMap edge_centrality_map,
0480 VertexIndexMap vertex_index)
0481 {
0482 typedef typename graph_traits< Graph >::degree_size_type
0483 degree_size_type;
0484 typedef
0485 typename graph_traits< Graph >::edge_descriptor edge_descriptor;
0486 typedef typename mpl::if_c<
0487 (is_same< CentralityMap, dummy_property_map >::value),
0488 EdgeCentralityMap, CentralityMap >::type a_centrality_map;
0489 typedef typename property_traits< a_centrality_map >::value_type
0490 centrality_type;
0491
0492 typename graph_traits< Graph >::vertices_size_type V
0493 = num_vertices(g);
0494
0495 std::vector< std::vector< edge_descriptor > > incoming(V);
0496 std::vector< centrality_type > distance(V);
0497 std::vector< centrality_type > dependency(V);
0498 std::vector< degree_size_type > path_count(V);
0499
0500 brandes_betweenness_centrality(g, centrality, edge_centrality_map,
0501 make_iterator_property_map(incoming.begin(), vertex_index),
0502 make_iterator_property_map(distance.begin(), vertex_index),
0503 make_iterator_property_map(dependency.begin(), vertex_index),
0504 make_iterator_property_map(path_count.begin(), vertex_index),
0505 vertex_index);
0506 }
0507
0508 template < typename WeightMap >
0509 struct brandes_betweenness_centrality_dispatch1
0510 {
0511 template < typename Graph, typename CentralityMap,
0512 typename EdgeCentralityMap, typename VertexIndexMap >
0513 static void run(const Graph& g, CentralityMap centrality,
0514 EdgeCentralityMap edge_centrality_map,
0515 VertexIndexMap vertex_index, WeightMap weight_map)
0516 {
0517 brandes_betweenness_centrality_dispatch2(g, centrality,
0518 edge_centrality_map, weight_map, vertex_index);
0519 }
0520 };
0521
0522 template <>
0523 struct brandes_betweenness_centrality_dispatch1< param_not_found >
0524 {
0525 template < typename Graph, typename CentralityMap,
0526 typename EdgeCentralityMap, typename VertexIndexMap >
0527 static void run(const Graph& g, CentralityMap centrality,
0528 EdgeCentralityMap edge_centrality_map,
0529 VertexIndexMap vertex_index, param_not_found)
0530 {
0531 brandes_betweenness_centrality_dispatch2(
0532 g, centrality, edge_centrality_map, vertex_index);
0533 }
0534 };
0535
0536 template < typename T > struct is_bgl_named_params
0537 {
0538 BOOST_STATIC_CONSTANT(bool, value = false);
0539 };
0540
0541 template < typename Param, typename Tag, typename Rest >
0542 struct is_bgl_named_params< bgl_named_params< Param, Tag, Rest > >
0543 {
0544 BOOST_STATIC_CONSTANT(bool, value = true);
0545 };
0546
0547 }
0548 }
0549
0550 template < typename Graph, typename Param, typename Tag, typename Rest >
0551 void brandes_betweenness_centrality(const Graph& g,
0552 const bgl_named_params< Param, Tag, Rest >& params
0553 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag))
0554 {
0555 typedef bgl_named_params< Param, Tag, Rest > named_params;
0556
0557 typedef typename get_param_type< edge_weight_t, named_params >::type ew;
0558 detail::graph::brandes_betweenness_centrality_dispatch1< ew >::run(g,
0559 choose_param(
0560 get_param(params, vertex_centrality), dummy_property_map()),
0561 choose_param(get_param(params, edge_centrality), dummy_property_map()),
0562 choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
0563 get_param(params, edge_weight));
0564 }
0565
0566
0567
0568 template < typename Graph, typename CentralityMap >
0569 typename disable_if< detail::graph::is_bgl_named_params< CentralityMap >,
0570 void >::type
0571 brandes_betweenness_centrality(const Graph& g,
0572 CentralityMap centrality BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0573 Graph, vertex_list_graph_tag))
0574 {
0575 detail::graph::brandes_betweenness_centrality_dispatch2(
0576 g, centrality, dummy_property_map(), get(vertex_index, g));
0577 }
0578
0579 template < typename Graph, typename CentralityMap, typename EdgeCentralityMap >
0580 void brandes_betweenness_centrality(const Graph& g, CentralityMap centrality,
0581 EdgeCentralityMap edge_centrality_map BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0582 Graph, vertex_list_graph_tag))
0583 {
0584 detail::graph::brandes_betweenness_centrality_dispatch2(
0585 g, centrality, edge_centrality_map, get(vertex_index, g));
0586 }
0587
0588
0589
0590
0591
0592
0593
0594 template < typename Graph, typename CentralityMap >
0595 void relative_betweenness_centrality(const Graph& g, CentralityMap centrality)
0596 {
0597 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator;
0598 typedef
0599 typename property_traits< CentralityMap >::value_type centrality_type;
0600
0601 typename graph_traits< Graph >::vertices_size_type n = num_vertices(g);
0602 centrality_type factor
0603 = centrality_type(2) / centrality_type(n * n - 3 * n + 2);
0604 vertex_iterator v, v_end;
0605 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
0606 {
0607 put(centrality, *v, factor * get(centrality, *v));
0608 }
0609 }
0610
0611
0612 template < typename Graph, typename CentralityMap >
0613 typename property_traits< CentralityMap >::value_type central_point_dominance(
0614 const Graph& g,
0615 CentralityMap centrality BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0616 Graph, vertex_list_graph_tag))
0617 {
0618 using std::max;
0619
0620 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator;
0621 typedef
0622 typename property_traits< CentralityMap >::value_type centrality_type;
0623
0624 typename graph_traits< Graph >::vertices_size_type n = num_vertices(g);
0625
0626
0627 centrality_type max_centrality(0);
0628 vertex_iterator v, v_end;
0629 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
0630 {
0631 max_centrality = (max)(max_centrality, get(centrality, *v));
0632 }
0633
0634
0635 centrality_type sum(0);
0636 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
0637 {
0638 sum += (max_centrality - get(centrality, *v));
0639 }
0640 return sum / (n - 1);
0641 }
0642
0643 }
0644
0645 #endif