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, ...@@ -392,13 +392,12 @@ void infect_vertex_property(GraphInterface& gi, boost::any prop,
boost::python::object val); boost::python::object val);
void edge_endpoint(GraphInterface& gi, boost::any prop, void edge_endpoint(GraphInterface& gi, boost::any prop,
boost::any eprop, std::string endpoint); 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 mark_edges(GraphInterface& gi, boost::any prop);
void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop, void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop,
boost::any& dict); boost::any& dict);
void perfect_vhash(GraphInterface& gi, boost::any prop, boost::any hprop, void perfect_vhash(GraphInterface& gi, boost::any prop, boost::any hprop,
boost::any& dict); boost::any& dict);
...@@ -523,7 +522,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core) ...@@ -523,7 +522,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
def("ungroup_vector_property", &ungroup_vector_property); def("ungroup_vector_property", &ungroup_vector_property);
def("infect_vertex_property", &infect_vertex_property); def("infect_vertex_property", &infect_vertex_property);
def("edge_endpoint", &edge_endpoint); 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("mark_edges", &mark_edges);
def("perfect_ehash", &perfect_ehash); def("perfect_ehash", &perfect_ehash);
def("perfect_vhash", &perfect_vhash); def("perfect_vhash", &perfect_vhash);
......
...@@ -35,17 +35,132 @@ void operator+=(std::vector<Val1>& v1, const std::vector<Val2>& v2) ...@@ -35,17 +35,132 @@ void operator+=(std::vector<Val1>& v1, const std::vector<Val2>& v2)
v1[i] += v2[i]; 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> template <class Graph, class Vertex, class EProp, class VProp>
void operator()(Graph& g, EProp eprop, VProp vprop) const 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<EProp>::value_type eval_t;
typedef typename property_traits<VProp>::value_type vval_t; typedef typename property_traits<VProp>::value_type vval_t;
convert<vval_t, eval_t> conv; 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); int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \ #pragma omp parallel for default(shared) private(i) \
schedule(runtime) if (N > 100) schedule(runtime) if (N > 100)
...@@ -54,17 +169,40 @@ struct do_out_edges_sum ...@@ -54,17 +169,40 @@ struct do_out_edges_sum
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g); typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex()) if (v == graph_traits<Graph>::null_vertex())
continue; continue;
vprop[v] = vval_t(); op(v, eprop, vprop, g);
for (auto e : out_edges_range(v, g))
vprop[v] += conv(eprop[e]);
} }
} }
}; };
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, if (op == "sum")
placeholders::_2, placeholders::_3), {
edge_properties(), writable_vertex_properties()) run_action<>()(gi, std::bind(do_out_edges_op(), placeholders::_1,
(eprop, vprop); 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 ...@@ -39,7 +39,7 @@ Summary
ungroup_vector_property ungroup_vector_property
infect_vertex_property infect_vertex_property
edge_endpoint_property edge_endpoint_property
incident_edges_sum incident_edges_op
perfect_prop_hash perfect_prop_hash
value_types value_types
show_config show_config
...@@ -125,7 +125,7 @@ __all__ = ["Graph", "GraphView", "Vertex", "Edge", "Vector_bool", ...@@ -125,7 +125,7 @@ __all__ = ["Graph", "GraphView", "Vertex", "Edge", "Vector_bool",
"Vector_size_t", "value_types", "load_graph", "PropertyMap", "Vector_size_t", "value_types", "load_graph", "PropertyMap",
"group_vector_property", "ungroup_vector_property", "group_vector_property", "ungroup_vector_property",
"infect_vertex_property", "edge_endpoint_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", "PropertyArray", "openmp_enabled", "openmp_get_num_threads",
"openmp_set_num_threads", "openmp_get_schedule", "openmp_set_num_threads", "openmp_get_schedule",
"openmp_set_schedule", "__author__", "__copyright__", "__URL__", "openmp_set_schedule", "__author__", "__copyright__", "__URL__",
...@@ -1038,16 +1038,18 @@ def edge_endpoint_property(g, prop, endpoint, eprop=None): ...@@ -1038,16 +1038,18 @@ def edge_endpoint_property(g, prop, endpoint, eprop=None):
_prop("e", g, eprop), endpoint) _prop("e", g, eprop), endpoint)
return eprop return eprop
@_limit_args({"direction": ["in", "out"]}) @_limit_args({"direction": ["in", "out"], "op": ["sum", "prod", "min", "max"]})
def incident_edges_sum(g, direction, eprop, vprop=None): def incident_edges_op(g, direction, op, eprop, vprop=None):
"""Return a vertex property map corresponding to the sum of the edge property """Return a vertex property map corresponding to a specific operation (sum,
`eprop` of incident edges on each vertex, following the direction given by product, min or max) on the edge property `eprop` of incident edges on each
`direction`. vertex, following the direction given by `direction`.
Parameters Parameters
---------- ----------
direction : `"in"` or `"out"` direction : `"in"` or `"out"`
Direction of the incident edges. Direction of the incident edges.
op : `"sum"`, `"prod"`, `"min"` or `"max"`
Operation performed on incident edges.
eprop : :class:`~graph_tool.PropertyMap` eprop : :class:`~graph_tool.PropertyMap`
Edge property map to be summed. Edge property map to be summed.
vprop : :class:`~graph_tool.PropertyMap` (optional, default: `None`) vprop : :class:`~graph_tool.PropertyMap` (optional, default: `None`)
...@@ -1062,7 +1064,7 @@ def incident_edges_sum(g, direction, eprop, vprop=None): ...@@ -1062,7 +1064,7 @@ def incident_edges_sum(g, direction, eprop, vprop=None):
-------- --------
>>> gt.seed_rng(42) >>> gt.seed_rng(42)
>>> g = gt.random_graph(100, lambda: (3, 3)) >>> 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) >>> print(vsum.a)
[ 3 237 246 255 219 264 273 282 210 291 300 453 201 687 309 696 192 705 [ 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 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): ...@@ -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 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 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] 507 498 21 489 444 480 12 471 462 228]
""" """
val_t = eprop.value_type() val_t = eprop.value_type()
...@@ -1077,13 +1080,18 @@ def incident_edges_sum(g, direction, eprop, vprop=None): ...@@ -1077,13 +1080,18 @@ def incident_edges_sum(g, direction, eprop, vprop=None):
val_t = "int64_t" val_t = "int64_t"
if vprop is None: if vprop is None:
vprop = g.new_vertex_property(val_t) 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(): if direction == "in" and not g.is_directed():
return vprop return orig_vprop
if direction == "in": if direction == "in":
g = GraphView(g, reversed=True, skip_properties=True) g = GraphView(g, reversed=True, skip_properties=True)
libcore.out_edges_sum(g._Graph__graph, _prop("e", g, eprop), libcore.out_edges_op(g._Graph__graph, _prop("e", g, eprop),
_prop("v", g, vprop)) _prop("v", g, vprop), op)
return vprop if vprop is not orig_vprop:
g.copy_property(vprop, orig_vprop)
return orig_vprop
@_limit_args({"htype": ["int8_t", "int32_t", "int64_t"]}) @_limit_args({"htype": ["int8_t", "int32_t", "int64_t"]})
def perfect_prop_hash(props, htype="int32_t"): def perfect_prop_hash(props, htype="int32_t"):
......
Supports Markdown
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