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