os/ossrv/ossrv_pub/boost_apis/boost/graph/betweenness_centrality.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright 2004 The Trustees of Indiana University.
sl@0
     2
sl@0
     3
// Distributed under the Boost Software License, Version 1.0.
sl@0
     4
// (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     5
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     6
sl@0
     7
//  Authors: Douglas Gregor
sl@0
     8
//           Andrew Lumsdaine
sl@0
     9
#ifndef BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
sl@0
    10
#define BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
sl@0
    11
sl@0
    12
#include <stack>
sl@0
    13
#include <vector>
sl@0
    14
#include <boost/graph/dijkstra_shortest_paths.hpp>
sl@0
    15
#include <boost/graph/breadth_first_search.hpp>
sl@0
    16
#include <boost/graph/relax.hpp>
sl@0
    17
#include <boost/graph/graph_traits.hpp>
sl@0
    18
#include <boost/tuple/tuple.hpp>
sl@0
    19
#include <boost/type_traits/is_convertible.hpp>
sl@0
    20
#include <boost/type_traits/is_same.hpp>
sl@0
    21
#include <boost/mpl/if.hpp>
sl@0
    22
#include <boost/property_map.hpp>
sl@0
    23
#include <boost/graph/named_function_params.hpp>
sl@0
    24
#include <algorithm>
sl@0
    25
sl@0
    26
namespace boost {
sl@0
    27
sl@0
    28
namespace detail { namespace graph {
sl@0
    29
sl@0
    30
  /**
sl@0
    31
   * Customized visitor passed to Dijkstra's algorithm by Brandes'
sl@0
    32
   * betweenness centrality algorithm. This visitor is responsible for
sl@0
    33
   * keeping track of the order in which vertices are discovered, the
sl@0
    34
   * predecessors on the shortest path(s) to a vertex, and the number
sl@0
    35
   * of shortest paths.
sl@0
    36
   */
sl@0
    37
  template<typename Graph, typename WeightMap, typename IncomingMap,
sl@0
    38
           typename DistanceMap, typename PathCountMap>
sl@0
    39
  struct brandes_dijkstra_visitor : public bfs_visitor<>
sl@0
    40
  {
sl@0
    41
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
sl@0
    42
    typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
sl@0
    43
sl@0
    44
    brandes_dijkstra_visitor(std::stack<vertex_descriptor>& ordered_vertices,
sl@0
    45
                             WeightMap weight,
sl@0
    46
                             IncomingMap incoming,
sl@0
    47
                             DistanceMap distance,
sl@0
    48
                             PathCountMap path_count)
sl@0
    49
      : ordered_vertices(ordered_vertices), weight(weight), 
sl@0
    50
        incoming(incoming), distance(distance),
sl@0
    51
        path_count(path_count)
sl@0
    52
    { }
sl@0
    53
sl@0
    54
    /**
sl@0
    55
     * Whenever an edge e = (v, w) is relaxed, the incoming edge list
sl@0
    56
     * for w is set to {(v, w)} and the shortest path count of w is set to
sl@0
    57
     * the number of paths that reach {v}.
sl@0
    58
     */
sl@0
    59
    void edge_relaxed(edge_descriptor e, const Graph& g) 
sl@0
    60
    { 
sl@0
    61
      vertex_descriptor v = source(e, g), w = target(e, g);
sl@0
    62
      incoming[w].clear();
sl@0
    63
      incoming[w].push_back(e);
sl@0
    64
      put(path_count, w, get(path_count, v));
sl@0
    65
    }
sl@0
    66
sl@0
    67
    /**
sl@0
    68
     * If an edge e = (v, w) was not relaxed, it may still be the case
sl@0
    69
     * that we've found more equally-short paths, so include {(v, w)} in the
sl@0
    70
     * incoming edges of w and add all of the shortest paths to v to the
sl@0
    71
     * shortest path count of w.
sl@0
    72
     */
sl@0
    73
    void edge_not_relaxed(edge_descriptor e, const Graph& g) 
sl@0
    74
    {
sl@0
    75
      typedef typename property_traits<WeightMap>::value_type weight_type;
sl@0
    76
      typedef typename property_traits<DistanceMap>::value_type distance_type;
sl@0
    77
      vertex_descriptor v = source(e, g), w = target(e, g);
sl@0
    78
      distance_type d_v = get(distance, v), d_w = get(distance, w);
sl@0
    79
      weight_type w_e = get(weight, e);
sl@0
    80
sl@0
    81
      closed_plus<distance_type> combine;
sl@0
    82
      if (d_w == combine(d_v, w_e)) {
sl@0
    83
        put(path_count, w, get(path_count, w) + get(path_count, v));
sl@0
    84
        incoming[w].push_back(e);
sl@0
    85
      }
sl@0
    86
    }
sl@0
    87
sl@0
    88
    /// Keep track of vertices as they are reached
sl@0
    89
    void examine_vertex(vertex_descriptor w, const Graph&) 
sl@0
    90
    { 
sl@0
    91
      ordered_vertices.push(w);
sl@0
    92
    }
sl@0
    93
sl@0
    94
  private:
sl@0
    95
    std::stack<vertex_descriptor>& ordered_vertices;
sl@0
    96
    WeightMap weight;
sl@0
    97
    IncomingMap incoming;
sl@0
    98
    DistanceMap distance;
sl@0
    99
    PathCountMap path_count;
sl@0
   100
  };
sl@0
   101
sl@0
   102
  /**
sl@0
   103
   * Function object that calls Dijkstra's shortest paths algorithm
sl@0
   104
   * using the Dijkstra visitor for the Brandes betweenness centrality
sl@0
   105
   * algorithm.
sl@0
   106
   */
sl@0
   107
  template<typename WeightMap>
sl@0
   108
  struct brandes_dijkstra_shortest_paths
sl@0
   109
  {
sl@0
   110
    brandes_dijkstra_shortest_paths(WeightMap weight_map) 
sl@0
   111
      : weight_map(weight_map) { }
sl@0
   112
sl@0
   113
    template<typename Graph, typename IncomingMap, typename DistanceMap, 
sl@0
   114
             typename PathCountMap, typename VertexIndexMap>
sl@0
   115
    void 
sl@0
   116
    operator()(Graph& g, 
sl@0
   117
               typename graph_traits<Graph>::vertex_descriptor s,
sl@0
   118
               std::stack<typename graph_traits<Graph>::vertex_descriptor>& ov,
sl@0
   119
               IncomingMap incoming,
sl@0
   120
               DistanceMap distance,
sl@0
   121
               PathCountMap path_count,
sl@0
   122
               VertexIndexMap vertex_index)
sl@0
   123
    {
sl@0
   124
      typedef brandes_dijkstra_visitor<Graph, WeightMap, IncomingMap, 
sl@0
   125
                                       DistanceMap, PathCountMap> visitor_type;
sl@0
   126
      visitor_type visitor(ov, weight_map, incoming, distance, path_count);
sl@0
   127
sl@0
   128
      dijkstra_shortest_paths(g, s, 
sl@0
   129
                              boost::weight_map(weight_map)
sl@0
   130
                              .vertex_index_map(vertex_index)
sl@0
   131
                              .distance_map(distance)
sl@0
   132
                              .visitor(visitor));
sl@0
   133
    }
sl@0
   134
sl@0
   135
  private:
sl@0
   136
    WeightMap weight_map;
sl@0
   137
  };
sl@0
   138
sl@0
   139
  /**
sl@0
   140
   * Function object that invokes breadth-first search for the
sl@0
   141
   * unweighted form of the Brandes betweenness centrality algorithm.
sl@0
   142
   */
sl@0
   143
  struct brandes_unweighted_shortest_paths
sl@0
   144
  {
sl@0
   145
    /**
sl@0
   146
     * Customized visitor passed to breadth-first search, which
sl@0
   147
     * records predecessor and the number of shortest paths to each
sl@0
   148
     * vertex.
sl@0
   149
     */
sl@0
   150
    template<typename Graph, typename IncomingMap, typename DistanceMap, 
sl@0
   151
             typename PathCountMap>
sl@0
   152
    struct visitor_type : public bfs_visitor<>
sl@0
   153
    {
sl@0
   154
      typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
sl@0
   155
      typedef typename graph_traits<Graph>::vertex_descriptor 
sl@0
   156
        vertex_descriptor;
sl@0
   157
      
sl@0
   158
      visitor_type(IncomingMap incoming, DistanceMap distance, 
sl@0
   159
                   PathCountMap path_count, 
sl@0
   160
                   std::stack<vertex_descriptor>& ordered_vertices)
sl@0
   161
        : incoming(incoming), distance(distance), 
sl@0
   162
          path_count(path_count), ordered_vertices(ordered_vertices) { }
sl@0
   163
sl@0
   164
      /// Keep track of vertices as they are reached
sl@0
   165
      void examine_vertex(vertex_descriptor v, Graph&)
sl@0
   166
      {
sl@0
   167
        ordered_vertices.push(v);
sl@0
   168
      }
sl@0
   169
sl@0
   170
      /**
sl@0
   171
       * Whenever an edge e = (v, w) is labelled a tree edge, the
sl@0
   172
       * incoming edge list for w is set to {(v, w)} and the shortest
sl@0
   173
       * path count of w is set to the number of paths that reach {v}.
sl@0
   174
       */
sl@0
   175
      void tree_edge(edge_descriptor e, Graph& g)
sl@0
   176
      {
sl@0
   177
        vertex_descriptor v = source(e, g);
sl@0
   178
        vertex_descriptor w = target(e, g);
sl@0
   179
        put(distance, w, get(distance, v) + 1);
sl@0
   180
        
sl@0
   181
        put(path_count, w, get(path_count, v));
sl@0
   182
        incoming[w].push_back(e);
sl@0
   183
      }
sl@0
   184
sl@0
   185
      /**
sl@0
   186
       * If an edge e = (v, w) is not a tree edge, it may still be the
sl@0
   187
       * case that we've found more equally-short paths, so include (v, w)
sl@0
   188
       * in the incoming edge list of w and add all of the shortest
sl@0
   189
       * paths to v to the shortest path count of w.
sl@0
   190
       */
sl@0
   191
      void non_tree_edge(edge_descriptor e, Graph& g)
sl@0
   192
      {
sl@0
   193
        vertex_descriptor v = source(e, g);
sl@0
   194
        vertex_descriptor w = target(e, g);
sl@0
   195
        if (get(distance, w) == get(distance, v) + 1) {
sl@0
   196
          put(path_count, w, get(path_count, w) + get(path_count, v));
sl@0
   197
          incoming[w].push_back(e);
sl@0
   198
        }
sl@0
   199
      }
sl@0
   200
sl@0
   201
    private:
sl@0
   202
      IncomingMap incoming;
sl@0
   203
      DistanceMap distance;
sl@0
   204
      PathCountMap path_count;
sl@0
   205
      std::stack<vertex_descriptor>& ordered_vertices;
sl@0
   206
    };
sl@0
   207
sl@0
   208
    template<typename Graph, typename IncomingMap, typename DistanceMap, 
sl@0
   209
             typename PathCountMap, typename VertexIndexMap>
sl@0
   210
    void 
sl@0
   211
    operator()(Graph& g, 
sl@0
   212
               typename graph_traits<Graph>::vertex_descriptor s,
sl@0
   213
               std::stack<typename graph_traits<Graph>::vertex_descriptor>& ov,
sl@0
   214
               IncomingMap incoming,
sl@0
   215
               DistanceMap distance,
sl@0
   216
               PathCountMap path_count,
sl@0
   217
               VertexIndexMap vertex_index)
sl@0
   218
    {
sl@0
   219
      typedef typename graph_traits<Graph>::vertex_descriptor
sl@0
   220
        vertex_descriptor;
sl@0
   221
sl@0
   222
      visitor_type<Graph, IncomingMap, DistanceMap, PathCountMap>
sl@0
   223
        visitor(incoming, distance, path_count, ov);
sl@0
   224
      
sl@0
   225
      std::vector<default_color_type> 
sl@0
   226
        colors(num_vertices(g), color_traits<default_color_type>::white());
sl@0
   227
      boost::queue<vertex_descriptor> Q;
sl@0
   228
      breadth_first_visit(g, s, Q, visitor, 
sl@0
   229
                          make_iterator_property_map(colors.begin(), 
sl@0
   230
                                                     vertex_index));
sl@0
   231
    }
sl@0
   232
  };
sl@0
   233
sl@0
   234
  // When the edge centrality map is a dummy property map, no
sl@0
   235
  // initialization is needed.
sl@0
   236
  template<typename Iter>
sl@0
   237
  inline void 
sl@0
   238
  init_centrality_map(std::pair<Iter, Iter>, dummy_property_map) { }
sl@0
   239
sl@0
   240
  // When we have a real edge centrality map, initialize all of the
sl@0
   241
  // centralities to zero.
sl@0
   242
  template<typename Iter, typename Centrality>
sl@0
   243
  void 
sl@0
   244
  init_centrality_map(std::pair<Iter, Iter> keys, Centrality centrality_map)
sl@0
   245
  {
sl@0
   246
    typedef typename property_traits<Centrality>::value_type 
sl@0
   247
      centrality_type;
sl@0
   248
    while (keys.first != keys.second) {
sl@0
   249
      put(centrality_map, *keys.first, centrality_type(0));
sl@0
   250
      ++keys.first;
sl@0
   251
    }
sl@0
   252
  }
sl@0
   253
sl@0
   254
  // When the edge centrality map is a dummy property map, no update
sl@0
   255
  // is performed.
sl@0
   256
  template<typename Key, typename T>
sl@0
   257
  inline void 
sl@0
   258
  update_centrality(dummy_property_map, const Key&, const T&) { }
sl@0
   259
sl@0
   260
  // When we have a real edge centrality map, add the value to the map
sl@0
   261
  template<typename CentralityMap, typename Key, typename T>
sl@0
   262
  inline void 
sl@0
   263
  update_centrality(CentralityMap centrality_map, Key k, const T& x)
sl@0
   264
  { put(centrality_map, k, get(centrality_map, k) + x); }
sl@0
   265
sl@0
   266
  template<typename Iter>
sl@0
   267
  inline void 
sl@0
   268
  divide_centrality_by_two(std::pair<Iter, Iter>, dummy_property_map) {}
sl@0
   269
sl@0
   270
  template<typename Iter, typename CentralityMap>
sl@0
   271
  inline void
sl@0
   272
  divide_centrality_by_two(std::pair<Iter, Iter> keys, 
sl@0
   273
                           CentralityMap centrality_map)
sl@0
   274
  {
sl@0
   275
    typename property_traits<CentralityMap>::value_type two(2);
sl@0
   276
    while (keys.first != keys.second) {
sl@0
   277
      put(centrality_map, *keys.first, get(centrality_map, *keys.first) / two);
sl@0
   278
      ++keys.first;
sl@0
   279
    }
sl@0
   280
  }
sl@0
   281
sl@0
   282
  template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
sl@0
   283
           typename IncomingMap, typename DistanceMap, 
sl@0
   284
           typename DependencyMap, typename PathCountMap,
sl@0
   285
           typename VertexIndexMap, typename ShortestPaths>
sl@0
   286
  void 
sl@0
   287
  brandes_betweenness_centrality_impl(const Graph& g, 
sl@0
   288
                                      CentralityMap centrality,     // C_B
sl@0
   289
                                      EdgeCentralityMap edge_centrality_map,
sl@0
   290
                                      IncomingMap incoming, // P
sl@0
   291
                                      DistanceMap distance,         // d
sl@0
   292
                                      DependencyMap dependency,     // delta
sl@0
   293
                                      PathCountMap path_count,      // sigma
sl@0
   294
                                      VertexIndexMap vertex_index,
sl@0
   295
                                      ShortestPaths shortest_paths)
sl@0
   296
  {
sl@0
   297
    typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
   298
    typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
sl@0
   299
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
sl@0
   300
sl@0
   301
    // Initialize centrality
sl@0
   302
    init_centrality_map(vertices(g), centrality);
sl@0
   303
    init_centrality_map(edges(g), edge_centrality_map);
sl@0
   304
sl@0
   305
    std::stack<vertex_descriptor> ordered_vertices;
sl@0
   306
    vertex_iterator s, s_end;
sl@0
   307
    for (tie(s, s_end) = vertices(g); s != s_end; ++s) {
sl@0
   308
      // Initialize for this iteration
sl@0
   309
      vertex_iterator w, w_end;
sl@0
   310
      for (tie(w, w_end) = vertices(g); w != w_end; ++w) {
sl@0
   311
        incoming[*w].clear();
sl@0
   312
        put(path_count, *w, 0);
sl@0
   313
        put(dependency, *w, 0);
sl@0
   314
      }
sl@0
   315
      put(path_count, *s, 1);
sl@0
   316
      
sl@0
   317
      // Execute the shortest paths algorithm. This will be either
sl@0
   318
      // Dijkstra's algorithm or a customized breadth-first search,
sl@0
   319
      // depending on whether the graph is weighted or unweighted.
sl@0
   320
      shortest_paths(g, *s, ordered_vertices, incoming, distance,
sl@0
   321
                     path_count, vertex_index);
sl@0
   322
      
sl@0
   323
      while (!ordered_vertices.empty()) {
sl@0
   324
        vertex_descriptor w = ordered_vertices.top();
sl@0
   325
        ordered_vertices.pop();
sl@0
   326
        
sl@0
   327
        typedef typename property_traits<IncomingMap>::value_type
sl@0
   328
          incoming_type;
sl@0
   329
        typedef typename incoming_type::iterator incoming_iterator;
sl@0
   330
        typedef typename property_traits<DependencyMap>::value_type 
sl@0
   331
          dependency_type;
sl@0
   332
        
sl@0
   333
        for (incoming_iterator vw = incoming[w].begin();
sl@0
   334
             vw != incoming[w].end(); ++vw) {
sl@0
   335
          vertex_descriptor v = source(*vw, g);
sl@0
   336
          dependency_type factor = dependency_type(get(path_count, v))
sl@0
   337
            / dependency_type(get(path_count, w));
sl@0
   338
          factor *= (dependency_type(1) + get(dependency, w));
sl@0
   339
          put(dependency, v, get(dependency, v) + factor);
sl@0
   340
          update_centrality(edge_centrality_map, *vw, factor);
sl@0
   341
        }
sl@0
   342
        
sl@0
   343
        if (w != *s) {
sl@0
   344
          update_centrality(centrality, w, get(dependency, w));
sl@0
   345
        }
sl@0
   346
      }
sl@0
   347
    }
sl@0
   348
sl@0
   349
    typedef typename graph_traits<Graph>::directed_category directed_category;
sl@0
   350
    const bool is_undirected = 
sl@0
   351
      is_convertible<directed_category*, undirected_tag*>::value;
sl@0
   352
    if (is_undirected) {
sl@0
   353
      divide_centrality_by_two(vertices(g), centrality);
sl@0
   354
      divide_centrality_by_two(edges(g), edge_centrality_map);
sl@0
   355
    }
sl@0
   356
  }
sl@0
   357
sl@0
   358
} } // end namespace detail::graph
sl@0
   359
sl@0
   360
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
sl@0
   361
         typename IncomingMap, typename DistanceMap, 
sl@0
   362
         typename DependencyMap, typename PathCountMap, 
sl@0
   363
         typename VertexIndexMap>
sl@0
   364
void 
sl@0
   365
brandes_betweenness_centrality(const Graph& g, 
sl@0
   366
                               CentralityMap centrality,     // C_B
sl@0
   367
                               EdgeCentralityMap edge_centrality_map,
sl@0
   368
                               IncomingMap incoming, // P
sl@0
   369
                               DistanceMap distance,         // d
sl@0
   370
                               DependencyMap dependency,     // delta
sl@0
   371
                               PathCountMap path_count,      // sigma
sl@0
   372
                               VertexIndexMap vertex_index)
sl@0
   373
{
sl@0
   374
  detail::graph::brandes_unweighted_shortest_paths shortest_paths;
sl@0
   375
sl@0
   376
  detail::graph::brandes_betweenness_centrality_impl(g, centrality, 
sl@0
   377
                                                     edge_centrality_map,
sl@0
   378
                                                     incoming, distance,
sl@0
   379
                                                     dependency, path_count,
sl@0
   380
                                                     vertex_index, 
sl@0
   381
                                                     shortest_paths);
sl@0
   382
}
sl@0
   383
sl@0
   384
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap, 
sl@0
   385
         typename IncomingMap, typename DistanceMap, 
sl@0
   386
         typename DependencyMap, typename PathCountMap, 
sl@0
   387
         typename VertexIndexMap, typename WeightMap>    
sl@0
   388
void 
sl@0
   389
brandes_betweenness_centrality(const Graph& g, 
sl@0
   390
                               CentralityMap centrality,     // C_B
sl@0
   391
                               EdgeCentralityMap edge_centrality_map,
sl@0
   392
                               IncomingMap incoming, // P
sl@0
   393
                               DistanceMap distance,         // d
sl@0
   394
                               DependencyMap dependency,     // delta
sl@0
   395
                               PathCountMap path_count,      // sigma
sl@0
   396
                               VertexIndexMap vertex_index,
sl@0
   397
                               WeightMap weight_map)
sl@0
   398
{
sl@0
   399
  detail::graph::brandes_dijkstra_shortest_paths<WeightMap>
sl@0
   400
    shortest_paths(weight_map);
sl@0
   401
sl@0
   402
  detail::graph::brandes_betweenness_centrality_impl(g, centrality, 
sl@0
   403
                                                     edge_centrality_map,
sl@0
   404
                                                     incoming, distance,
sl@0
   405
                                                     dependency, path_count,
sl@0
   406
                                                     vertex_index, 
sl@0
   407
                                                     shortest_paths);
sl@0
   408
}
sl@0
   409
sl@0
   410
namespace detail { namespace graph {
sl@0
   411
  template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
sl@0
   412
           typename WeightMap, typename VertexIndexMap>
sl@0
   413
  void 
sl@0
   414
  brandes_betweenness_centrality_dispatch2(const Graph& g,
sl@0
   415
                                           CentralityMap centrality,
sl@0
   416
                                           EdgeCentralityMap edge_centrality_map,
sl@0
   417
                                           WeightMap weight_map,
sl@0
   418
                                           VertexIndexMap vertex_index)
sl@0
   419
  {
sl@0
   420
    typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
sl@0
   421
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
sl@0
   422
    typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
sl@0
   423
    typedef typename mpl::if_c<(is_same<CentralityMap, 
sl@0
   424
                                        dummy_property_map>::value),
sl@0
   425
                                         EdgeCentralityMap, 
sl@0
   426
                               CentralityMap>::type a_centrality_map;
sl@0
   427
    typedef typename property_traits<a_centrality_map>::value_type 
sl@0
   428
      centrality_type;
sl@0
   429
sl@0
   430
    typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
sl@0
   431
    
sl@0
   432
    std::vector<std::vector<edge_descriptor> > incoming(V);
sl@0
   433
    std::vector<centrality_type> distance(V);
sl@0
   434
    std::vector<centrality_type> dependency(V);
sl@0
   435
    std::vector<degree_size_type> path_count(V);
sl@0
   436
sl@0
   437
    brandes_betweenness_centrality(
sl@0
   438
      g, centrality, edge_centrality_map,
sl@0
   439
      make_iterator_property_map(incoming.begin(), vertex_index),
sl@0
   440
      make_iterator_property_map(distance.begin(), vertex_index),
sl@0
   441
      make_iterator_property_map(dependency.begin(), vertex_index),
sl@0
   442
      make_iterator_property_map(path_count.begin(), vertex_index),
sl@0
   443
      vertex_index,
sl@0
   444
      weight_map);
sl@0
   445
  }
sl@0
   446
  
sl@0
   447
sl@0
   448
  template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
sl@0
   449
           typename VertexIndexMap>
sl@0
   450
  void 
sl@0
   451
  brandes_betweenness_centrality_dispatch2(const Graph& g,
sl@0
   452
                                           CentralityMap centrality,
sl@0
   453
                                           EdgeCentralityMap edge_centrality_map,
sl@0
   454
                                           VertexIndexMap vertex_index)
sl@0
   455
  {
sl@0
   456
    typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
sl@0
   457
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
sl@0
   458
    typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
sl@0
   459
    typedef typename mpl::if_c<(is_same<CentralityMap, 
sl@0
   460
                                        dummy_property_map>::value),
sl@0
   461
                                         EdgeCentralityMap, 
sl@0
   462
                               CentralityMap>::type a_centrality_map;
sl@0
   463
    typedef typename property_traits<a_centrality_map>::value_type 
sl@0
   464
      centrality_type;
sl@0
   465
sl@0
   466
    typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
sl@0
   467
    
sl@0
   468
    std::vector<std::vector<edge_descriptor> > incoming(V);
sl@0
   469
    std::vector<centrality_type> distance(V);
sl@0
   470
    std::vector<centrality_type> dependency(V);
sl@0
   471
    std::vector<degree_size_type> path_count(V);
sl@0
   472
sl@0
   473
    brandes_betweenness_centrality(
sl@0
   474
      g, centrality, edge_centrality_map,
sl@0
   475
      make_iterator_property_map(incoming.begin(), vertex_index),
sl@0
   476
      make_iterator_property_map(distance.begin(), vertex_index),
sl@0
   477
      make_iterator_property_map(dependency.begin(), vertex_index),
sl@0
   478
      make_iterator_property_map(path_count.begin(), vertex_index),
sl@0
   479
      vertex_index);
sl@0
   480
  }
sl@0
   481
sl@0
   482
  template<typename WeightMap>
sl@0
   483
  struct brandes_betweenness_centrality_dispatch1
sl@0
   484
  {
sl@0
   485
    template<typename Graph, typename CentralityMap, 
sl@0
   486
             typename EdgeCentralityMap, typename VertexIndexMap>
sl@0
   487
    static void 
sl@0
   488
    run(const Graph& g, CentralityMap centrality, 
sl@0
   489
        EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
sl@0
   490
        WeightMap weight_map)
sl@0
   491
    {
sl@0
   492
      brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map,
sl@0
   493
                                               weight_map, vertex_index);
sl@0
   494
    }
sl@0
   495
  };
sl@0
   496
sl@0
   497
  template<>
sl@0
   498
  struct brandes_betweenness_centrality_dispatch1<error_property_not_found>
sl@0
   499
  {
sl@0
   500
    template<typename Graph, typename CentralityMap, 
sl@0
   501
             typename EdgeCentralityMap, typename VertexIndexMap>
sl@0
   502
    static void 
sl@0
   503
    run(const Graph& g, CentralityMap centrality, 
sl@0
   504
        EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
sl@0
   505
        error_property_not_found)
sl@0
   506
    {
sl@0
   507
      brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map,
sl@0
   508
                                               vertex_index);
sl@0
   509
    }
sl@0
   510
  };
sl@0
   511
sl@0
   512
} } // end namespace detail::graph
sl@0
   513
sl@0
   514
template<typename Graph, typename Param, typename Tag, typename Rest>
sl@0
   515
void 
sl@0
   516
brandes_betweenness_centrality(const Graph& g, 
sl@0
   517
                               const bgl_named_params<Param,Tag,Rest>& params)
sl@0
   518
{
sl@0
   519
  typedef bgl_named_params<Param,Tag,Rest> named_params;
sl@0
   520
sl@0
   521
  typedef typename property_value<named_params, edge_weight_t>::type ew;
sl@0
   522
  detail::graph::brandes_betweenness_centrality_dispatch1<ew>::run(
sl@0
   523
    g, 
sl@0
   524
    choose_param(get_param(params, vertex_centrality), 
sl@0
   525
                 dummy_property_map()),
sl@0
   526
    choose_param(get_param(params, edge_centrality), 
sl@0
   527
                 dummy_property_map()),
sl@0
   528
    choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
sl@0
   529
    get_param(params, edge_weight));
sl@0
   530
}
sl@0
   531
sl@0
   532
template<typename Graph, typename CentralityMap>
sl@0
   533
void 
sl@0
   534
brandes_betweenness_centrality(const Graph& g, CentralityMap centrality)
sl@0
   535
{
sl@0
   536
  detail::graph::brandes_betweenness_centrality_dispatch2(
sl@0
   537
    g, centrality, dummy_property_map(), get(vertex_index, g));
sl@0
   538
}
sl@0
   539
sl@0
   540
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap>
sl@0
   541
void 
sl@0
   542
brandes_betweenness_centrality(const Graph& g, CentralityMap centrality,
sl@0
   543
                               EdgeCentralityMap edge_centrality_map)
sl@0
   544
{
sl@0
   545
  detail::graph::brandes_betweenness_centrality_dispatch2(
sl@0
   546
    g, centrality, edge_centrality_map, get(vertex_index, g));
sl@0
   547
}
sl@0
   548
sl@0
   549
/**
sl@0
   550
 * Converts "absolute" betweenness centrality (as computed by the
sl@0
   551
 * brandes_betweenness_centrality algorithm) in the centrality map
sl@0
   552
 * into "relative" centrality. The result is placed back into the
sl@0
   553
 * given centrality map.
sl@0
   554
 */
sl@0
   555
template<typename Graph, typename CentralityMap>
sl@0
   556
void 
sl@0
   557
relative_betweenness_centrality(const Graph& g, CentralityMap centrality)
sl@0
   558
{
sl@0
   559
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
   560
  typedef typename property_traits<CentralityMap>::value_type centrality_type;
sl@0
   561
sl@0
   562
  typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
sl@0
   563
  centrality_type factor = centrality_type(2)/centrality_type(n*n - 3*n + 2);
sl@0
   564
  vertex_iterator v, v_end;
sl@0
   565
  for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
sl@0
   566
    put(centrality, *v, factor * get(centrality, *v));
sl@0
   567
  }
sl@0
   568
}
sl@0
   569
sl@0
   570
// Compute the central point dominance of a graph.
sl@0
   571
template<typename Graph, typename CentralityMap>
sl@0
   572
typename property_traits<CentralityMap>::value_type
sl@0
   573
central_point_dominance(const Graph& g, CentralityMap centrality)
sl@0
   574
{
sl@0
   575
  using std::max;
sl@0
   576
sl@0
   577
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
   578
  typedef typename property_traits<CentralityMap>::value_type centrality_type;
sl@0
   579
sl@0
   580
  typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
sl@0
   581
sl@0
   582
  // Find max centrality
sl@0
   583
  centrality_type max_centrality(0);
sl@0
   584
  vertex_iterator v, v_end;
sl@0
   585
  for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
sl@0
   586
    max_centrality = (max)(max_centrality, get(centrality, *v));
sl@0
   587
  }
sl@0
   588
sl@0
   589
  // Compute central point dominance
sl@0
   590
  centrality_type sum(0);
sl@0
   591
  for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
sl@0
   592
    sum += (max_centrality - get(centrality, *v));
sl@0
   593
  }
sl@0
   594
  return sum/(n-1);
sl@0
   595
}
sl@0
   596
sl@0
   597
} // end namespace boost
sl@0
   598
sl@0
   599
#endif // BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP