Commit 2b749c41 authored by Tiago Peixoto's avatar Tiago Peixoto

Improve copying of edge properties

parent 1495bc72
......@@ -435,6 +435,10 @@ void set_vertex_property(GraphInterface& gi, boost::any prop,
void set_edge_property(GraphInterface& gi, boost::any prop,
boost::python::object val);
void copy_external_edge_property(const GraphInterface& src,
const GraphInterface& tgt,
boost::any prop_src,
boost::any prop_tgt);
void export_python_interface();
......@@ -563,6 +567,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
def("perfect_vhash", &perfect_vhash);
def("set_vertex_property", &set_vertex_property);
def("set_edge_property", &set_edge_property);
def("copy_external_edge_property", &copy_external_edge_property);
class_<LibInfo>("mod_info")
.add_property("name", &LibInfo::GetName)
......
......@@ -124,6 +124,69 @@ struct vertex_selector
}
};
template <class PropertyMaps>
struct copy_external_edge_property_dispatch
{
template <class GraphTgt, class GraphSrc, class PropertyTgt>
void operator()(const GraphTgt& tgt, const GraphSrc& src,
PropertyTgt dst_map, boost::any prop_src) const
{
try
{
auto src_map = boost::any_cast<typename PropertyTgt::checked_t>(prop_src);
dispatch(tgt, src, dst_map, src_map);
}
catch (boost::bad_any_cast&)
{
typedef typename boost::property_traits<PropertyTgt>::value_type val_tgt;
typedef typename boost::graph_traits<GraphSrc>::edge_descriptor edge_t;
DynamicPropertyMapWrap<val_tgt, edge_t> src_map(prop_src, PropertyMaps());
dispatch(tgt, src, dst_map, src_map);
}
}
template <class GraphTgt, class GraphSrc, class PropertyTgt,
class PropertySrc>
void dispatch(const GraphTgt& tgt, const GraphSrc& src,
PropertyTgt dst_map, PropertySrc src_map) const
{
typedef typename boost::graph_traits<GraphSrc>::edge_descriptor edge_t;
gt_hash_map<std::tuple<size_t,size_t>, std::deque<edge_t>> src_edges;
for (auto e : edges_range(src))
{
auto u = source(e, src);
auto v = target(e, src);
if (!graph_tool::is_directed(src) && u > v)
std::swap(u, v);
src_edges[std::make_tuple(u, v)].push_back(e);
}
try
{
for (auto e : edges_range(tgt))
{
auto u = source(e, tgt);
auto v = target(e, tgt);
if (!graph_tool::is_directed(src) && u > v)
std::swap(u, v);
auto& es = src_edges[std::make_tuple(u, v)];
if (es.empty())
throw ValueException("source and target graphs are not compatible");
put(dst_map, e, get(src_map, es.front()));
es.pop_front();
}
}
catch (boost::bad_lexical_cast&)
{
throw ValueException("property values are not convertible");
}
}
};
} // namespace graph_tool
#endif // GRAPH_PROPERTIES_COPY_HH
......@@ -40,3 +40,17 @@ void GraphInterface::copy_edge_property(const GraphInterface& src,
writable_edge_properties())
(this->get_graph_view(), src.get_graph_view(), prop_tgt);
}
void copy_external_edge_property(const GraphInterface& src,
const GraphInterface& tgt,
boost::any prop_src,
boost::any prop_tgt)
{
gt_dispatch<>()
(std::bind(copy_external_edge_property_dispatch<edge_properties>(),
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, prop_src),
all_graph_views(), all_graph_views(),
writable_edge_properties())
(tgt.get_graph_view(), src.get_graph_view(), prop_tgt);
}
......@@ -2724,10 +2724,15 @@ class Graph(object):
sf = self
if full:
g = GraphView(g, skip_properties=True, skip_efilt=True,
skip_vfilt=True, directed=True)
sf = GraphView(sf, skip_properties=True, skip_efilt=True,
skip_vfilt=True, directed=True)
if g is sf:
g = GraphView(g, skip_properties=True, skip_efilt=True,
skip_vfilt=True, directed=True)
sf = g
else:
g = GraphView(g, skip_properties=True, skip_efilt=True,
skip_vfilt=True, directed=True)
sf = GraphView(sf, skip_properties=True, skip_efilt=True,
skip_vfilt=True, directed=True)
if src.key_type() == "v":
if g.num_vertices() > sf.num_vertices():
raise ValueError("graphs with incompatible sizes (%d, %d)" %
......@@ -2736,22 +2741,26 @@ class Graph(object):
sf.__graph.copy_vertex_property(g.__graph,
_prop("v", g, src),
_prop("v", sf, tgt))
except ValueError:
raise ValueError("property maps with the following types are"
" not convertible: %s, %s" %
(src.value_type(), tgt.value_type()))
except ValueError as e:
raise ValueError("error copying maps with types %s, %s: %s" %
(src.value_type(), tgt.value_type(), str(e)))
elif src.key_type() == "e":
if g.num_edges() > sf.num_edges():
raise ValueError("graphs with incompatible sizes (%d, %d)" %
(g.num_edges(), sf.num_edges()))
try:
sf.__graph.copy_edge_property(g.__graph,
_prop("e", g, src),
_prop("e", sf, tgt))
except ValueError:
raise ValueError("property maps with the following types are"
" not convertible: %s, %s" %
(src.value_type(), tgt.value_type()))
if g is sf:
sf.__graph.copy_edge_property(g.__graph,
_prop("e", g, src),
_prop("e", sf, tgt))
else:
libcore.copy_external_edge_property(g.__graph,
self.__graph,
_prop("e", g, src),
_prop("e", sf, tgt))
except ValueError as e:
raise ValueError("error copying maps with types %s, %s: %s" %
(src.value_type(), tgt.value_type(), str(e)))
else:
tgt[sf] = src[g]
return ret
......
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