mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Cache graph path (start, end) vertex pairs
To reduce graph traversal.
This commit is contained in:
@@ -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,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_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user