diff -r 666f914201fb -r 2fe1408b6811 epoc32/include/stdapis/boost/graph/betweenness_centrality.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/epoc32/include/stdapis/boost/graph/betweenness_centrality.hpp Tue Mar 16 16:12:26 2010 +0000 @@ -0,0 +1,599 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP +#define BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace detail { namespace graph { + + /** + * Customized visitor passed to Dijkstra's algorithm by Brandes' + * betweenness centrality algorithm. This visitor is responsible for + * keeping track of the order in which vertices are discovered, the + * predecessors on the shortest path(s) to a vertex, and the number + * of shortest paths. + */ + template + struct brandes_dijkstra_visitor : public bfs_visitor<> + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + + brandes_dijkstra_visitor(std::stack& ordered_vertices, + WeightMap weight, + IncomingMap incoming, + DistanceMap distance, + PathCountMap path_count) + : ordered_vertices(ordered_vertices), weight(weight), + incoming(incoming), distance(distance), + path_count(path_count) + { } + + /** + * Whenever an edge e = (v, w) is relaxed, the incoming edge list + * for w is set to {(v, w)} and the shortest path count of w is set to + * the number of paths that reach {v}. + */ + void edge_relaxed(edge_descriptor e, const Graph& g) + { + vertex_descriptor v = source(e, g), w = target(e, g); + incoming[w].clear(); + incoming[w].push_back(e); + put(path_count, w, get(path_count, v)); + } + + /** + * If an edge e = (v, w) was not relaxed, it may still be the case + * that we've found more equally-short paths, so include {(v, w)} in the + * incoming edges of w and add all of the shortest paths to v to the + * shortest path count of w. + */ + void edge_not_relaxed(edge_descriptor e, const Graph& g) + { + typedef typename property_traits::value_type weight_type; + typedef typename property_traits::value_type distance_type; + vertex_descriptor v = source(e, g), w = target(e, g); + distance_type d_v = get(distance, v), d_w = get(distance, w); + weight_type w_e = get(weight, e); + + closed_plus combine; + if (d_w == combine(d_v, w_e)) { + put(path_count, w, get(path_count, w) + get(path_count, v)); + incoming[w].push_back(e); + } + } + + /// Keep track of vertices as they are reached + void examine_vertex(vertex_descriptor w, const Graph&) + { + ordered_vertices.push(w); + } + + private: + std::stack& ordered_vertices; + WeightMap weight; + IncomingMap incoming; + DistanceMap distance; + PathCountMap path_count; + }; + + /** + * Function object that calls Dijkstra's shortest paths algorithm + * using the Dijkstra visitor for the Brandes betweenness centrality + * algorithm. + */ + template + struct brandes_dijkstra_shortest_paths + { + brandes_dijkstra_shortest_paths(WeightMap weight_map) + : weight_map(weight_map) { } + + template + void + operator()(Graph& g, + typename graph_traits::vertex_descriptor s, + std::stack::vertex_descriptor>& ov, + IncomingMap incoming, + DistanceMap distance, + PathCountMap path_count, + VertexIndexMap vertex_index) + { + typedef brandes_dijkstra_visitor visitor_type; + visitor_type visitor(ov, weight_map, incoming, distance, path_count); + + dijkstra_shortest_paths(g, s, + boost::weight_map(weight_map) + .vertex_index_map(vertex_index) + .distance_map(distance) + .visitor(visitor)); + } + + private: + WeightMap weight_map; + }; + + /** + * Function object that invokes breadth-first search for the + * unweighted form of the Brandes betweenness centrality algorithm. + */ + struct brandes_unweighted_shortest_paths + { + /** + * Customized visitor passed to breadth-first search, which + * records predecessor and the number of shortest paths to each + * vertex. + */ + template + struct visitor_type : public bfs_visitor<> + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + + visitor_type(IncomingMap incoming, DistanceMap distance, + PathCountMap path_count, + std::stack& ordered_vertices) + : incoming(incoming), distance(distance), + path_count(path_count), ordered_vertices(ordered_vertices) { } + + /// Keep track of vertices as they are reached + void examine_vertex(vertex_descriptor v, Graph&) + { + ordered_vertices.push(v); + } + + /** + * Whenever an edge e = (v, w) is labelled a tree edge, the + * incoming edge list for w is set to {(v, w)} and the shortest + * path count of w is set to the number of paths that reach {v}. + */ + void tree_edge(edge_descriptor e, Graph& g) + { + vertex_descriptor v = source(e, g); + vertex_descriptor w = target(e, g); + put(distance, w, get(distance, v) + 1); + + put(path_count, w, get(path_count, v)); + incoming[w].push_back(e); + } + + /** + * If an edge e = (v, w) is not a tree edge, it may still be the + * case that we've found more equally-short paths, so include (v, w) + * in the incoming edge list of w and add all of the shortest + * paths to v to the shortest path count of w. + */ + void non_tree_edge(edge_descriptor e, Graph& g) + { + vertex_descriptor v = source(e, g); + vertex_descriptor w = target(e, g); + if (get(distance, w) == get(distance, v) + 1) { + put(path_count, w, get(path_count, w) + get(path_count, v)); + incoming[w].push_back(e); + } + } + + private: + IncomingMap incoming; + DistanceMap distance; + PathCountMap path_count; + std::stack& ordered_vertices; + }; + + template + void + operator()(Graph& g, + typename graph_traits::vertex_descriptor s, + std::stack::vertex_descriptor>& ov, + IncomingMap incoming, + DistanceMap distance, + PathCountMap path_count, + VertexIndexMap vertex_index) + { + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + + visitor_type + visitor(incoming, distance, path_count, ov); + + std::vector + colors(num_vertices(g), color_traits::white()); + boost::queue Q; + breadth_first_visit(g, s, Q, visitor, + make_iterator_property_map(colors.begin(), + vertex_index)); + } + }; + + // When the edge centrality map is a dummy property map, no + // initialization is needed. + template + inline void + init_centrality_map(std::pair, dummy_property_map) { } + + // When we have a real edge centrality map, initialize all of the + // centralities to zero. + template + void + init_centrality_map(std::pair keys, Centrality centrality_map) + { + typedef typename property_traits::value_type + centrality_type; + while (keys.first != keys.second) { + put(centrality_map, *keys.first, centrality_type(0)); + ++keys.first; + } + } + + // When the edge centrality map is a dummy property map, no update + // is performed. + template + inline void + update_centrality(dummy_property_map, const Key&, const T&) { } + + // When we have a real edge centrality map, add the value to the map + template + inline void + update_centrality(CentralityMap centrality_map, Key k, const T& x) + { put(centrality_map, k, get(centrality_map, k) + x); } + + template + inline void + divide_centrality_by_two(std::pair, dummy_property_map) {} + + template + inline void + divide_centrality_by_two(std::pair keys, + CentralityMap centrality_map) + { + typename property_traits::value_type two(2); + while (keys.first != keys.second) { + put(centrality_map, *keys.first, get(centrality_map, *keys.first) / two); + ++keys.first; + } + } + + template + void + brandes_betweenness_centrality_impl(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index, + ShortestPaths shortest_paths) + { + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::edge_iterator edge_iterator; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + + // Initialize centrality + init_centrality_map(vertices(g), centrality); + init_centrality_map(edges(g), edge_centrality_map); + + std::stack ordered_vertices; + vertex_iterator s, s_end; + for (tie(s, s_end) = vertices(g); s != s_end; ++s) { + // Initialize for this iteration + vertex_iterator w, w_end; + for (tie(w, w_end) = vertices(g); w != w_end; ++w) { + incoming[*w].clear(); + put(path_count, *w, 0); + put(dependency, *w, 0); + } + put(path_count, *s, 1); + + // Execute the shortest paths algorithm. This will be either + // Dijkstra's algorithm or a customized breadth-first search, + // depending on whether the graph is weighted or unweighted. + shortest_paths(g, *s, ordered_vertices, incoming, distance, + path_count, vertex_index); + + while (!ordered_vertices.empty()) { + vertex_descriptor w = ordered_vertices.top(); + ordered_vertices.pop(); + + typedef typename property_traits::value_type + incoming_type; + typedef typename incoming_type::iterator incoming_iterator; + typedef typename property_traits::value_type + dependency_type; + + for (incoming_iterator vw = incoming[w].begin(); + vw != incoming[w].end(); ++vw) { + vertex_descriptor v = source(*vw, g); + dependency_type factor = dependency_type(get(path_count, v)) + / dependency_type(get(path_count, w)); + factor *= (dependency_type(1) + get(dependency, w)); + put(dependency, v, get(dependency, v) + factor); + update_centrality(edge_centrality_map, *vw, factor); + } + + if (w != *s) { + update_centrality(centrality, w, get(dependency, w)); + } + } + } + + typedef typename graph_traits::directed_category directed_category; + const bool is_undirected = + is_convertible::value; + if (is_undirected) { + divide_centrality_by_two(vertices(g), centrality); + divide_centrality_by_two(edges(g), edge_centrality_map); + } + } + +} } // end namespace detail::graph + +template +void +brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index) +{ + detail::graph::brandes_unweighted_shortest_paths shortest_paths; + + detail::graph::brandes_betweenness_centrality_impl(g, centrality, + edge_centrality_map, + incoming, distance, + dependency, path_count, + vertex_index, + shortest_paths); +} + +template +void +brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index, + WeightMap weight_map) +{ + detail::graph::brandes_dijkstra_shortest_paths + shortest_paths(weight_map); + + detail::graph::brandes_betweenness_centrality_impl(g, centrality, + edge_centrality_map, + incoming, distance, + dependency, path_count, + vertex_index, + shortest_paths); +} + +namespace detail { namespace graph { + template + void + brandes_betweenness_centrality_dispatch2(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, + WeightMap weight_map, + VertexIndexMap vertex_index) + { + typedef typename graph_traits::degree_size_type degree_size_type; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename mpl::if_c<(is_same::value), + EdgeCentralityMap, + CentralityMap>::type a_centrality_map; + typedef typename property_traits::value_type + centrality_type; + + typename graph_traits::vertices_size_type V = num_vertices(g); + + std::vector > incoming(V); + std::vector distance(V); + std::vector dependency(V); + std::vector path_count(V); + + brandes_betweenness_centrality( + g, centrality, edge_centrality_map, + make_iterator_property_map(incoming.begin(), vertex_index), + make_iterator_property_map(distance.begin(), vertex_index), + make_iterator_property_map(dependency.begin(), vertex_index), + make_iterator_property_map(path_count.begin(), vertex_index), + vertex_index, + weight_map); + } + + + template + void + brandes_betweenness_centrality_dispatch2(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, + VertexIndexMap vertex_index) + { + typedef typename graph_traits::degree_size_type degree_size_type; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename mpl::if_c<(is_same::value), + EdgeCentralityMap, + CentralityMap>::type a_centrality_map; + typedef typename property_traits::value_type + centrality_type; + + typename graph_traits::vertices_size_type V = num_vertices(g); + + std::vector > incoming(V); + std::vector distance(V); + std::vector dependency(V); + std::vector path_count(V); + + brandes_betweenness_centrality( + g, centrality, edge_centrality_map, + make_iterator_property_map(incoming.begin(), vertex_index), + make_iterator_property_map(distance.begin(), vertex_index), + make_iterator_property_map(dependency.begin(), vertex_index), + make_iterator_property_map(path_count.begin(), vertex_index), + vertex_index); + } + + template + struct brandes_betweenness_centrality_dispatch1 + { + template + static void + run(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, + WeightMap weight_map) + { + brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, + weight_map, vertex_index); + } + }; + + template<> + struct brandes_betweenness_centrality_dispatch1 + { + template + static void + run(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, + error_property_not_found) + { + brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, + vertex_index); + } + }; + +} } // end namespace detail::graph + +template +void +brandes_betweenness_centrality(const Graph& g, + const bgl_named_params& params) +{ + typedef bgl_named_params named_params; + + typedef typename property_value::type ew; + detail::graph::brandes_betweenness_centrality_dispatch1::run( + g, + choose_param(get_param(params, vertex_centrality), + dummy_property_map()), + choose_param(get_param(params, edge_centrality), + dummy_property_map()), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + get_param(params, edge_weight)); +} + +template +void +brandes_betweenness_centrality(const Graph& g, CentralityMap centrality) +{ + detail::graph::brandes_betweenness_centrality_dispatch2( + g, centrality, dummy_property_map(), get(vertex_index, g)); +} + +template +void +brandes_betweenness_centrality(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map) +{ + detail::graph::brandes_betweenness_centrality_dispatch2( + g, centrality, edge_centrality_map, get(vertex_index, g)); +} + +/** + * Converts "absolute" betweenness centrality (as computed by the + * brandes_betweenness_centrality algorithm) in the centrality map + * into "relative" centrality. The result is placed back into the + * given centrality map. + */ +template +void +relative_betweenness_centrality(const Graph& g, CentralityMap centrality) +{ + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename property_traits::value_type centrality_type; + + typename graph_traits::vertices_size_type n = num_vertices(g); + centrality_type factor = centrality_type(2)/centrality_type(n*n - 3*n + 2); + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + put(centrality, *v, factor * get(centrality, *v)); + } +} + +// Compute the central point dominance of a graph. +template +typename property_traits::value_type +central_point_dominance(const Graph& g, CentralityMap centrality) +{ + using std::max; + + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename property_traits::value_type centrality_type; + + typename graph_traits::vertices_size_type n = num_vertices(g); + + // Find max centrality + centrality_type max_centrality(0); + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + max_centrality = (max)(max_centrality, get(centrality, *v)); + } + + // Compute central point dominance + centrality_type sum(0); + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + sum += (max_centrality - get(centrality, *v)); + } + return sum/(n-1); +} + +} // end namespace boost + +#endif // BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP