Commit 88cf9f15 authored by Tiago Peixoto's avatar Tiago Peixoto

Implement edge weight parameter in condensation_graph()

parent 33b91262
...@@ -100,7 +100,8 @@ extern void community_network(GraphInterface& gi, GraphInterface& cgi, ...@@ -100,7 +100,8 @@ extern void community_network(GraphInterface& gi, GraphInterface& cgi,
boost::any community_property, boost::any community_property,
boost::any condensed_community_property, boost::any condensed_community_property,
boost::any vertex_count, 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) BOOST_PYTHON_MODULE(libgraph_tool_community)
{ {
......
...@@ -32,50 +32,130 @@ using namespace boost; ...@@ -32,50 +32,130 @@ using namespace boost;
using namespace graph_tool; using namespace graph_tool;
typedef ConstantPropertyMap<int32_t,GraphInterface::edge_t> no_eweight_map_t;
typedef ConstantPropertyMap<int32_t,GraphInterface::vertex_t> no_vweight_map_t;
typedef DynamicPropertyMapWrap<int32_t,GraphInterface::vertex_t> viweight_map_t;
typedef DynamicPropertyMapWrap<double,GraphInterface::vertex_t> vweight_map_t;
typedef DynamicPropertyMapWrap<int32_t,GraphInterface::edge_t> eiweight_map_t;
typedef DynamicPropertyMapWrap<double,GraphInterface::edge_t> eweight_map_t;
typedef DynamicPropertyMapWrap<python::object,GraphInterface::vertex_t> voweight_map_t;
typedef DynamicPropertyMapWrap<python::object,GraphInterface::edge_t> eoweight_map_t;
struct get_community_network_dispatch
{
template <class Graph, class CommunityGraph, class CommunityMap,
class VertexWeightMap, class EdgeWeightMap, class EdgeIndex,
class VertexIndex>
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<boost::any,boost::any> count) const
{
typedef typename get_prop_type<CommunityMap, VertexIndex>::type
comm_t;
comm_t cs_map = boost::any_cast<comm_t>(acs_map);
typedef typename mpl::if_<is_same<no_vweight_map_t, VertexWeightMap>,
viweight_map_t, VertexWeightMap>::type vweight_t;
typedef typename mpl::if_<is_same<no_eweight_map_t, EdgeWeightMap>,
eiweight_map_t, EdgeWeightMap>::type eweight_t;
vweight_t vertex_count = boost::any_cast<vweight_t>(count.first);
eweight_t edge_count = boost::any_cast<eweight_t>(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 <class PropertyMap>
struct apply
{
typedef typename PropertyMap::checked_t type;
};
};
struct get_identity
{
template <class PropertyMap>
struct apply
{
typedef PropertyMap type;
};
};
template <class PropertyMap, class IndexMap>
struct get_prop_type
{
typedef typename mpl::if_<typename is_same<PropertyMap, IndexMap>::type,
get_identity,
get_checked_t>::type extract;
typedef typename extract::template apply<PropertyMap>::type type;
};
};
void community_network(GraphInterface& gi, GraphInterface& cgi, void community_network(GraphInterface& gi, GraphInterface& cgi,
boost::any community_property, boost::any community_property,
boost::any condensed_community_property, boost::any condensed_community_property,
boost::any vertex_count, boost::any vertex_count,
boost::any edge_count, boost::any weight) boost::any edge_count, boost::any vweight,
boost::any eweight)
{ {
typedef DynamicPropertyMapWrap<double,GraphInterface::edge_t> weight_map_t; typedef typename mpl::vector<vweight_map_t, voweight_map_t, no_vweight_map_t>::type
typedef ConstantPropertyMap<double,GraphInterface::edge_t> no_weight_map_t; vweight_properties;
typedef mpl::vector<weight_map_t,no_weight_map_t> weight_properties; typedef typename mpl::vector<eweight_map_t, eoweight_map_t, no_eweight_map_t>::type
eweight_properties;
if (weight.empty()) if (eweight.empty())
weight = no_weight_map_t(1.0); {
eweight = no_eweight_map_t(1);
edge_count = eiweight_map_t(edge_count, edge_scalar_properties());
}
else 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<int32_t, if (vweight.empty())
GraphInterface::vertex_index_map_t>::type
vcount_t;
vcount_t vcount(gi.GetVertexIndex());
try
{ {
vcount = any_cast<vcount_t>(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<mpl::vector<int32_t,double>, run_action<>()(gi, bind<void>(get_community_network_dispatch(), _1,
GraphInterface::edge_index_map_t,
mpl::bool_<false> >::type
ecount_properties;
if (!belongs<ecount_properties>()(edge_count))
throw ValueException("invalid edge count property");
run_action<>()(gi, bind<void>(get_community_network(), _1,
ref(cgi.GetGraph()), cgi.GetVertexIndex(), ref(cgi.GetGraph()), cgi.GetVertexIndex(),
cgi.GetEdgeIndex(), _2, cgi.GetEdgeIndex(), _2,
condensed_community_property, condensed_community_property,
_3, vcount, _4), _3, _4, make_pair(vertex_count, edge_count)),
vertex_properties(), weight_properties(), vertex_scalar_properties(), vweight_properties(),
ecount_properties()) eweight_properties())
(community_property, weight, edge_count); (community_property, vweight, eweight);
cgi.ReIndexEdges(); cgi.ReIndexEdges();
} }
...@@ -37,11 +37,13 @@ using namespace boost; ...@@ -37,11 +37,13 @@ using namespace boost;
struct get_community_network struct get_community_network
{ {
template <class Graph, class CommunityGraph, class CommunityMap, template <class Graph, class CommunityGraph, class CommunityMap,
class WeightMap, class EdgeIndex, class VertexIndex, class CCommunityMap,
class VertexProperty, class EdgeProperty> class VertexWeightMap, class EdgeWeightMap, class EdgeIndex,
class VertexIndex, class VertexProperty, class EdgeProperty>
void operator()(const Graph& g, CommunityGraph& cg, void operator()(const Graph& g, CommunityGraph& cg,
VertexIndex cvertex_index, EdgeIndex cedge_index, 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 VertexProperty vertex_count, EdgeProperty edge_count) const
{ {
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t; typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
...@@ -52,17 +54,18 @@ struct get_community_network ...@@ -52,17 +54,18 @@ struct get_community_network
cedge_t; cedge_t;
typedef typename boost::property_traits<CommunityMap>::value_type typedef typename boost::property_traits<CommunityMap>::value_type
s_type; s_type;
typedef typename boost::property_traits<VertexProperty>::value_type
vprop_type;
typedef typename get_prop_type<CommunityMap, VertexIndex>::type tr1::unordered_map<s_type, pair<vector<vertex_t>, vprop_type>, hash<s_type> >
comm_map_t;
comm_map_t cs_map = boost::any_cast<comm_map_t>(acs_map);
tr1::unordered_map<s_type, vector<vertex_t>, hash<s_type> >
comms; comms;
typename graph_traits<Graph>::vertex_iterator v, v_end; typename graph_traits<Graph>::vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v) for (tie(v, v_end) = vertices(g); v != v_end; ++v)
comms[get(s_map, *v)].push_back(*v); {
pair<vector<vertex_t>, vprop_type>& m = comms[get(s_map, *v)];
m.first.push_back(*v);
m.second += get(vweight, *v);
}
// create vertices // create vertices
tr1::unordered_map<s_type, cvertex_t, hash<s_type> > tr1::unordered_map<s_type, cvertex_t, hash<s_type> >
...@@ -71,7 +74,7 @@ struct get_community_network ...@@ -71,7 +74,7 @@ struct get_community_network
++iter) ++iter)
{ {
cvertex_t v = add_vertex(cg); cvertex_t v = add_vertex(cg);
vertex_count[v] = iter->second.size(); put(vertex_count, v, iter->second.second);
comm_vertices[iter->first] = v; comm_vertices[iter->first] = v;
put_dispatch(cs_map, v, iter->first, put_dispatch(cs_map, v, iter->first,
typename boost::is_convertible typename boost::is_convertible
...@@ -87,9 +90,9 @@ struct get_community_network ...@@ -87,9 +90,9 @@ struct get_community_network
++iter) ++iter)
{ {
cvertex_t cs = comm_vertices[iter->first]; 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<Graph>::out_edge_iterator e, e_end; typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(s, g); e != e_end; ++e) for (tie(e, e_end) = out_edges(s, g); e != e_end; ++e)
{ {
...@@ -107,41 +110,14 @@ struct get_community_network ...@@ -107,41 +110,14 @@ struct get_community_network
{ {
ce = add_edge(cs, ct, cg).first; ce = add_edge(cs, ct, cg).first;
comm_edges[make_pair(cs, ct)] = ce; 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 <class PropertyMap>
struct apply
{
typedef typename PropertyMap::checked_t type;
};
};
struct get_identity
{
template <class PropertyMap>
struct apply
{
typedef PropertyMap type;
};
};
template <class PropertyMap, class IndexMap>
struct get_prop_type
{
typedef typename mpl::if_<typename is_same<PropertyMap, IndexMap>::type,
get_identity,
get_checked_t>::type extract;
typedef typename extract::template apply<PropertyMap>::type type;
};
template <class PropertyMap> template <class PropertyMap>
void put_dispatch(PropertyMap cs_map, void put_dispatch(PropertyMap cs_map,
const typename property_traits<PropertyMap>::key_type& v, const typename property_traits<PropertyMap>::key_type& v,
...@@ -164,4 +140,3 @@ struct get_community_network ...@@ -164,4 +140,3 @@ struct get_community_network
} // graph_tool namespace } // graph_tool namespace
#endif // GRAPH_COMMUNITY_NETWORK_HH #endif // GRAPH_COMMUNITY_NETWORK_HH
...@@ -278,7 +278,7 @@ def modularity(g, prop, weight=None): ...@@ -278,7 +278,7 @@ def modularity(g, prop, weight=None):
return m return m
def condensation_graph(g, prop, weight=None): def condensation_graph(g, prop, vweight=None, eweight=None):
r""" r"""
Obtain the condensation graph, where each vertex with the same 'prop' value Obtain the condensation graph, where each vertex with the same 'prop' value
is condensed in one vertex. is condensed in one vertex.
...@@ -289,7 +289,9 @@ def condensation_graph(g, prop, weight=None): ...@@ -289,7 +289,9 @@ def condensation_graph(g, prop, weight=None):
Graph to be used. Graph to be used.
prop : :class:`~graph_tool.PropertyMap` prop : :class:`~graph_tool.PropertyMap`
Vertex property map with the community partition. 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. Edge property map with the optional edge weights.
Returns Returns
...@@ -337,11 +339,14 @@ def condensation_graph(g, prop, weight=None): ...@@ -337,11 +339,14 @@ def condensation_graph(g, prop, weight=None):
size of the corresponding community. size of the corresponding community.
""" """
gp = Graph(directed=g.is_directed()) gp = Graph(directed=g.is_directed())
vcount = gp.new_vertex_property("int32_t") if vweight is None:
if weight != None: vcount = gp.new_vertex_property("int32_t")
ecount = gp.new_edge_property("double")
else: else:
vcount = gp.new_vertex_property(vweight.value_type())
if eweight is None:
ecount = gp.new_edge_property("int32_t") ecount = gp.new_edge_property("int32_t")
else:
ecount = gp.new_edge_property(eweight.value_type())
cprop = gp.new_vertex_property(prop.value_type()) cprop = gp.new_vertex_property(prop.value_type())
libgraph_tool_community.community_network(g._Graph__graph, libgraph_tool_community.community_network(g._Graph__graph,
gp._Graph__graph, gp._Graph__graph,
...@@ -349,5 +354,6 @@ def condensation_graph(g, prop, weight=None): ...@@ -349,5 +354,6 @@ def condensation_graph(g, prop, weight=None):
_prop("v", gp, cprop), _prop("v", gp, cprop),
_prop("v", gp, vcount), _prop("v", gp, vcount),
_prop("e", gp, ecount), _prop("e", gp, ecount),
_prop("e", g, weight)) _prop("v", g, vweight),
_prop("e", g, eweight))
return gp, cprop, vcount, ecount return gp, cprop, vcount, ecount
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment