Change LinkGraph::EdgeMatrix to a sparse storage format

Use a btree_map instead of a SmallMatrix.
This avoids excessive storage requirements for large graphs,
and overly expensive edge matrix resize operations.
Remove next_edge iteration mechanism.
This commit is contained in:
Jonathan G Rennison
2022-12-05 18:17:25 +00:00
parent c457dc680b
commit e647075870
16 changed files with 353 additions and 470 deletions

View File

@@ -82,20 +82,19 @@ public:
DynUniformArenaAllocator path_allocator; ///< Arena allocator used for paths
/**
* A job edge. Wraps a link graph edge and an edge annotation. The
* annotation can be modified, the edge is constant.
* An annotation-only job edge. Wraps an edge annotation. The
* annotation can be modified.
*/
class Edge : public LinkGraph::ConstEdge {
class AnnoEdge {
private:
EdgeAnnotation &anno; ///< Annotation being wrapped.
public:
/**
* Constructor.
* @param edge Link graph edge to be wrapped.
* @param anno Annotation to be wrapped.
*/
Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
LinkGraph::ConstEdge(edge), anno(anno) {}
AnnoEdge(EdgeAnnotation &anno) :
anno(anno) {}
/**
* Get the transport demand between end the points of the edge.
@@ -153,39 +152,18 @@ public:
};
/**
* Iterator for job edges.
* A job edge. Wraps a link graph edge and an edge annotation. The
* annotation can be modified, the edge is constant.
*/
class EdgeIterator : public LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator> {
EdgeAnnotation *base_anno; ///< Array of annotations to be (indirectly) iterated.
class Edge : public LinkGraph::ConstEdge, public AnnoEdge {
public:
/**
* Constructor.
* @param base Array of edges to be iterated.
* @param base_anno Array of annotations to be iterated.
* @param current Start offset of iteration.
* @param edge Link graph edge to be wrapped.
* @param anno Annotation to be wrapped.
*/
EdgeIterator(const LinkGraph::BaseEdge *base, EdgeAnnotation *base_anno, NodeID current) :
LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, current),
base_anno(base_anno) {}
/**
* Dereference.
* @return Pair of the edge currently pointed to and the ID of its
* other end.
*/
std::pair<NodeID, Edge> operator*() const
{
return std::pair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
}
/**
* Dereference. Has to be repeated here as operator* is different than
* in LinkGraph::EdgeWrapper.
* @return Fake pointer to pair of NodeID/Edge.
*/
FakePointer operator->() const {
return FakePointer(this->operator*());
}
Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
LinkGraph::ConstEdge(edge), AnnoEdge(anno) {}
};
/**
@@ -214,21 +192,11 @@ public:
* @param to Remote end of the edge.
* @return Edge between this node and "to".
*/
Edge operator[](NodeID to) const { return Edge(this->edges[to], this->edge_annos[to]); }
AnnoEdge operator[](NodeID to) const { return AnnoEdge(this->edge_annos[to]); }
/**
* Iterator for the "begin" of the edge array. Only edges with capacity
* are iterated. The others are skipped.
* @return Iterator pointing to the first edge.
*/
EdgeIterator Begin() const { return EdgeIterator(this->edges, this->edge_annos, index); }
Edge MakeEdge(const LinkGraph::BaseEdge &base_edge, NodeID to) const { return Edge(base_edge, this->edge_annos[to]); }
/**
* Iterator for the "end" of the edge array. Only edges with capacity
* are iterated. The others are skipped.
* @return Iterator pointing beyond the last edge.
*/
EdgeIterator End() const { return EdgeIterator(this->edges, this->edge_annos, INVALID_NODE); }
Edge MakeEdge(const LinkGraphJob &lgj, NodeID to) const { return this->MakeEdge(lgj.GetBaseEdge(this->GetNodeID(), to), to); }
/**
* Get amount of supply that hasn't been delivered, yet.
@@ -390,6 +358,26 @@ public:
* @return Link graph.
*/
inline const LinkGraph &Graph() const { return this->link_graph; }
const LinkGraph::BaseEdge &GetBaseEdge(NodeID from, NodeID to) const
{
return this->link_graph.GetBaseEdge(from, to);
}
template <typename F>
void IterateEdgesFromNode(const Node &from_node, F proc)
{
auto iter = this->link_graph.GetEdges().lower_bound(std::make_pair(from_node.GetNodeID(), (NodeID)0));
while (iter != this->link_graph.GetEdges().end()) {
NodeID from = iter->first.first;
NodeID to = iter->first.second;
if (from != from_node.GetNodeID()) return;
if (from != to) {
proc(from, to, from_node.MakeEdge(iter->second, to));
}
++iter;
}
}
};
/**