From cef818dbb36b340295de108b6533235e999dff49 Mon Sep 17 00:00:00 2001 From: Javier Dehesa Date: Fri, 25 Apr 2014 10:50:22 +0200 Subject: [PATCH 1/6] Support for edge multiplicities in brandes_betweenness_centrality Ticket #9935 --- doc/betweenness_centrality.html | 30 ++- .../boost/graph/betweenness_centrality.hpp | 198 ++++++++++++++++-- include/boost/graph/named_function_params.hpp | 2 + .../reference/betweenness_centrality.qbk | 16 ++ 4 files changed, 222 insertions(+), 24 deletions(-) diff --git a/doc/betweenness_centrality.html b/doc/betweenness_centrality.html index 9b1a27d01..1b697a4bc 100644 --- a/doc/betweenness_centrality.html +++ b/doc/betweenness_centrality.html @@ -57,6 +57,19 @@

(Python)brandes_betweenness_centralit VertexIndexMap vertex_index, WeightMap weight_map); +template<typename Graph, typename CentralityMap, typename EdgeCentralityMap, + typename IncomingMap, typename DistanceMap, typename DependencyMap, + typename PathCountMap, typename VertexIndexMap, typename WeightMap> +void +brandes_betweenness_centrality(const Graph& g, CentralityMap centrality_map, + EdgeCentralityMap edge_centrality, + IncomingMap incoming, + DistanceMap distance, DependencyMap dependency, + PathCountMap path_count, + VertexIndexMap vertex_index, + WeightMap weight_map, + MultiplicityMap multiplicity_map); + // helper functions template<typename Graph, typename CentralityMap> void @@ -271,7 +284,7 @@

Named parameters

Python: Unsupported parameter. -IN: weight_map(WeightMap w_map) +IN: weight_map(WeightMap weight_map)
The weight or ``length'' of each edge in the graph. The weights must all be non-negative, and the algorithm will throw a @@ -286,6 +299,21 @@

Named parameters

Python: If supplied, must be an edge_double_map for the graph.
+IN: multiplicity_map(MultiplicityMap multiplicity_map) +
+ The multiplicity of each edge in the graph. The multiplicities + must all be positive, and the algorithm will throw a + negative_edge + exception is one of the edges is non-positive. + The type MultiplicityMap must be a model of + Readable Property Map. The edge descriptor type of + the graph needs to be usable as the key type for the multiplicity + map. The value type for this map must be + the same as the value type of the distance map.
+ Default: All edge multiplicities are assumed to be one. + Python: Unsupported parameter. +
+

Complexity

The time complexity is O(VE) for unweighted graphs and O(VE + V(V+E) log V) for weighted graphs. The space complexity diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index d596d5a28..eadf7e2b3 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -35,20 +35,22 @@ namespace detail { namespace graph { * predecessors on the shortest path(s) to a vertex, and the number * of shortest paths. */ - template + template struct brandes_dijkstra_visitor : public bfs_visitor<> { typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename property_traits::value_type multiplicity_type; brandes_dijkstra_visitor(std::stack& ordered_vertices, WeightMap weight, + MultiplicityMap multiplicity, IncomingMap incoming, DistanceMap distance, PathCountMap path_count) - : ordered_vertices(ordered_vertices), weight(weight), - incoming(incoming), distance(distance), + : ordered_vertices(ordered_vertices), weight(weight), + multiplicity(multiplicity), incoming(incoming), distance(distance), path_count(path_count) { } @@ -59,10 +61,11 @@ namespace detail { namespace graph { */ void edge_relaxed(edge_descriptor e, const Graph& g) { + check_edge_multiplicity(e, 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)); + put(path_count, w, get(multiplicity, e) * get(path_count, v)); } /** @@ -73,6 +76,8 @@ namespace detail { namespace graph { */ void edge_not_relaxed(edge_descriptor e, const Graph& g) { + check_edge_multiplicity(e, 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); @@ -81,7 +86,8 @@ namespace detail { namespace graph { closed_plus combine; if (d_w == combine(d_v, w_e)) { - put(path_count, w, get(path_count, w) + get(path_count, v)); + put(path_count, w, + get(path_count, w) + get(multiplicity, e) * get(path_count, v)); incoming[w].push_back(e); } } @@ -93,8 +99,23 @@ namespace detail { namespace graph { } private: + /** + * Check if the multiplicity of an edge is positive and throw an exception + * if it is not. + */ + void check_edge_multiplicity(edge_descriptor e, const Graph& g) { + // copied from dijkstra_shortest_paths + std::less_equal compare; + closed_plus combine; + multiplicity_type zero = multiplicity_type(); + if (compare(combine(zero, get(multiplicity, e)), zero)) { + boost::throw_exception(negative_edge()); + } + } + std::stack& ordered_vertices; WeightMap weight; + MultiplicityMap multiplicity; IncomingMap incoming; DistanceMap distance; PathCountMap path_count; @@ -105,11 +126,11 @@ namespace detail { namespace graph { * using the Dijkstra visitor for the Brandes betweenness centrality * algorithm. */ - template + template struct brandes_dijkstra_shortest_paths { - brandes_dijkstra_shortest_paths(WeightMap weight_map) - : weight_map(weight_map) { } + brandes_dijkstra_shortest_paths(WeightMap weight_map, MultiplicityMap multiplicity_map) + : weight_map(weight_map), multiplicity_map(multiplicity_map) { } template @@ -122,9 +143,9 @@ namespace detail { namespace graph { PathCountMap path_count, VertexIndexMap vertex_index) { - typedef brandes_dijkstra_visitor visitor_type; - visitor_type visitor(ov, weight_map, incoming, distance, path_count); + visitor_type visitor(ov, weight_map, multiplicity_map, incoming, distance, path_count); dijkstra_shortest_paths(g, s, boost::weight_map(weight_map) @@ -135,6 +156,7 @@ namespace detail { namespace graph { private: WeightMap weight_map; + MultiplicityMap multiplicity_map; }; /** @@ -280,6 +302,13 @@ namespace detail { namespace graph { } } + template + inline boost::static_property_map::edge_descriptor> + make_static_one_property(const Graph& g) { + typedef typename graph_traits::edge_descriptor edge_descriptor; + return boost::make_static_property_map(ValueType(1)); + } + template::edge_descriptor edge_descriptor; + typedef typename property_traits::value_type multiplicity_type; + + static_property_map + multiplicity_map = detail::graph::make_static_one_property(g); + + multiplicity_map = detail::graph::make_static_one_property(g); + brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, + incoming, distance, dependency, + path_count, vertex_index, shortest_paths, + multiplicity_map); + } + + 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, + MultiplicityMap multiplicity_map) { typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; @@ -335,6 +395,7 @@ namespace detail { namespace graph { vertex_descriptor v = source(*vw, g); dependency_type factor = dependency_type(get(path_count, v)) / dependency_type(get(path_count, w)); + factor *= dependency_type(get(multiplicity_map, *vw)); factor *= (dependency_type(1) + get(dependency, w)); put(dependency, v, get(dependency, v) + factor); update_centrality(edge_centrality_map, *vw, factor); @@ -398,25 +459,56 @@ brandes_betweenness_centrality(const Graph& g, WeightMap weight_map BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { - detail::graph::brandes_dijkstra_shortest_paths - shortest_paths(weight_map); + // default constant multiplicity of one + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename property_traits::value_type multiplicity_type; + + static_property_map + multiplicity_map = detail::graph::make_static_one_property(g); + + brandes_betweenness_centrality(g, centrality, edge_centrality_map, + incoming, distance, dependency, path_count, + vertex_index, weight_map, multiplicity_map); +} + +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, + MultiplicityMap multiplicity_map + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) +{ + detail::graph::brandes_dijkstra_shortest_paths + shortest_paths(weight_map, multiplicity_map); detail::graph::brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, incoming, distance, dependency, path_count, vertex_index, - shortest_paths); + shortest_paths, + multiplicity_map); } namespace detail { namespace graph { template + typename WeightMap, typename MultiplicityMap, typename VertexIndexMap> void brandes_betweenness_centrality_dispatch2(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map, WeightMap weight_map, + MultiplicityMap multiplicity_map, VertexIndexMap vertex_index) { typedef typename graph_traits::degree_size_type degree_size_type; @@ -442,7 +534,8 @@ namespace detail { namespace graph { make_iterator_property_map(dependency.begin(), vertex_index), make_iterator_property_map(path_count.begin(), vertex_index), vertex_index, - weight_map); + weight_map, + multiplicity_map); } @@ -479,7 +572,7 @@ namespace detail { namespace graph { vertex_index); } - template + template struct brandes_betweenness_centrality_dispatch1 { 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, param_not_found) + { + // default constant multiplicity of one + 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 + multiplicity_type; + + static_property_map + multiplicity_map = detail::graph::make_static_one_property(g); + + brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, + weight_map, multiplicity_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, + param_not_found, MultiplicityMap multiplicity_map) { + // default constant weight of one + 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 + weight_type; + + static_property_map + weight_map = detail::graph::make_static_one_property(g); + brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, - weight_map, vertex_index); + weight_map, multiplicity_map, + vertex_index); } }; template<> - struct brandes_betweenness_centrality_dispatch1 + struct brandes_betweenness_centrality_dispatch1 { template static void run(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, - param_not_found) + param_not_found, param_not_found) { brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, vertex_index); @@ -530,14 +680,16 @@ brandes_betweenness_centrality(const Graph& g, typedef bgl_named_params named_params; typedef typename get_param_type::type ew; - detail::graph::brandes_betweenness_centrality_dispatch1::run( + typedef typename get_param_type::type em; + 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)); + get_param(params, edge_weight), + get_param(params, edge_multiplicity_t())); } // disable_if is required to work around problem with MSVC 7.1 (it seems to not diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 26d3d5e40..b3dda72d4 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -28,6 +28,7 @@ namespace boost { struct parity_map_t { }; + struct edge_multiplicity_t { }; struct vertex_assignment_map_t { }; struct distance_compare_t { }; struct distance_combine_t { }; @@ -76,6 +77,7 @@ namespace boost { BOOST_BGL_ONE_PARAM_CREF(edge_color_map, edge_color) \ BOOST_BGL_ONE_PARAM_CREF(capacity_map, edge_capacity) \ BOOST_BGL_ONE_PARAM_CREF(residual_capacity_map, edge_residual_capacity) \ + BOOST_BGL_ONE_PARAM_CREF(multiplicity_map, edge_multiplicity) \ BOOST_BGL_ONE_PARAM_CREF(reverse_edge_map, edge_reverse) \ BOOST_BGL_ONE_PARAM_CREF(discover_time_map, vertex_discover_time) \ BOOST_BGL_ONE_PARAM_CREF(lowpoint_map, vertex_lowpoint) \ diff --git a/quickbook/reference/betweenness_centrality.qbk b/quickbook/reference/betweenness_centrality.qbk index 3c65610a4..93c25a0d3 100644 --- a/quickbook/reference/betweenness_centrality.qbk +++ b/quickbook/reference/betweenness_centrality.qbk @@ -182,4 +182,20 @@ interface. VertexIndexMap vertex_index, WeightMap weight_map) + template + void + brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality, + IncomingMap incoming, + DistanceMap distance, + DependencyMap dependency, + PathCountMap path_count, + VertexIndexMap vertex_index, + WeightMap weight_map, + MultiplicityMap multiplicity_map) + [endsect] From b625638c679c8f12ac100bd68f89b526baa6aca4 Mon Sep 17 00:00:00 2001 From: Javier Dehesa Date: Wed, 30 Apr 2014 13:57:14 +0200 Subject: [PATCH 2/6] Betweenness with multiplicitites and without weights Now betweenness with multiplicities can be computed using the unweighted version of the algorithm, if no weights are given (using named parameters or passing a dummy_property_map as weight). --- .../boost/graph/betweenness_centrality.hpp | 142 ++++++++++++------ 1 file changed, 93 insertions(+), 49 deletions(-) diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index eadf7e2b3..603909cb4 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -28,6 +28,23 @@ namespace boost { namespace detail { namespace graph { + + /** + * Check if an edge property is positive and throw an exception + * if it is not. + */ + template + void check_edge_positive(Edge e, Property property) { + // copied from dijkstra_shortest_paths + typedef typename property_traits::value_type property_type; + std::less_equal compare; + closed_plus combine; + property_type zero = property_type(); + if (compare(combine(zero, get(property, e)), zero)) { + boost::throw_exception(negative_edge()); + } + } + /** * Customized visitor passed to Dijkstra's algorithm by Brandes' * betweenness centrality algorithm. This visitor is responsible for @@ -61,7 +78,8 @@ namespace detail { namespace graph { */ void edge_relaxed(edge_descriptor e, const Graph& g) { - check_edge_multiplicity(e, g); + check_edge_positive(e, multiplicity); + vertex_descriptor v = source(e, g), w = target(e, g); incoming[w].clear(); incoming[w].push_back(e); @@ -76,7 +94,7 @@ namespace detail { namespace graph { */ void edge_not_relaxed(edge_descriptor e, const Graph& g) { - check_edge_multiplicity(e, g); + check_edge_positive(e, multiplicity); typedef typename property_traits::value_type weight_type; typedef typename property_traits::value_type distance_type; @@ -99,20 +117,6 @@ namespace detail { namespace graph { } private: - /** - * Check if the multiplicity of an edge is positive and throw an exception - * if it is not. - */ - void check_edge_multiplicity(edge_descriptor e, const Graph& g) { - // copied from dijkstra_shortest_paths - std::less_equal compare; - closed_plus combine; - multiplicity_type zero = multiplicity_type(); - if (compare(combine(zero, get(multiplicity, e)), zero)) { - boost::throw_exception(negative_edge()); - } - } - std::stack& ordered_vertices; WeightMap weight; MultiplicityMap multiplicity; @@ -163,8 +167,14 @@ namespace detail { namespace graph { * Function object that invokes breadth-first search for the * unweighted form of the Brandes betweenness centrality algorithm. */ + template struct brandes_unweighted_shortest_paths { + + brandes_unweighted_shortest_paths(MultiplicityMap multiplicity_map) + : multiplicity_map(multiplicity_map) + { } + /** * Customized visitor passed to breadth-first search, which * records predecessor and the number of shortest paths to each @@ -180,9 +190,11 @@ namespace detail { namespace graph { visitor_type(IncomingMap incoming, DistanceMap distance, PathCountMap path_count, - std::stack& ordered_vertices) + std::stack& ordered_vertices, + MultiplicityMap multiplicity) : incoming(incoming), distance(distance), - path_count(path_count), ordered_vertices(ordered_vertices) { } + path_count(path_count), ordered_vertices(ordered_vertices), + multiplicity(multiplicity) { } /// Keep track of vertices as they are reached void examine_vertex(vertex_descriptor v, Graph&) @@ -197,11 +209,13 @@ namespace detail { namespace graph { */ void tree_edge(edge_descriptor e, Graph& g) { + check_edge_positive(e, multiplicity); + 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)); + put(path_count, w, get(multiplicity, e) * get(path_count, v)); incoming[w].push_back(e); } @@ -213,10 +227,13 @@ namespace detail { namespace graph { */ void non_tree_edge(edge_descriptor e, Graph& g) { + check_edge_positive(e, multiplicity); + 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)); + put(path_count, w, + get(path_count, w) + get(multiplicity, e) * get(path_count, v)); incoming[w].push_back(e); } } @@ -226,6 +243,7 @@ namespace detail { namespace graph { DistanceMap distance; PathCountMap path_count; std::stack& ordered_vertices; + MultiplicityMap multiplicity; }; template - visitor(incoming, distance, path_count, ov); + visitor(incoming, distance, path_count, ov, multiplicity_map); std::vector colors(num_vertices(g), color_traits::white()); @@ -252,6 +270,30 @@ namespace detail { namespace graph { make_iterator_property_map(colors.begin(), vertex_index)); } + + private: + MultiplicityMap multiplicity_map; + }; + + template + struct make_shortest_paths + { + typedef brandes_dijkstra_shortest_paths type; + type operator()(WeightMap weight_map, MultiplicityMap multiplicity_map) + { + return brandes_dijkstra_shortest_paths + (weight_map, multiplicity_map); + } + }; + + template + struct make_shortest_paths + { + typedef brandes_unweighted_shortest_paths type; + type operator()(dummy_property_map weight_map, MultiplicityMap multiplicity_map) + { + return brandes_unweighted_shortest_paths(multiplicity_map); + } }; // When the edge centrality map is a dummy property map, no @@ -302,11 +344,13 @@ namespace detail { namespace graph { } } - template - inline boost::static_property_map::edge_descriptor> + template + inline boost::static_property_map::value_type, + typename graph_traits::edge_descriptor> make_static_one_property(const Graph& g) { typedef typename graph_traits::edge_descriptor edge_descriptor; - return boost::make_static_property_map(ValueType(1)); + typedef typename property_traits::value_type property_type; + return boost::make_static_property_map(property_type(1)); } template::edge_descriptor edge_descriptor; typedef typename property_traits::value_type multiplicity_type; + typedef static_property_map MultiplicityMap; - static_property_map - multiplicity_map = detail::graph::make_static_one_property(g); + MultiplicityMap multiplicity_map = + detail::graph::make_static_one_property(g); - multiplicity_map = detail::graph::make_static_one_property(g); brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, incoming, distance, dependency, path_count, vertex_index, shortest_paths, @@ -433,7 +477,16 @@ brandes_betweenness_centrality(const Graph& g, VertexIndexMap vertex_index BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { - detail::graph::brandes_unweighted_shortest_paths shortest_paths; + // default constant multiplicity of one + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename property_traits::value_type multiplicity_type; + typedef static_property_map MultiplicityMap; + + MultiplicityMap multiplicity_map = + detail::graph::make_static_one_property(g); + + detail::graph::brandes_unweighted_shortest_paths + shortest_paths(multiplicity_map); detail::graph::brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, @@ -462,9 +515,10 @@ brandes_betweenness_centrality(const Graph& g, // default constant multiplicity of one typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename property_traits::value_type multiplicity_type; + typedef static_property_map MultiplicityMap; - static_property_map - multiplicity_map = detail::graph::make_static_one_property(g); + MultiplicityMap multiplicity_map = + detail::graph::make_static_one_property(g); brandes_betweenness_centrality(g, centrality, edge_centrality_map, incoming, distance, dependency, path_count, @@ -488,8 +542,9 @@ brandes_betweenness_centrality(const Graph& g, MultiplicityMap multiplicity_map BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { - detail::graph::brandes_dijkstra_shortest_paths - shortest_paths(weight_map, multiplicity_map); + typedef detail::graph::make_shortest_paths make; + typedef typename make::type ShortestPaths; + ShortestPaths shortest_paths = make()(weight_map, multiplicity_map); detail::graph::brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, @@ -604,11 +659,11 @@ namespace detail { namespace graph { dummy_property_map>::value), EdgeCentralityMap, CentralityMap>::type a_centrality_map; - typedef typename property_traits::value_type - multiplicity_type; + typedef typename property_traits::value_type multiplicity_type; + typedef static_property_map MultiplicityMap; - static_property_map - multiplicity_map = detail::graph::make_static_one_property(g); + MultiplicityMap multiplicity_map = + detail::graph::make_static_one_property(g); brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, weight_map, multiplicity_map, @@ -626,20 +681,9 @@ namespace detail { namespace graph { EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, param_not_found, MultiplicityMap multiplicity_map) { - // default constant weight of one - 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 - weight_type; - - static_property_map - weight_map = detail::graph::make_static_one_property(g); - + // default weight to dummy property map brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, - weight_map, multiplicity_map, + dummy_property_map(), multiplicity_map, vertex_index); } }; From 6e0e0731121e025f7de62621607b679666289a89 Mon Sep 17 00:00:00 2001 From: Javier Dehesa Date: Mon, 12 May 2014 13:36:54 +0200 Subject: [PATCH 3/6] Fixed a wrong call to make_static_one_property --- include/boost/graph/betweenness_centrality.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 603909cb4..cdb51574b 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -483,7 +483,7 @@ brandes_betweenness_centrality(const Graph& g, typedef static_property_map MultiplicityMap; MultiplicityMap multiplicity_map = - detail::graph::make_static_one_property(g); + detail::graph::make_static_one_property(g); detail::graph::brandes_unweighted_shortest_paths shortest_paths(multiplicity_map); From 5ab5134e517f414cdb59edc9475d7ac636322922 Mon Sep 17 00:00:00 2001 From: Javier Dehesa Date: Mon, 19 May 2014 13:34:40 +0200 Subject: [PATCH 4/6] Some slight code simplification. --- .../boost/graph/betweenness_centrality.hpp | 46 ++++++------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index cdb51574b..863a7ba46 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -344,13 +344,10 @@ namespace detail { namespace graph { } } - template - inline boost::static_property_map::value_type, - typename graph_traits::edge_descriptor> - make_static_one_property(const Graph& g) { - typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename property_traits::value_type property_type; - return boost::make_static_property_map(property_type(1)); + template + inline Number + one() { + return Number(1); } template::edge_descriptor edge_descriptor; typedef typename property_traits::value_type multiplicity_type; - typedef static_property_map MultiplicityMap; - - MultiplicityMap multiplicity_map = - detail::graph::make_static_one_property(g); + typedef static_property_map MultiplicityMap; + MultiplicityMap multiplicity_map(detail::graph::one()); brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, incoming, distance, dependency, @@ -478,12 +472,9 @@ brandes_betweenness_centrality(const Graph& g, BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { // default constant multiplicity of one - typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename property_traits::value_type multiplicity_type; - typedef static_property_map MultiplicityMap; - - MultiplicityMap multiplicity_map = - detail::graph::make_static_one_property(g); + typedef static_property_map MultiplicityMap; + MultiplicityMap multiplicity_map(detail::graph::one()); detail::graph::brandes_unweighted_shortest_paths shortest_paths(multiplicity_map); @@ -513,12 +504,9 @@ brandes_betweenness_centrality(const Graph& g, BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { // default constant multiplicity of one - typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename property_traits::value_type multiplicity_type; - typedef static_property_map MultiplicityMap; - - MultiplicityMap multiplicity_map = - detail::graph::make_static_one_property(g); + typedef static_property_map MultiplicityMap; + MultiplicityMap multiplicity_map(detail::graph::one()); brandes_betweenness_centrality(g, centrality, edge_centrality_map, incoming, distance, dependency, path_count, @@ -654,16 +642,12 @@ namespace detail { namespace graph { WeightMap weight_map, param_not_found) { // default constant multiplicity of one - typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename mpl::if_c<(is_same::value), - EdgeCentralityMap, - CentralityMap>::type a_centrality_map; + typedef typename mpl::if_, + EdgeCentralityMap, CentralityMap>::type + a_centrality_map; typedef typename property_traits::value_type multiplicity_type; - typedef static_property_map MultiplicityMap; - - MultiplicityMap multiplicity_map = - detail::graph::make_static_one_property(g); + typedef static_property_map MultiplicityMap; + MultiplicityMap multiplicity_map(detail::graph::one()); brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, weight_map, multiplicity_map, From 337f84d83bbdca6c2f02a5d005d6128be55d12ab Mon Sep 17 00:00:00 2001 From: Javier Dehesa Date: Wed, 21 May 2014 10:43:51 +0200 Subject: [PATCH 5/6] Some other simplifications --- include/boost/graph/betweenness_centrality.hpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 863a7ba46..12265d04b 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -344,12 +344,6 @@ namespace detail { namespace graph { } } - template - inline Number - one() { - return Number(1); - } - template::value_type multiplicity_type; typedef static_property_map MultiplicityMap; - MultiplicityMap multiplicity_map(detail::graph::one()); + MultiplicityMap multiplicity_map(multiplicity_type(1)); brandes_betweenness_centrality_impl(g, centrality, edge_centrality_map, incoming, distance, dependency, @@ -474,7 +468,7 @@ brandes_betweenness_centrality(const Graph& g, // default constant multiplicity of one typedef typename property_traits::value_type multiplicity_type; typedef static_property_map MultiplicityMap; - MultiplicityMap multiplicity_map(detail::graph::one()); + MultiplicityMap multiplicity_map(multiplicity_type(1)); detail::graph::brandes_unweighted_shortest_paths shortest_paths(multiplicity_map); @@ -506,7 +500,7 @@ brandes_betweenness_centrality(const Graph& g, // default constant multiplicity of one typedef typename property_traits::value_type multiplicity_type; typedef static_property_map MultiplicityMap; - MultiplicityMap multiplicity_map(detail::graph::one()); + MultiplicityMap multiplicity_map(multiplicity_type(1)); brandes_betweenness_centrality(g, centrality, edge_centrality_map, incoming, distance, dependency, path_count, @@ -647,7 +641,7 @@ namespace detail { namespace graph { a_centrality_map; typedef typename property_traits::value_type multiplicity_type; typedef static_property_map MultiplicityMap; - MultiplicityMap multiplicity_map(detail::graph::one()); + MultiplicityMap multiplicity_map(multiplicity_type(1)); brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, weight_map, multiplicity_map, From 39ad1fedc73a48181855fd9087b18186997c3c92 Mon Sep 17 00:00:00 2001 From: Javier Dehesa Date: Thu, 17 Jul 2014 12:12:31 +0200 Subject: [PATCH 6/6] Little changes in betweenness_centrality - Added a new exception for nonpositive_edge - multiplicity_map parameter moved to the end of parameters lists - A couple of typos in the docs. --- doc/betweenness_centrality.html | 9 ++-- doc/exception.html | 5 ++- .../boost/graph/betweenness_centrality.hpp | 42 ++++++++++--------- include/boost/graph/exception.hpp | 13 +++++- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/doc/betweenness_centrality.html b/doc/betweenness_centrality.html index 1b697a4bc..f5a9e9b1e 100644 --- a/doc/betweenness_centrality.html +++ b/doc/betweenness_centrality.html @@ -59,7 +59,8 @@

(Python)brandes_betweenness_centralit template<typename Graph, typename CentralityMap, typename EdgeCentralityMap, typename IncomingMap, typename DistanceMap, typename DependencyMap, - typename PathCountMap, typename VertexIndexMap, typename WeightMap> + typename PathCountMap, typename VertexIndexMap, typename WeightMap, + typename MultiplicityMap> void brandes_betweenness_centrality(const Graph& g, CentralityMap centrality_map, EdgeCentralityMap edge_centrality, @@ -289,7 +290,7 @@

Named parameters

The weight or ``length'' of each edge in the graph. The weights must all be non-negative, and the algorithm will throw a negative_edge - exception is one of the edges is negative. + exception if one of the edges is negative. The type WeightMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight @@ -303,8 +304,8 @@

Named parameters

The multiplicity of each edge in the graph. The multiplicities must all be positive, and the algorithm will throw a - negative_edge - exception is one of the edges is non-positive. + nonpositive_edge + exception if one of the edges is non-positive. The type MultiplicityMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the multiplicity diff --git a/doc/exception.html b/doc/exception.html index def19cefd..f5f611bd8 100644 --- a/doc/exception.html +++ b/doc/exception.html @@ -34,7 +34,10 @@

Synopsis

struct not_a_dag : public bad_graph { not_a_dag(); }; - struct negative_edge : public bad_graph { + struct nonpositive_edge : public bad_graph { + negative_edge(); + }; + struct negative_edge : public nonpositive_edge { negative_edge(); }; struct negative_cycle : public bad_graph { diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 12265d04b..6ae782a71 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -41,7 +41,7 @@ namespace detail { namespace graph { closed_plus combine; property_type zero = property_type(); if (compare(combine(zero, get(property, e)), zero)) { - boost::throw_exception(negative_edge()); + boost::throw_exception(nonpositive_edge()); } } @@ -52,8 +52,8 @@ namespace detail { namespace graph { * predecessors on the shortest path(s) to a vertex, and the number * of shortest paths. */ - template + template struct brandes_dijkstra_visitor : public bfs_visitor<> { typedef typename graph_traits::vertex_descriptor vertex_descriptor; @@ -62,13 +62,13 @@ namespace detail { namespace graph { brandes_dijkstra_visitor(std::stack& ordered_vertices, WeightMap weight, - MultiplicityMap multiplicity, IncomingMap incoming, DistanceMap distance, - PathCountMap path_count) + PathCountMap path_count, + MultiplicityMap multiplicity) : ordered_vertices(ordered_vertices), weight(weight), - multiplicity(multiplicity), incoming(incoming), distance(distance), - path_count(path_count) + incoming(incoming), distance(distance), + path_count(path_count), multiplicity(multiplicity) { } /** @@ -119,10 +119,10 @@ namespace detail { namespace graph { private: std::stack& ordered_vertices; WeightMap weight; - MultiplicityMap multiplicity; IncomingMap incoming; DistanceMap distance; PathCountMap path_count; + MultiplicityMap multiplicity; }; /** @@ -147,9 +147,11 @@ namespace detail { namespace graph { PathCountMap path_count, VertexIndexMap vertex_index) { - typedef brandes_dijkstra_visitor visitor_type; - visitor_type visitor(ov, weight_map, multiplicity_map, incoming, distance, path_count); + typedef brandes_dijkstra_visitor visitor_type; + visitor_type visitor(ov, weight_map, incoming, distance, path_count, + multiplicity_map); dijkstra_shortest_paths(g, s, boost::weight_map(weight_map) @@ -539,14 +541,14 @@ brandes_betweenness_centrality(const Graph& g, namespace detail { namespace graph { template + typename WeightMap, typename VertexIndexMap, typename MultiplicityMap> void brandes_betweenness_centrality_dispatch2(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map, WeightMap weight_map, - MultiplicityMap multiplicity_map, - VertexIndexMap vertex_index) + VertexIndexMap vertex_index, + MultiplicityMap multiplicity_map) { typedef typename graph_traits::degree_size_type degree_size_type; typedef typename graph_traits::edge_descriptor edge_descriptor; @@ -620,8 +622,8 @@ namespace detail { namespace graph { WeightMap weight_map, MultiplicityMap multiplicity_map) { brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, - weight_map, multiplicity_map, - vertex_index); + weight_map, vertex_index, + multiplicity_map); } }; @@ -644,8 +646,8 @@ namespace detail { namespace graph { MultiplicityMap multiplicity_map(multiplicity_type(1)); brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, - weight_map, multiplicity_map, - vertex_index); + weight_map, vertex_index, + multiplicity_map); } }; @@ -661,8 +663,8 @@ namespace detail { namespace graph { { // default weight to dummy property map brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, - dummy_property_map(), multiplicity_map, - vertex_index); + dummy_property_map(), vertex_index, + multiplicity_map); } }; diff --git a/include/boost/graph/exception.hpp b/include/boost/graph/exception.hpp index 382d67192..3a28af26e 100644 --- a/include/boost/graph/exception.hpp +++ b/include/boost/graph/exception.hpp @@ -26,9 +26,18 @@ namespace boost { { } }; - struct negative_edge : public bad_graph { + struct nonpositive_edge : public bad_graph { + nonpositive_edge() + : bad_graph("The graph may not contain an edge with non-positive weight.") + { } + protected: + nonpositive_edge(const std::string& what_arg) + : bad_graph(what_arg) { } + }; + + struct negative_edge : public nonpositive_edge { negative_edge() - : bad_graph("The graph may not contain an edge with negative weight.") + : nonpositive_edge("The graph may not contain an edge with negative weight.") { } };