Commit 67a10cd3 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement edge_difference()

parent 46454b3d
......@@ -320,6 +320,8 @@ void group_vector_property(GraphInterface& g, boost::any vector_prop,
boost::any prop, size_t pos, bool edge);
void infect_vertex_property(GraphInterface& gi, boost::any prop,
python::object val);
void edge_difference(GraphInterface& gi, boost::any prop,
boost::any eprop);
void export_python_interface();
BOOST_PYTHON_MODULE(libgraph_tool_core)
......@@ -409,6 +411,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
def("group_vector_property", &group_vector_property);
def("ungroup_vector_property", &ungroup_vector_property);
def("infect_vertex_property", &infect_vertex_property);
def("edge_difference", &edge_difference);
class_<LibInfo>("mod_info")
.add_property("name", &LibInfo::GetName)
......
......@@ -179,3 +179,52 @@ void infect_vertex_property(GraphInterface& gi, boost::any prop,
gi.GetVertexIndex(), _2, val),
writable_vertex_properties())(prop);
}
template <class Value>
vector<Value> operator-(const vector<Value>& a, const vector<Value>& b)
{
vector<Value> c(a);
c.resize(max(a.size(), b.size()), Value(0));
for (size_t i = 0; i < b.size(); ++i)
c[i] = a[i] - b[i];
return c;
}
struct do_edge_difference
{
template <class Graph, class EdgeIndexMap, class VertexPropertyMap>
void operator()(Graph& g, EdgeIndexMap edge_index, VertexPropertyMap prop,
boost::any eprop) const
{
typedef typename property_traits<VertexPropertyMap>::value_type vval_t;
typedef typename mpl::if_<is_same<vval_t, size_t>, int32_t, vval_t>::type
val_t;
typedef typename property_map_type::apply<val_t, EdgeIndexMap>::type
eprop_t;
eprop_t ediff = any_cast<eprop_t>(eprop);
ediff.reserve(num_edges(g));
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(v, g); e != e_end; ++e)
ediff[*e] = prop[target(*e, g)] - prop[source(*e, g)];
}
}
};
void edge_difference(GraphInterface& gi, boost::any prop,
boost::any eprop)
{
typedef typename mpl::insert_range<vertex_scalar_properties,
mpl::end<vertex_scalar_properties>::type,
vertex_scalar_vector_properties>::type vprops_t;
run_action<>()(gi, bind<void>(do_edge_difference(), _1,
gi.GetEdgeIndex(), _2, eprop),
vprops_t())(prop);
}
......@@ -111,9 +111,9 @@ __all__ = ["Graph", "GraphView", "Vertex", "Edge", "Vector_bool",
"Vector_int32_t", "Vector_int64_t", "Vector_double",
"Vector_long_double", "Vector_string", "value_types", "load_graph",
"PropertyMap", "group_vector_property", "ungroup_vector_property",
"show_config", "PropertyArray", "__author__", "__copyright__",
"__URL__", "__version__"]
"infect_vertex_property", "edge_difference", "show_config",
"PropertyArray", "__author__", "__copyright__", "__URL__",
"__version__"]
# this is rather pointless, but it works around a sphinx bug
graph_tool = sys.modules[__name__]
......@@ -785,6 +785,46 @@ def infect_vertex_property(g, prop, vals=None):
libcore.infect_vertex_property(g._Graph__graph, _prop("v", g, prop),
vals)
def edge_difference(g, prop, ediff=None):
"""Return an edge property map corresponding to the difference between the
values of `prop` of target and source vertices of each edge.
Parameters
----------
prop : :class:`~graph_tool.PropertyMap`
Vertex property map to be used to compute the difference..
ediff : :class:`~graph_tool.PropertyMap` (optional, default: `None`)
If not provided, the difference values will be stored in this property
map.
Returns
-------
ediff : :class:`~graph_tool.PropertyMap`
Edge differences.
Examples
--------
>>> from numpy.random import seed
>>> seed(42)
>>> g = gt.random_graph(100, lambda: (3, 3))
>>> ediff = gt.edge_difference(g, g.vertex_index)
>>> print ediff.a
3
"""
val_t = prop.value_type()
if val_t == "unsigned long":
val_t = "int32_t"
if ediff is None:
ediff = g.new_edge_property(val_t)
if ediff.value_type() != val_t:
raise ValueError("'ediff' must be of the same value type as 'prop': " +
val_t)
libcore.edge_difference(g._Graph__graph, _prop("v", g, prop),
_prop("e", g, ediff))
return ediff
class PropertyDict(dict):
"""Wrapper for the dict of vertex, graph or edge properties, which sets the
value on the property map when changed in the dict."""
......
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