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

Fix edge index housekeeping

parent d6422b73
......@@ -40,6 +40,8 @@ GraphInterface::GraphInterface()
_directed(true),
_vertex_index(get(vertex_index,_mg)),
_edge_index(get(edge_index_t(),_mg)),
_max_edge_index(0),
_nedges(0),
_graph_index(0),
_vertex_filter_map(_vertex_index),
_vertex_filter_invert(false),
......
......@@ -18,6 +18,8 @@
#ifndef GRAPH_HH
#define GRAPH_HH
#include <deque>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
......@@ -153,6 +155,9 @@ public:
edge_index_map_t GetEdgeIndex() {return _edge_index;}
graph_index_map_t GetGraphIndex() {return graph_index_map_t(0);}
void AddEdgeIndex(const edge_t& e);
void RemoveEdgeIndex(const edge_t& e);
private:
// Gets the encapsulated graph view. See graph_filtering.cc for details
boost::any GetGraphView() const;
......@@ -191,9 +196,10 @@ 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
size_t _max_edge_index; // needed for property map bounds
deque<size_t> _free_indexes; // indexes of deleted edges to be used up for
// new edges to avoid very large indexes, and
// property map memory usage
size_t _max_edge_index;
// graph index map
graph_index_map_t _graph_index;
......
......@@ -131,15 +131,17 @@ check_filtered(const Graph &g, const EdgeFilter& edge_filter,
bool directed)
{
#ifndef NO_GRAPH_FILTERING
edge_filter.reserve(max_eindex);
vertex_filter.reserve(num_vertices(g));
MaskFilter<EdgeFilter> e_filter(edge_filter, e_invert);
MaskFilter<VertexFilter> v_filter(vertex_filter, v_invert);
if (e_active)
{
if (max_eindex > 0)
edge_filter.reserve(max_eindex+1);
if (v_active)
{
if (num_vertices(g) > 0)
vertex_filter.reserve(num_vertices(g));
typedef filtered_graph<Graph, MaskFilter<EdgeFilter>,
MaskFilter<VertexFilter> > fg_t;
fg_t init(g, e_filter, v_filter);
......@@ -162,6 +164,8 @@ check_filtered(const Graph &g, const EdgeFilter& edge_filter,
{
if (v_active)
{
if (num_vertices(g) > 0)
vertex_filter.reserve(num_vertices(g));
typedef filtered_graph<Graph, keep_all,
MaskFilter<VertexFilter> > fg_t;
fg_t init(g, keep_all(), v_filter);
......@@ -211,6 +215,9 @@ void GraphInterface::ReIndexEdges()
for (tie(v, v_end) = vertices(_mg); v != v_end; ++v)
for (tie(e, e_end) = out_edges(*v, _mg); e != e_end; ++e)
_edge_index[*e] = index++;
_max_edge_index = (index > 0) ? index - 1 : 0;
_nedges = index;
_free_indexes.clear();
}
// this will definitively remove all the edges from the graph, which are being
......@@ -231,10 +238,9 @@ void GraphInterface::PurgeEdges()
deleted_edges.push_back(*e);
for (typeof(deleted_edges.begin()) iter = deleted_edges.begin();
iter != deleted_edges.end(); ++iter)
remove_edge(*iter, _mg);
RemoveEdgeIndex(*iter);
deleted_edges.clear();
}
ReIndexEdges();
}
......
......@@ -160,18 +160,33 @@ void GraphInterface::RemoveVertex(const python::object& v)
struct add_new_edge
{
template <class Graph, class EdgeIndexMap>
void operator()(Graph* gp, const GraphInterface& gi, const PythonVertex& s,
void operator()(Graph* gp, GraphInterface& gi, const PythonVertex& s,
const PythonVertex& t, EdgeIndexMap edge_index,
size_t new_index, python::object& new_e) const
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] = new_index;
gi.AddEdgeIndex(e);
}
};
void GraphInterface::AddEdgeIndex(const edge_t& e)
{
if (!_free_indexes.empty())
{
_edge_index[e] = _free_indexes.front();
_free_indexes.pop_front();
}
else
{
_edge_index[e] = _nedges;
_max_edge_index = _nedges;
}
_nedges++;
}
python::object GraphInterface::AddEdge(const python::object& s,
const python::object& t)
{
......@@ -179,23 +194,11 @@ 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, new_index,
_edge_index,
lambda::var(new_e)))();
_nedges++;
_max_edge_index = max(_max_edge_index, new_index);
return new_e;
}
......@@ -225,12 +228,39 @@ void GraphInterface::RemoveEdge(const python::object& e)
lambda::var(found)))();
if (!found)
throw GraphException("invalid edge descriptor");
if (_edge_index[de] != _nedges - 1)
_free_indexes.push_back(_edge_index[de]);
RemoveEdgeIndex(de);
}
void GraphInterface::RemoveEdgeIndex(const edge_t& e)
{
size_t index = _edge_index[e];
if (index == _max_edge_index)
{
if (_max_edge_index - 1 == _free_indexes.back())
{
if (_max_edge_index > 0)
_max_edge_index--;
while (_max_edge_index == _free_indexes.back())
{
_free_indexes.pop_back();
if (_max_edge_index > 0)
_max_edge_index--;
}
}
else
{
if (_max_edge_index > 0)
_max_edge_index--;
}
}
else
_max_edge_index = (_nedges > 1) ? _nedges - 2 : 0;
remove_edge(de, _mg);
{
typeof(_free_indexes.begin()) pos =
lower_bound(_free_indexes.begin(), _free_indexes.end(), index);
_free_indexes.insert(pos, index);
}
_nedges--;
remove_edge(e, _mg);
}
struct get_degree_map
......
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