Commit 2b25ac58 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Refactor incident_edges_sum() into more general incident_edges_op()

parent 126f2179
......@@ -392,13 +392,12 @@ void infect_vertex_property(GraphInterface& gi, boost::any prop,
boost::python::object val);
void edge_endpoint(GraphInterface& gi, boost::any prop,
boost::any eprop, std::string endpoint);
void out_edges_sum(GraphInterface& gi, boost::any eprop, boost::any vprop);
void out_edges_op(GraphInterface& gi, boost::any eprop, boost::any vprop,
std::string op);
void mark_edges(GraphInterface& gi, boost::any prop);
void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop,
boost::any& dict);
void perfect_vhash(GraphInterface& gi, boost::any prop, boost::any hprop,
boost::any& dict);
......@@ -523,7 +522,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
def("ungroup_vector_property", &ungroup_vector_property);
def("infect_vertex_property", &infect_vertex_property);
def("edge_endpoint", &edge_endpoint);
def("out_edges_sum", &out_edges_sum);
def("out_edges_op", &out_edges_op);
def("mark_edges", &mark_edges);
def("perfect_ehash", &perfect_ehash);
def("perfect_vhash", &perfect_vhash);
......
......@@ -35,17 +35,132 @@ void operator+=(std::vector<Val1>& v1, const std::vector<Val2>& v2)
v1[i] += v2[i];
}
struct do_out_edges_sum
template <class Val1, class Val2>
void operator*=(std::vector<Val1>& v1, const std::vector<Val2>& v2)
{
if (v2.size() > v1.size())
v1.resize(v2.size());
for (size_t i = 0; i < v2.size(); ++i)
v1[i] *= v2[i];
}
void operator*=(std::string& v1, const string& v2)
{
throw GraphException("Cannot multiply strings.");
}
template <class Val1, class Val2>
bool operator<(const std::vector<Val1>& v1, const std::vector<Val2>& v2)
{
if (v1.size() != v2.size())
return v1.size() < v2.size();
for (size_t i = 0; i < v2.size(); ++i)
{
if (v1[i] < v2[i])
return true;
}
return false;
}
struct SumOp
{
template <class Graph, class Vertex, class EProp, class VProp>
void operator()(Vertex v, EProp& eprop, VProp& vprop, Graph& g) const
{
typedef typename property_traits<EProp>::value_type eval_t;
typedef typename property_traits<VProp>::value_type vval_t;
convert<vval_t, eval_t> conv;
size_t count = 0;
for (auto e : out_edges_range(v, g))
{
if (count == 0)
vprop[v] = conv(eprop[e]);
else
vprop[v] += conv(eprop[e]);
++count;
}
}
};
struct ProdOp
{
template <class Graph, class Vertex, class EProp, class VProp>
void operator()(Vertex v, EProp& eprop, VProp& vprop, Graph& g) const
{
typedef typename property_traits<EProp>::value_type eval_t;
typedef typename property_traits<VProp>::value_type vval_t;
convert<vval_t, eval_t> conv;
size_t count = 0;
for (auto e : out_edges_range(v, g))
{
if (count == 0)
vprop[v] = conv(eprop[e]);
else
vprop[v] *= conv(eprop[e]);
++count;
}
}
};
struct MinOp
{
template <class Graph, class EProp, class VProp>
void operator()(Graph& g, EProp eprop, VProp vprop) const
template <class Graph, class Vertex, class EProp, class VProp>
void operator()(Vertex v, EProp& eprop, VProp& vprop, Graph& g) const
{
typedef typename property_traits<EProp>::value_type eval_t;
typedef typename property_traits<VProp>::value_type vval_t;
convert<vval_t, eval_t> conv;
for (auto e : out_edges_range(v, g))
{
vprop[v] = conv(eprop[e]);
break;
}
for (auto e : out_edges_range(v, g))
vprop[v] = std::min(vprop[v], conv(eprop[e]));
}
};
struct MaxOp
{
template <class Graph, class Vertex, class EProp, class VProp>
void operator()(Vertex v, EProp& eprop, VProp& vprop, Graph& g) const
{
typedef typename property_traits<EProp>::value_type eval_t;
typedef typename property_traits<VProp>::value_type vval_t;
convert<vval_t, eval_t> conv;
for (auto e : out_edges_range(v, g))
{
vprop[v] = conv(eprop[e]);
break;
}
for (auto e : out_edges_range(v, g))
vprop[v] = std::max(vprop[v], conv(eprop[e]));
}
};
struct do_out_edges_op
{
template <class Graph, class EProp, class OP>
void operator()(Graph& g, EProp eprop, boost::any avprop, OP op) const
{
typedef typename property_traits<EProp>::value_type eval_t;
typedef typename property_map_type::apply<
typename mpl::if_<std::is_same<eval_t, size_t>,
int64_t, eval_t>::type,
GraphInterface::vertex_index_map_t>::type VProp;
typedef typename property_traits<VProp>::value_type vval_t;
auto vprop = boost::any_cast<VProp>(avprop).get_unchecked(num_vertices(g));
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(runtime) if (N > 100)
......@@ -54,17 +169,40 @@ struct do_out_edges_sum
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
vprop[v] = vval_t();
for (auto e : out_edges_range(v, g))
vprop[v] += conv(eprop[e]);
op(v, eprop, vprop, g);
}
}
};
void out_edges_sum(GraphInterface& gi, boost::any eprop, boost::any vprop)
void out_edges_op(GraphInterface& gi, boost::any eprop, boost::any vprop,
std::string op)
{
run_action<>()(gi, std::bind(do_out_edges_sum(), placeholders::_1,
placeholders::_2, placeholders::_3),
edge_properties(), writable_vertex_properties())
(eprop, vprop);
if (op == "sum")
{
run_action<>()(gi, std::bind(do_out_edges_op(), placeholders::_1,
placeholders::_2, vprop, SumOp()),
edge_properties())
(eprop);
}
else if (op == "prod")
{
run_action<>()(gi, std::bind(do_out_edges_op(), placeholders::_1,
placeholders::_2, vprop, ProdOp()),
edge_properties())
(eprop);
}
else if (op == "min")
{
run_action<>()(gi, std::bind(do_out_edges_op(), placeholders::_1,
placeholders::_2, vprop, MinOp()),
edge_properties())
(eprop);
}
else if (op == "max")
{
run_action<>()(gi, std::bind(do_out_edges_op(), placeholders::_1,
placeholders::_2, vprop, MaxOp()),
edge_properties())
(eprop);
}
}
......@@ -39,7 +39,7 @@ Summary
ungroup_vector_property
infect_vertex_property
edge_endpoint_property
incident_edges_sum
incident_edges_op
perfect_prop_hash
value_types
show_config
......@@ -125,7 +125,7 @@ __all__ = ["Graph", "GraphView", "Vertex", "Edge", "Vector_bool",
"Vector_size_t", "value_types", "load_graph", "PropertyMap",
"group_vector_property", "ungroup_vector_property",
"infect_vertex_property", "edge_endpoint_property",
"incident_edges_sum", "perfect_prop_hash", "seed_rng", "show_config",
"incident_edges_op", "perfect_prop_hash", "seed_rng", "show_config",
"PropertyArray", "openmp_enabled", "openmp_get_num_threads",
"openmp_set_num_threads", "openmp_get_schedule",
"openmp_set_schedule", "__author__", "__copyright__", "__URL__",
......@@ -1038,16 +1038,18 @@ def edge_endpoint_property(g, prop, endpoint, eprop=None):
_prop("e", g, eprop), endpoint)
return eprop
@_limit_args({"direction": ["in", "out"]})
def incident_edges_sum(g, direction, eprop, vprop=None):
"""Return a vertex property map corresponding to the sum of the edge property
`eprop` of incident edges on each vertex, following the direction given by
`direction`.
@_limit_args({"direction": ["in", "out"], "op": ["sum", "prod", "min", "max"]})
def incident_edges_op(g, direction, op, eprop, vprop=None):
"""Return a vertex property map corresponding to a specific operation (sum,
product, min or max) on the edge property `eprop` of incident edges on each
vertex, following the direction given by `direction`.
Parameters
----------
direction : `"in"` or `"out"`
Direction of the incident edges.
op : `"sum"`, `"prod"`, `"min"` or `"max"`
Operation performed on incident edges.
eprop : :class:`~graph_tool.PropertyMap`
Edge property map to be summed.
vprop : :class:`~graph_tool.PropertyMap` (optional, default: `None`)
......@@ -1062,7 +1064,7 @@ def incident_edges_sum(g, direction, eprop, vprop=None):
--------
>>> gt.seed_rng(42)
>>> g = gt.random_graph(100, lambda: (3, 3))
>>> vsum = gt.incident_edges_sum(g, "out", g.edge_index)
>>> vsum = gt.incident_edges_op(g, "out", "sum", g.edge_index)
>>> print(vsum.a)
[ 3 237 246 255 219 264 273 282 210 291 300 453 201 687 309 696 192 705
669 318 183 714 723 732 174 327 660 741 165 750 336 759 156 651 768 345
......@@ -1070,6 +1072,7 @@ def incident_edges_sum(g, direction, eprop, vprop=None):
624 849 102 381 858 867 93 615 390 876 84 885 894 399 75 606 678 597
66 408 588 579 57 570 417 561 48 552 543 426 39 534 525 516 30 435
507 498 21 489 444 480 12 471 462 228]
"""
val_t = eprop.value_type()
......@@ -1077,13 +1080,18 @@ def incident_edges_sum(g, direction, eprop, vprop=None):
val_t = "int64_t"
if vprop is None:
vprop = g.new_vertex_property(val_t)
orig_vprop = vprop
if vprop.value_type != val_t:
vprop = g.new_vertex_property(val_t)
if direction == "in" and not g.is_directed():
return vprop
return orig_vprop
if direction == "in":
g = GraphView(g, reversed=True, skip_properties=True)
libcore.out_edges_sum(g._Graph__graph, _prop("e", g, eprop),
_prop("v", g, vprop))
return vprop
libcore.out_edges_op(g._Graph__graph, _prop("e", g, eprop),
_prop("v", g, vprop), op)
if vprop is not orig_vprop:
g.copy_property(vprop, orig_vprop)
return orig_vprop
@_limit_args({"htype": ["int8_t", "int32_t", "int64_t"]})
def perfect_prop_hash(props, htype="int32_t"):
......
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