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,
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)
{
......
......@@ -32,50 +32,130 @@ using namespace boost;
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,
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<double,GraphInterface::edge_t> weight_map_t;
typedef ConstantPropertyMap<double,GraphInterface::edge_t> no_weight_map_t;
typedef mpl::vector<weight_map_t,no_weight_map_t> weight_properties;
typedef typename mpl::vector<vweight_map_t, voweight_map_t, no_vweight_map_t>::type
vweight_properties;
typedef typename mpl::vector<eweight_map_t, eoweight_map_t, no_eweight_map_t>::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());
typedef property_map_type::apply<int32_t,
GraphInterface::vertex_index_map_t>::type
vcount_t;
vcount_t vcount(gi.GetVertexIndex());
{
try
{
vcount = any_cast<vcount_t>(vertex_count);
eweight = eweight_map_t(eweight, edge_scalar_properties());
edge_count = eweight_map_t(edge_count, edge_scalar_properties());
}
catch (bad_any_cast&)
catch (...)
{
throw ValueException("invalid vertex count property");
eweight = eoweight_map_t(eweight, edge_properties());
edge_count = eoweight_map_t(edge_count, edge_properties());
}
}
typedef property_map_types::apply<mpl::vector<int32_t,double>,
GraphInterface::edge_index_map_t,
mpl::bool_<false> >::type
ecount_properties;
if (!belongs<ecount_properties>()(edge_count))
throw ValueException("invalid edge count property");
if (vweight.empty())
{
vweight = no_vweight_map_t(1);
vertex_count = viweight_map_t(vertex_count, vertex_scalar_properties());
}
else
{
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());
}
}
run_action<>()(gi, bind<void>(get_community_network(), _1,
run_action<>()(gi, bind<void>(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();
}
......@@ -37,11 +37,13 @@ using namespace boost;
struct get_community_network
{
template <class Graph, class CommunityGraph, class CommunityMap,
class WeightMap, class EdgeIndex, class VertexIndex,
class VertexProperty, class EdgeProperty>
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<Graph>::vertex_descriptor vertex_t;
......@@ -52,17 +54,18 @@ struct get_community_network
cedge_t;
typedef typename boost::property_traits<CommunityMap>::value_type
s_type;
typedef typename boost::property_traits<VertexProperty>::value_type
vprop_type;
typedef typename get_prop_type<CommunityMap, VertexIndex>::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> >
tr1::unordered_map<s_type, pair<vector<vertex_t>, vprop_type>, hash<s_type> >
comms;
typename graph_traits<Graph>::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<vector<vertex_t>, vprop_type>& m = comms[get(s_map, *v)];
m.first.push_back(*v);
m.second += get(vweight, *v);
}
// create vertices
tr1::unordered_map<s_type, cvertex_t, hash<s_type> >
......@@ -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<Graph>::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 <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>
void put_dispatch(PropertyMap cs_map,
const typename property_traits<PropertyMap>::key_type& v,
......@@ -164,4 +140,3 @@ struct get_community_network
} // graph_tool namespace
#endif // GRAPH_COMMUNITY_NETWORK_HH
......@@ -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())
if vweight is None:
vcount = gp.new_vertex_property("int32_t")
if weight != None:
ecount = gp.new_edge_property("double")
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
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