Cache graph path (start, end) vertex pairs

To reduce graph traversal.
This commit is contained in:
Oliver Hamlet
2019-06-23 17:07:13 +01:00
parent b0c63dde63
commit 6327ad369b
2 changed files with 53 additions and 10 deletions
+23 -9
View File
@@ -83,6 +83,7 @@ std::vector<std::string> PluginSorter::Sort(Game& game) {
// Clear existing data.
graph_.clear();
indexMap_.clear();
pathsCache_.clear();
AddPluginVertices(game);
@@ -264,7 +265,11 @@ void PluginSorter::CheckForCycles() const {
}
bool PluginSorter::EdgeCreatesCycle(const vertex_t& fromVertex,
const vertex_t& toVertex) const {
const vertex_t& toVertex) {
if (pathsCache_.count(GraphPath(toVertex, fromVertex)) != 0) {
return true;
}
auto start = toVertex;
auto end = fromVertex;
@@ -288,6 +293,8 @@ bool PluginSorter::EdgeCreatesCycle(const vertex_t& fromVertex,
for (auto adjacentV :
boost::make_iterator_range(boost::adjacent_vertices(v, graph_))) {
if (forwardVisited.count(adjacentV) == 0) {
pathsCache_.insert(GraphPath(start, adjacentV));
forwardVisited.insert(adjacentV);
forwardQueue.push(adjacentV);
}
@@ -302,6 +309,8 @@ bool PluginSorter::EdgeCreatesCycle(const vertex_t& fromVertex,
for (auto adjacentV : boost::make_iterator_range(
boost::inv_adjacent_vertices(v, graph_))) {
if (reverseVisited.count(adjacentV) == 0) {
pathsCache_.insert(GraphPath(adjacentV, end));
reverseVisited.insert(adjacentV);
reverseQueue.push(adjacentV);
}
@@ -315,16 +324,21 @@ bool PluginSorter::EdgeCreatesCycle(const vertex_t& fromVertex,
void PluginSorter::AddEdge(const vertex_t& fromVertex,
const vertex_t& toVertex,
EdgeType edgeType) {
if (!boost::edge(fromVertex, toVertex, graph_).second) {
if (logger_) {
logger_->trace("Adding {} edge from \"{}\" to \"{}\".",
describeEdgeType(edgeType),
graph_[fromVertex].GetName(),
graph_[toVertex].GetName());
}
auto graphPath = GraphPath(fromVertex, toVertex);
boost::add_edge(fromVertex, toVertex, edgeType, graph_);
if (pathsCache_.count(graphPath) != 0) {
return;
}
if (logger_) {
logger_->trace("Adding {} edge from \"{}\" to \"{}\".",
describeEdgeType(edgeType),
graph_[fromVertex].GetName(),
graph_[toVertex].GetName());
}
boost::add_edge(fromVertex, toVertex, edgeType, graph_);
pathsCache_.insert(graphPath);
}
void PluginSorter::AddHardcodedPluginEdges(Game& game) {
+30 -1
View File
@@ -30,6 +30,7 @@
#include <map>
#include <spdlog/spdlog.h>
#include <boost/container_hash/hash.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
@@ -51,6 +52,32 @@ typedef boost::associative_property_map<std::map<vertex_t, size_t>>
std::string describeEdgeType(EdgeType edgeType);
struct GraphPath {
GraphPath(vertex_t from, vertex_t to) : from(from), to(to) {}
bool operator==(const GraphPath& rhs) const {
return this->from == rhs.from && this->to == rhs.to;
}
vertex_t from;
vertex_t to;
};
}
namespace std {
template<>
struct hash<loot::GraphPath> {
size_t operator()(const loot::GraphPath& graphPath) const {
size_t seed = 0;
boost::hash_combine(seed, graphPath.from);
boost::hash_combine(seed, graphPath.to);
return seed;
}
};
}
namespace loot {
class PluginSorter {
public:
std::vector<std::string> Sort(Game& game);
@@ -58,7 +85,7 @@ public:
private:
std::optional<vertex_t> GetVertexByName(const std::string& name) const;
void CheckForCycles() const;
bool EdgeCreatesCycle(const vertex_t& u, const vertex_t& v) const;
bool EdgeCreatesCycle(const vertex_t& u, const vertex_t& v);
void AddPluginVertices(Game& game);
void AddSpecificEdges();
@@ -76,6 +103,8 @@ private:
vertex_map_t vertexIndexMap_;
std::shared_ptr<spdlog::logger> logger_;
std::unordered_set<Group> groups_;
std::unordered_set<GraphPath> pathsCache_;
};
}