Commit 3ba46e75 authored by Tiago Peixoto's avatar Tiago Peixoto

Fix graph copying and filtered graph copying semantics

Graphs are now exactly copied, including filter state and filter
property maps.
parent 919ade0c
......@@ -66,18 +66,10 @@ struct graph_copy
}
};
typedef graph_tool::detail::get_all_graph_views
::apply<graph_tool::detail::scalar_pairs,
mpl::bool_<false>,
mpl::bool_<true>,
mpl::bool_<false>,
mpl::bool_<true>,
mpl::bool_<true> >::type graph_views;
// copy constructor
GraphInterface::GraphInterface(const GraphInterface& gi)
:_mg(),
_reversed(false),
_reversed(gi._reversed),
_directed(gi._directed),
_vertex_index(get(vertex_index,_mg)),
_edge_index(get(edge_index_t(),_mg)),
......@@ -88,15 +80,11 @@ GraphInterface::GraphInterface(const GraphInterface& gi)
_edge_filter_invert(false),
_edge_filter_active(false)
{
typedef mpl::transform<detail::all_graph_views,
mpl::quote1<add_pointer> >::type all_graph_views;
run_action<>()(*this, bind<void>(graph_copy(), _1, _2,
_vertex_index,
gi._vertex_index,
_edge_index,
gi._edge_index),
all_graph_views())(gi.GetGraphView());
graph_copy()(&_mg, &gi._mg, _vertex_index,
gi._vertex_index, _edge_index,
gi._edge_index);
// filters will be copied in python
}
//
......@@ -156,7 +144,11 @@ struct convert
{
T1 operator()(const string& v) const
{
return lexical_cast<Type1>(v);
//uint8_t is not char, it is bool!
if (is_same<T1, uint8_t>::value)
return convert<T1,int>()(lexical_cast<int>(v));
else
return lexical_cast<Type1>(v);
}
};
......@@ -165,7 +157,11 @@ struct convert
{
string operator()(const T2& v) const
{
return lexical_cast<string>(v);
//uint8_t is not char, it is bool!
if (is_same<T2, uint8_t>::value)
return lexical_cast<string>(convert<int,T2>()(v));
else
return lexical_cast<string>(v);
}
};
......@@ -205,7 +201,7 @@ struct copy_property
{
template <class Graph, class PropertySrc,
class PropertyTgt>
void operator()(Graph* tgtp, boost::any srcp, PropertySrc src_map,
void operator()(const Graph* tgtp, const Graph* srcp, PropertySrc src_map,
PropertyTgt dst_map) const
{
typedef typename property_traits<PropertySrc>::value_type val_src;
......@@ -213,8 +209,8 @@ struct copy_property
try
{
Graph& tgt = *tgtp;
Graph& src = *any_cast<Graph*>(srcp);
const Graph& tgt = *tgtp;
const Graph& src = *srcp;
convert<val_tgt,val_src> c;
typename IteratorSel::template apply<Graph>::type vs, vs_end;
typename IteratorSel::template apply<Graph>::type vt, vt_end;
......@@ -269,19 +265,17 @@ struct vertex_selector
}
};
typedef mpl::vector<GraphInterface::multigraph_t> unfiltered;
void GraphInterface::CopyVertexProperty(const GraphInterface& src,
boost::any prop_src,
boost::any prop_tgt)
{
typedef property_map_types::apply<mpl::vector<string,vector<string> >,
GraphInterface::edge_index_map_t,
mpl::bool_<false> >::type
edge_properties;
typedef edge_properties writable_edge_properties;
run_action<graph_views>()
run_action<unfiltered>()
(*this, bind<void>(copy_property<vertex_selector>(),
_1, src.GetGraphView(), _2, _3),
_1, &src._mg, _2, _3),
vertex_properties(), writable_vertex_properties())
(prop_src, prop_tgt);
}
......@@ -290,15 +284,11 @@ void GraphInterface::CopyEdgeProperty(const GraphInterface& src,
boost::any prop_src,
boost::any prop_tgt)
{
typedef property_map_types::apply<mpl::vector<double>,
GraphInterface::edge_index_map_t,
mpl::bool_<false> >::type
edge_properties;
typedef edge_properties writable_edge_properties;
run_action<graph_views>()
run_action<unfiltered>()
(*this, bind<void>(copy_property<edge_selector>(),
_1, src.GetGraphView(), _2, _3),
_1, &src._mg, _2, _3),
edge_properties(), writable_edge_properties())
(prop_src, prop_tgt);
}
......@@ -55,7 +55,7 @@ def _prop(t, g, prop):
try:
pmap = g.properties[(t,prop)]
except KeyError:
raise GraphError("no internal %s property named: %d" %\
raise GraphError("no internal %s property named: %s" %\
("vertex" if t == "v" else \
("edge" if t == "e" else "graph"),prop))
else:
......@@ -214,10 +214,33 @@ class Graph(object):
for k,v in g.__properties.iteritems():
new_p = self.new_property(v.key_type(), v.value_type())
self.copy_property(v, new_p, g)
self.properties[(v.key_type(),k)] = new_p
self.properties[k] = new_p
self.__stashed_filter_state = [g.__filter_state]
if libcore.graph_filtering_enabled():
self.pop_filter()
v_filt, v_rev = g.__filter_state["vertex_filter"]
if v_filt != None:
if v_filt not in g.vertex_properties.values():
new_filt = self.new_vertex_property("bool")
self.copy_property(v_filt, new_filt)
else:
for k,v in g.vertex_properties.iteritems():
if v == v_filt:
new_filt = self.vertex_properties[k]
self.__stashed_filter_state[0]["vertex_filter"] = (new_filt,
v_rev)
e_filt, e_rev = g.__filter_state["edge_filter"]
if e_filt != None:
if e_filt not in g.edge_properties.values():
new_filt = self.new_edge_property("bool")
self.copy_property(e_filt, new_filt)
else:
for k,v in g.edge_properties.iteritems():
if v == e_filt:
new_filt = self.edge_properties[k]
self.__stashed_filter_state[0]["edge_filter"] = (new_filt,
e_rev)
self.pop_filter()
@_handle_exceptions
def copy(self):
......@@ -427,11 +450,11 @@ class Graph(object):
g.stash_filter()
self.stash_filter()
if src.key_type() == "v":
self.__graph.CopyVertexProperty(g.__graph, src._PropertyMap__map,
tgt._PropertyMap__map)
self.__graph.CopyVertexProperty(g.__graph, _prop("v", g, src),
_prop("v", g, tgt))
elif src.key_type() == "e":
self.__graph.CopyEdgeProperty(g.__graph, src._PropertyMap__map,
tgt._PropertyMap__map)
self.__graph.CopyEdgeProperty(g.__graph, _prop("e", g, src),
_prop("e", g, tgt))
else:
tgt[self] = src[g]
self.pop_filter()
......@@ -565,21 +588,22 @@ class Graph(object):
"""Remove all vertices of the graph which are currently being filtered
out, and return to the unfiltered state"""
self.__graph.PurgeVertices()
self.__graph.SetVertexFilterProperty('')
self.__graph.SetVertexFilterProperty(None)
@_handle_exceptions
def purge_edges(self):
"""Remove all edges of the graph which are currently being filtered out,
and return to the unfiltered state"""
self.__graph.PurgeEdges()
self.__graph.SetEdgeFilterProperty('')
self.__graph.SetEdgeFilterProperty(None)
@_handle_exceptions
def stash_filter(self):
"""Stash current filter state and recover unfiltered graph"""
self.__stashed_filter_state.append(self.__filter_state)
self.set_vertex_filter("")
self.set_edge_filter("")
if libcore.graph_filtering_enabled():
self.set_vertex_filter(None)
self.set_edge_filter(None)
self.directed()
self.set_reversed(False)
......@@ -587,10 +611,11 @@ class Graph(object):
def pop_filter(self):
"""Pop last stashed filter state"""
state = self.__stashed_filter_state.pop()
self.set_vertex_filter(state["vertex_filter"][0],
state["vertex_filter"][1])
self.set_edge_filter(state["edge_filter"][0],
state["edge_filter"][1])
if libcore.graph_filtering_enabled():
self.set_vertex_filter(state["vertex_filter"][0],
state["vertex_filter"][1])
self.set_edge_filter(state["edge_filter"][0],
state["edge_filter"][1])
self.set_directed(state["directed"])
self.set_reversed(state["reversed"])
......
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