Commit 6957f8ec authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement PropertyMap.set_value()

parent bc126545
...@@ -400,6 +400,10 @@ void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop, ...@@ -400,6 +400,10 @@ 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);
void set_vertex_property(GraphInterface& gi, boost::any prop,
boost::python::object val);
void set_edge_property(GraphInterface& gi, boost::any prop,
boost::python::object val);
void export_python_interface(); void export_python_interface();
...@@ -527,6 +531,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_core) ...@@ -527,6 +531,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
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);
def("set_vertex_property", &set_vertex_property);
def("set_edge_property", &set_edge_property);
class_<LibInfo>("mod_info") class_<LibInfo>("mod_info")
.add_property("name", &LibInfo::GetName) .add_property("name", &LibInfo::GetName)
......
...@@ -176,37 +176,38 @@ struct do_infect_vertex_property ...@@ -176,37 +176,38 @@ struct do_infect_vertex_property
} }
} }
unchecked_vector_property_map<uint8_t, IndexMap> unchecked_vector_property_map<bool, IndexMap>
marked(index, num_vertices(g)); marked(index, num_vertices(g));
PropertyMap temp(index, 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)
for (i = 0; i < N; ++i) for (i = 0; i < N; ++i)
{ {
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g); auto v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex()) if (v == graph_traits<Graph>::null_vertex())
continue; continue;
bool skip;
{
#pragma omp critical
skip = marked[v];
}
if (skip)
continue;
if (!all && vals.find(prop[v]) == vals.end()) if (!all && vals.find(prop[v]) == vals.end())
continue; continue;
typename graph_traits<Graph>::adjacency_iterator a, a_end; for (auto a : adjacent_vertices_range(v, g))
for (tie(a, a_end) = adjacent_vertices(v, g); a != a_end; ++a)
{ {
if (prop[*a] == prop[v]) if (prop[a] == prop[v])
continue; continue;
{ marked[a] = true;
#pragma omp critical temp[a] = prop[v];
marked[*a] = true;
}
prop[*a] = prop[v];
} }
} }
#pragma omp parallel for default(shared) private(i)
for (i = 0; i < N; ++i)
{
auto v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
if (marked[v])
prop[v] = temp[v];
}
} }
}; };
...@@ -332,3 +333,46 @@ void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop, ...@@ -332,3 +333,46 @@ void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop,
edge_properties(), writable_edge_scalar_properties()) edge_properties(), writable_edge_scalar_properties())
(prop, hprop); (prop, hprop);
} }
struct do_set_vertex_property
{
template <class Graph, class PropertyMap>
void operator()(Graph& g, PropertyMap prop, boost::python::object oval) const
{
typedef typename property_traits<PropertyMap>::value_type val_t;
val_t val = boost::python::extract<val_t>(oval);
for (auto v : vertices_range(g))
prop[v] = val;
}
};
void set_vertex_property(GraphInterface& gi, boost::any prop,
boost::python::object val)
{
run_action<>()(gi, std::bind(do_set_vertex_property(), std::placeholders::_1,
std::placeholders::_2, val),
writable_vertex_properties())(prop);
}
struct do_set_edge_property
{
template <class Graph, class PropertyMap>
void operator()(Graph& g, PropertyMap prop, boost::python::object oval) const
{
typedef typename property_traits<PropertyMap>::value_type val_t;
val_t val = boost::python::extract<val_t>(oval);
for (auto e : edges_range(g))
prop[e] = val;
}
};
void set_edge_property(GraphInterface& gi, boost::any prop,
boost::python::object val)
{
run_action<>()(gi, std::bind(do_set_edge_property(), std::placeholders::_1,
std::placeholders::_2, val),
writable_edge_properties())(prop);
}
...@@ -799,6 +799,17 @@ class PropertyMap(object): ...@@ -799,6 +799,17 @@ class PropertyMap(object):
"""Return True if the property is writable.""" """Return True if the property is writable."""
return self.__map.is_writable() return self.__map.is_writable()
def set_value(self, val):
"""Sets all values in the property map to ``val``."""
g = self.get_graph()
if self.key_type() == "v":
libcore.set_vertex_property(g._Graph__graph, self.__map.get_map(), val)
elif self.key_type() == "e":
libcore.set_edge_property(g._Graph__graph, self.__map.get_map(), val)
else:
self[g] = val
def __call__(self, a): def __call__(self, a):
p = self.copy() p = self.copy()
p.fa = a p.fa = a
...@@ -2084,26 +2095,30 @@ class Graph(object): ...@@ -2084,26 +2095,30 @@ class Graph(object):
return self.new_graph_property(value_type, vals) return self.new_graph_property(value_type, vals)
raise ValueError("unknown key type: " + key_type) raise ValueError("unknown key type: " + key_type)
def new_vertex_property(self, value_type, vals=None): def new_vertex_property(self, value_type, vals=None, val=None):
"""Create a new (uninitialized) vertex property map of type ``value_type``, """Create a new vertex property map of type ``value_type``, and return it. If
and return it. If provided, the values will be initialized by ``vals``, provided, the values will be initialized by ``vals``, which should be
which should be either a sequence or a single value.""" sequence or by ``val`` which should be a single value.
"""
prop = PropertyMap(new_vertex_property(_type_alias(value_type), prop = PropertyMap(new_vertex_property(_type_alias(value_type),
self.__graph.GetVertexIndex(), self.__graph.GetVertexIndex(),
libcore.any()), libcore.any()),
self, "v") self, "v")
if vals is not None: if vals is not None:
try: try:
prop.a = vals prop.fa = vals
except ValueError: except ValueError:
for v, x in zip(self.vertices(), vals): for v, x in zip(self.vertices(), vals):
prop[v] = x prop[v] = x
elif val is not None:
prop.set_value(val)
return prop return prop
def new_edge_property(self, value_type, vals=None): def new_edge_property(self, value_type, vals=None, val=None):
"""Create a new (uninitialized) edge property map of type """Create a new edge property map of type ``value_type``, and return it. If
``value_type``, and return it. If provided, the values will be provided, the values will be initialized by ``vals``, which should be
initialized by ``vals``, which should be a sequence or a single value.""" sequence or by ``val`` which should be a single value.
"""
prop = PropertyMap(new_edge_property(_type_alias(value_type), prop = PropertyMap(new_edge_property(_type_alias(value_type),
self.__graph.GetEdgeIndex(), self.__graph.GetEdgeIndex(),
libcore.any()), libcore.any()),
...@@ -2114,6 +2129,8 @@ class Graph(object): ...@@ -2114,6 +2129,8 @@ class Graph(object):
except ValueError: except ValueError:
for e, x in zip(self.edges(), vals): for e, x in zip(self.edges(), vals):
prop[e] = x prop[e] = x
elif val is not None:
prop.set_value(val)
return prop return prop
def new_graph_property(self, value_type, val=None): def new_graph_property(self, value_type, val=None):
...@@ -2131,11 +2148,12 @@ class Graph(object): ...@@ -2131,11 +2148,12 @@ class Graph(object):
@_require("src", PropertyMap) @_require("src", PropertyMap)
@_require("tgt", (PropertyMap, type(None))) @_require("tgt", (PropertyMap, type(None)))
def copy_property(self, src, tgt=None, value_type=None, g=None): def copy_property(self, src, tgt=None, value_type=None, g=None):
"""Copy contents of ``src`` property to ``tgt`` property. If ``tgt`` is """Copy contents of ``src`` property to ``tgt`` property. If ``tgt`` is None,
None, then a new property map of the same type (or with the type given then a new property map of the same type (or with the type given by the
by the optional ``value_type`` parameter) is created, and returned. The optional ``value_type`` parameter) is created, and returned. The
optional parameter g specifies the (identical) source graph to copy optional parameter ``g`` specifies the source graph to copy properties
properties from (defaults to self). from (defaults to self).
""" """
if tgt is None: if tgt is None:
tgt = self.new_property(src.key_type(), tgt = self.new_property(src.key_type(),
...@@ -2159,13 +2177,29 @@ class Graph(object): ...@@ -2159,13 +2177,29 @@ class Graph(object):
g.set_edge_filter(None) g.set_edge_filter(None)
g.set_vertex_filter(None) g.set_vertex_filter(None)
if src.key_type() == "v": if src.key_type() == "v":
self.__graph.CopyVertexProperty(g.__graph, if g.num_vertices() > self.num_vertices():
_prop("v", g, src), raise ValueError("graphs with incompatible sizes (%d, %d)" %
_prop("v", self, tgt)) (g.num_vertices(), self.num_vertices()))
try:
self.__graph.CopyVertexProperty(g.__graph,
_prop("v", g, src),
_prop("v", self, tgt))
except ValueError:
raise ValueError("property maps with the following types are"
" not convertible: %s, %s" %
(src.value_type(), tgt.value_type()))
elif src.key_type() == "e": elif src.key_type() == "e":
self.__graph.CopyEdgeProperty(g.__graph, if g.num_edges() > self.num_edges():
_prop("e", g, src), raise ValueError("graphs with incompatible sizes (%d, %d)" %
_prop("e", self, tgt)) (g.num_edges(), self.num_edges()))
try:
self.__graph.CopyEdgeProperty(g.__graph,
_prop("e", g, src),
_prop("e", self, tgt))
except ValueError:
raise ValueError("property maps with the following types are"
" not convertible: %s, %s" %
(src.value_type(), tgt.value_type()))
else: else:
tgt[self] = src[g] tgt[self] = src[g]
finally: finally:
......
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