From 88cf9f1574aef63f671dbdd6219687277636b984 Mon Sep 17 00:00:00 2001 From: Tiago de Paula Peixoto Date: Sun, 11 Mar 2012 18:21:38 +0100 Subject: [PATCH] Implement edge weight parameter in condensation_graph() --- src/graph/community/graph_community.cc | 3 +- .../community/graph_community_network.cc | 136 ++++++++++++++---- .../community/graph_community_network.hh | 61 +++----- src/graph_tool/community/__init__.py | 18 ++- 4 files changed, 140 insertions(+), 78 deletions(-) diff --git a/src/graph/community/graph_community.cc b/src/graph/community/graph_community.cc index da74e07e..8bb6cd7e 100644 --- a/src/graph/community/graph_community.cc +++ b/src/graph/community/graph_community.cc @@ -100,7 +100,8 @@ extern void community_network(GraphInterface& gi, GraphInterface& cgi, boost::any community_property, boost::any condensed_community_property, boost::any vertex_count, - boost::any edge_count, boost::any weight); + boost::any edge_count, boost::any vweight, + boost::any eweight); BOOST_PYTHON_MODULE(libgraph_tool_community) { diff --git a/src/graph/community/graph_community_network.cc b/src/graph/community/graph_community_network.cc index 1decefcf..a9638aff 100644 --- a/src/graph/community/graph_community_network.cc +++ b/src/graph/community/graph_community_network.cc @@ -32,50 +32,130 @@ using namespace boost; using namespace graph_tool; +typedef ConstantPropertyMap no_eweight_map_t; +typedef ConstantPropertyMap no_vweight_map_t; +typedef DynamicPropertyMapWrap viweight_map_t; +typedef DynamicPropertyMapWrap vweight_map_t; +typedef DynamicPropertyMapWrap eiweight_map_t; +typedef DynamicPropertyMapWrap eweight_map_t; +typedef DynamicPropertyMapWrap voweight_map_t; +typedef DynamicPropertyMapWrap eoweight_map_t; + +struct get_community_network_dispatch +{ + template + void operator()(const Graph& g, CommunityGraph& cg, + VertexIndex cvertex_index, EdgeIndex cedge_index, + CommunityMap s_map, boost::any acs_map, + VertexWeightMap vweight, EdgeWeightMap eweight, + pair count) const + { + typedef typename get_prop_type::type + comm_t; + comm_t cs_map = boost::any_cast(acs_map); + + typedef typename mpl::if_, + viweight_map_t, VertexWeightMap>::type vweight_t; + typedef typename mpl::if_, + eiweight_map_t, EdgeWeightMap>::type eweight_t; + + vweight_t vertex_count = boost::any_cast(count.first); + eweight_t edge_count = boost::any_cast(count.second); + + get_community_network()(g, cg, cvertex_index, cedge_index, s_map, + cs_map, vweight, eweight, vertex_count, + edge_count); + } + + struct get_checked_t + { + template + struct apply + { + typedef typename PropertyMap::checked_t type; + }; + }; + + struct get_identity + { + template + struct apply + { + typedef PropertyMap type; + }; + }; + + template + struct get_prop_type + { + typedef typename mpl::if_::type, + get_identity, + get_checked_t>::type extract; + typedef typename extract::template apply::type type; + }; + +}; + void community_network(GraphInterface& gi, GraphInterface& cgi, boost::any community_property, boost::any condensed_community_property, boost::any vertex_count, - boost::any edge_count, boost::any weight) + boost::any edge_count, boost::any vweight, + boost::any eweight) { - typedef DynamicPropertyMapWrap weight_map_t; - typedef ConstantPropertyMap no_weight_map_t; - typedef mpl::vector weight_properties; + typedef typename mpl::vector::type + vweight_properties; + typedef typename mpl::vector::type + eweight_properties; - if (weight.empty()) - weight = no_weight_map_t(1.0); + if (eweight.empty()) + { + eweight = no_eweight_map_t(1); + edge_count = eiweight_map_t(edge_count, edge_scalar_properties()); + } else - weight = weight_map_t(weight, edge_scalar_properties()); + { + try + { + eweight = eweight_map_t(eweight, edge_scalar_properties()); + edge_count = eweight_map_t(edge_count, edge_scalar_properties()); + } + catch (...) + { + eweight = eoweight_map_t(eweight, edge_properties()); + edge_count = eoweight_map_t(edge_count, edge_properties()); + } + } - typedef property_map_type::apply::type - vcount_t; - vcount_t vcount(gi.GetVertexIndex()); - try + if (vweight.empty()) { - vcount = any_cast(vertex_count); + vweight = no_vweight_map_t(1); + vertex_count = viweight_map_t(vertex_count, vertex_scalar_properties()); } - catch (bad_any_cast&) + else { - throw ValueException("invalid vertex count property"); + try + { + vweight = vweight_map_t(vweight, vertex_scalar_properties()); + vertex_count = vweight_map_t(vertex_count, vertex_scalar_properties()); + } + catch (...) + { + vweight = voweight_map_t(vweight, vertex_properties()); + vertex_count = voweight_map_t(vertex_count, vertex_properties()); + } } - typedef property_map_types::apply, - GraphInterface::edge_index_map_t, - mpl::bool_ >::type - ecount_properties; - - if (!belongs()(edge_count)) - throw ValueException("invalid edge count property"); - - run_action<>()(gi, bind(get_community_network(), _1, + run_action<>()(gi, bind(get_community_network_dispatch(), _1, ref(cgi.GetGraph()), cgi.GetVertexIndex(), cgi.GetEdgeIndex(), _2, condensed_community_property, - _3, vcount, _4), - vertex_properties(), weight_properties(), - ecount_properties()) - (community_property, weight, edge_count); + _3, _4, make_pair(vertex_count, edge_count)), + vertex_scalar_properties(), vweight_properties(), + eweight_properties()) + (community_property, vweight, eweight); cgi.ReIndexEdges(); } diff --git a/src/graph/community/graph_community_network.hh b/src/graph/community/graph_community_network.hh index c10848e2..07b8ce97 100644 --- a/src/graph/community/graph_community_network.hh +++ b/src/graph/community/graph_community_network.hh @@ -37,11 +37,13 @@ using namespace boost; struct get_community_network { template + class CCommunityMap, + class VertexWeightMap, class EdgeWeightMap, class EdgeIndex, + class VertexIndex, class VertexProperty, class EdgeProperty> void operator()(const Graph& g, CommunityGraph& cg, VertexIndex cvertex_index, EdgeIndex cedge_index, - CommunityMap s_map, boost::any acs_map, WeightMap weight, + CommunityMap s_map, CCommunityMap cs_map, + VertexWeightMap vweight, EdgeWeightMap eweight, VertexProperty vertex_count, EdgeProperty edge_count) const { typedef typename graph_traits::vertex_descriptor vertex_t; @@ -52,17 +54,18 @@ struct get_community_network cedge_t; typedef typename boost::property_traits::value_type s_type; + typedef typename boost::property_traits::value_type + vprop_type; - typedef typename get_prop_type::type - comm_map_t; - - comm_map_t cs_map = boost::any_cast(acs_map); - - tr1::unordered_map, hash > + tr1::unordered_map, vprop_type>, hash > comms; typename graph_traits::vertex_iterator v, v_end; for (tie(v, v_end) = vertices(g); v != v_end; ++v) - comms[get(s_map, *v)].push_back(*v); + { + pair, vprop_type>& m = comms[get(s_map, *v)]; + m.first.push_back(*v); + m.second += get(vweight, *v); + } // create vertices tr1::unordered_map > @@ -71,7 +74,7 @@ struct get_community_network ++iter) { cvertex_t v = add_vertex(cg); - vertex_count[v] = iter->second.size(); + put(vertex_count, v, iter->second.second); comm_vertices[iter->first] = v; put_dispatch(cs_map, v, iter->first, typename boost::is_convertible @@ -87,9 +90,9 @@ struct get_community_network ++iter) { cvertex_t cs = comm_vertices[iter->first]; - for (size_t i = 0; i < iter->second.size(); ++i) + for (size_t i = 0; i < iter->second.first.size(); ++i) { - vertex_t s = iter->second[i]; + vertex_t s = iter->second.first[i]; typename graph_traits::out_edge_iterator e, e_end; for (tie(e, e_end) = out_edges(s, g); e != e_end; ++e) { @@ -107,41 +110,14 @@ struct get_community_network { ce = add_edge(cs, ct, cg).first; comm_edges[make_pair(cs, ct)] = ce; - cedge_index[ce] = comm_edges.size() - 1; + put(cedge_index, ce, comm_edges.size() - 1); } - edge_count[ce] += get(weight, *e); + put(edge_count, ce, get(edge_count, ce) + get(eweight, *e)); } } } } - struct get_checked_t - { - template - struct apply - { - typedef typename PropertyMap::checked_t type; - }; - }; - - struct get_identity - { - template - struct apply - { - typedef PropertyMap type; - }; - }; - - template - struct get_prop_type - { - typedef typename mpl::if_::type, - get_identity, - get_checked_t>::type extract; - typedef typename extract::template apply::type type; - }; - template void put_dispatch(PropertyMap cs_map, const typename property_traits::key_type& v, @@ -164,4 +140,3 @@ struct get_community_network } // graph_tool namespace #endif // GRAPH_COMMUNITY_NETWORK_HH - diff --git a/src/graph_tool/community/__init__.py b/src/graph_tool/community/__init__.py index 7962513a..45307336 100644 --- a/src/graph_tool/community/__init__.py +++ b/src/graph_tool/community/__init__.py @@ -278,7 +278,7 @@ def modularity(g, prop, weight=None): return m -def condensation_graph(g, prop, weight=None): +def condensation_graph(g, prop, vweight=None, eweight=None): r""" Obtain the condensation graph, where each vertex with the same 'prop' value is condensed in one vertex. @@ -289,7 +289,9 @@ def condensation_graph(g, prop, weight=None): Graph to be used. prop : :class:`~graph_tool.PropertyMap` Vertex property map with the community partition. - weight : :class:`~graph_tool.PropertyMap` (optional, default: None) + vweight : :class:`~graph_tool.PropertyMap` (optional, default: None) + Vertex property map with the optional vertex weights. + eweight : :class:`~graph_tool.PropertyMap` (optional, default: None) Edge property map with the optional edge weights. Returns @@ -337,11 +339,14 @@ def condensation_graph(g, prop, weight=None): size of the corresponding community. """ gp = Graph(directed=g.is_directed()) - vcount = gp.new_vertex_property("int32_t") - if weight != None: - ecount = gp.new_edge_property("double") + if vweight is None: + vcount = gp.new_vertex_property("int32_t") else: + vcount = gp.new_vertex_property(vweight.value_type()) + if eweight is None: ecount = gp.new_edge_property("int32_t") + else: + ecount = gp.new_edge_property(eweight.value_type()) cprop = gp.new_vertex_property(prop.value_type()) libgraph_tool_community.community_network(g._Graph__graph, gp._Graph__graph, @@ -349,5 +354,6 @@ def condensation_graph(g, prop, weight=None): _prop("v", gp, cprop), _prop("v", gp, vcount), _prop("e", gp, ecount), - _prop("e", g, weight)) + _prop("v", g, vweight), + _prop("e", g, eweight)) return gp, cprop, vcount, ecount -- GitLab