Commit dc184b46 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Fix edge indexing problem when modifying graph

This fixes a rather central bug, which causes duplicated indexes if
edges are removed and then new ones are added. Edge indexes are now
recycled as they are removed and then new ones are added. This still
guarantees O(1) complexity when adding or removing edges.
parent 562d8aa5
......@@ -185,6 +185,8 @@ private:
// edge index map
edge_index_map_t _edge_index;
vector<size_t> _free_indexes; // indexes of deleted edges to be used up for
// new edges to avoid needless fragmentation
// graph index map
graph_index_map_t _graph_index;
......
......@@ -162,13 +162,13 @@ struct add_new_edge
template <class Graph, class EdgeIndexMap>
void operator()(Graph* gp, const GraphInterface& gi, const PythonVertex& s,
const PythonVertex& t, EdgeIndexMap edge_index,
python::object& new_e) const
size_t new_index, python::object& new_e) const
{
Graph& g = *gp;
typename graph_traits<Graph>::edge_descriptor e =
add_edge(s.GetDescriptor(), t.GetDescriptor(), g).first;
new_e = python::object(PythonEdge<Graph>(gi, e));
edge_index[e] = num_edges(*gp) - 1;
edge_index[e] = new_index;
}
};
......@@ -179,10 +179,20 @@ python::object GraphInterface::AddEdge(const python::object& s,
PythonVertex& tgt = python::extract<PythonVertex&>(t);
src.CheckValid();
tgt.CheckValid();
size_t new_index;
if (_free_indexes.empty())
{
new_index = num_edges(_mg);
}
else
{
new_index = _free_indexes.back();
_free_indexes.pop_back();
}
python::object new_e;
run_action<>()(*this, lambda::bind<void>(add_new_edge(), lambda::_1,
lambda::var(*this), src, tgt,
_edge_index,
_edge_index, new_index,
lambda::var(new_e)))();
return new_e;
}
......@@ -213,6 +223,8 @@ void GraphInterface::RemoveEdge(const python::object& e)
lambda::var(found)))();
if (!found)
throw GraphException("invalid edge descriptor");
if (_edge_index[de] != num_edges(_mg) - 1)
_free_indexes.push_back(_edge_index[de]);
remove_edge(de, _mg);
}
......
......@@ -283,7 +283,7 @@ class Graph(object):
return self.__graph.AddVertex()
@_handle_exceptions
def remove_vertex(self, vertex, reindex_edges=True):
def remove_vertex(self, vertex):
"""Remove a vertex from the graph"""
k = vertex.in_degree() + vertex.out_degree()
index = self.vertex_index[vertex]
......
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