mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-11-19 10:34:25 +03:00
Introduce custom adjacency-list based graph
This commit is contained in:
@@ -52,7 +52,7 @@
|
||||
|
||||
using namespace std;
|
||||
using boost::default_color_type;
|
||||
using boost::filtered_graph;
|
||||
using boost::make_filtered_graph;
|
||||
using boost::make_assoc_property_map;
|
||||
using boost::adaptors::map_values;
|
||||
|
||||
@@ -172,15 +172,14 @@ namespace {
|
||||
struct CycleFound {};
|
||||
struct DetectCycles : public boost::default_dfs_visitor {
|
||||
explicit DetectCycles(const NGHolder &g) : startDs(g.startDs) {}
|
||||
void back_edge(const NFAEdge &e, const NFAGraph &g) const {
|
||||
void back_edge(const NFAEdge &e, const NGHolder &g) const {
|
||||
NFAVertex u = source(e, g), v = target(e, g);
|
||||
// We ignore the startDs self-loop.
|
||||
if (u == startDs && v == startDs) {
|
||||
return;
|
||||
}
|
||||
// Any other back-edge indicates a cycle.
|
||||
DEBUG_PRINTF("back edge %u->%u found\n", g[u].index,
|
||||
g[v].index);
|
||||
DEBUG_PRINTF("back edge %zu->%zu found\n", g[u].index, g[v].index);
|
||||
throw CycleFound();
|
||||
}
|
||||
private:
|
||||
@@ -215,10 +214,8 @@ bool isFloating(const NGHolder &g) {
|
||||
|
||||
bool isAcyclic(const NGHolder &g) {
|
||||
try {
|
||||
depth_first_search(
|
||||
g.g, visitor(DetectCycles(g))
|
||||
.root_vertex(g.start)
|
||||
.vertex_index_map(get(&NFAGraphVertexProps::index, g.g)));
|
||||
boost::depth_first_search(g, visitor(DetectCycles(g))
|
||||
.root_vertex(g.start));
|
||||
} catch (const CycleFound &) {
|
||||
return false;
|
||||
}
|
||||
@@ -234,11 +231,11 @@ bool hasReachableCycle(const NGHolder &g, NFAVertex src) {
|
||||
try {
|
||||
// Use depth_first_visit, rather than depth_first_search, so that we
|
||||
// only search from src.
|
||||
auto index_map = get(&NFAGraphVertexProps::index, g.g);
|
||||
depth_first_visit(
|
||||
g.g, src, DetectCycles(g),
|
||||
make_iterator_property_map(colors.begin(), index_map));
|
||||
} catch (const CycleFound&) {
|
||||
auto index_map = get(vertex_index, g);
|
||||
boost::depth_first_visit(g, src, DetectCycles(g),
|
||||
make_iterator_property_map(colors.begin(),
|
||||
index_map));
|
||||
} catch (const CycleFound &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -249,10 +246,7 @@ bool hasBigCycles(const NGHolder &g) {
|
||||
assert(hasCorrectlyNumberedVertices(g));
|
||||
set<NFAEdge> dead;
|
||||
BackEdges<set<NFAEdge>> backEdgeVisitor(dead);
|
||||
depth_first_search(
|
||||
g.g, visitor(backEdgeVisitor)
|
||||
.root_vertex(g.start)
|
||||
.vertex_index_map(get(&NFAGraphVertexProps::index, g.g)));
|
||||
boost::depth_first_search(g, visitor(backEdgeVisitor).root_vertex(g.start));
|
||||
|
||||
for (const auto &e : dead) {
|
||||
if (source(e, g) != target(e, g)) {
|
||||
@@ -266,8 +260,7 @@ bool hasBigCycles(const NGHolder &g) {
|
||||
set<NFAVertex> findVerticesInCycles(const NGHolder &g) {
|
||||
map<NFAVertex, size_t> comp_map;
|
||||
|
||||
strong_components(g.g, make_assoc_property_map(comp_map),
|
||||
vertex_index_map(get(&NFAGraphVertexProps::index, g.g)));
|
||||
strong_components(g, make_assoc_property_map(comp_map));
|
||||
|
||||
map<size_t, set<NFAVertex> > comps;
|
||||
|
||||
@@ -298,8 +291,7 @@ set<NFAVertex> findVerticesInCycles(const NGHolder &g) {
|
||||
|
||||
bool can_never_match(const NGHolder &g) {
|
||||
assert(edge(g.accept, g.acceptEod, g).second);
|
||||
if (!hasGreaterInDegree(0, g.accept, g)
|
||||
&& !hasGreaterInDegree(1, g.acceptEod, g)) {
|
||||
if (in_degree(g.accept, g) == 0 && in_degree(g.acceptEod, g) == 1) {
|
||||
DEBUG_PRINTF("no paths into accept\n");
|
||||
return true;
|
||||
}
|
||||
@@ -308,7 +300,7 @@ bool can_never_match(const NGHolder &g) {
|
||||
}
|
||||
|
||||
bool can_match_at_eod(const NGHolder &h) {
|
||||
if (hasGreaterInDegree(1, h.acceptEod, h)) {
|
||||
if (in_degree(h.acceptEod, h) > 1) {
|
||||
DEBUG_PRINTF("more than one edge to acceptEod\n");
|
||||
return true;
|
||||
}
|
||||
@@ -396,21 +388,17 @@ vector<NFAVertex> getTopoOrdering(const NGHolder &g) {
|
||||
EdgeSet backEdges;
|
||||
BackEdges<EdgeSet> be(backEdges);
|
||||
|
||||
auto index_map = get(&NFAGraphVertexProps::index, g.g);
|
||||
depth_first_search(g.g, visitor(be)
|
||||
.root_vertex(g.start)
|
||||
.color_map(make_iterator_property_map(
|
||||
colour.begin(), index_map))
|
||||
.vertex_index_map(index_map));
|
||||
auto index_map = get(vertex_index, g);
|
||||
depth_first_search(g, visitor(be).root_vertex(g.start)
|
||||
.color_map(make_iterator_property_map(
|
||||
colour.begin(), index_map)));
|
||||
|
||||
auto acyclic_g = make_filtered_graph(g.g, make_bad_edge_filter(&backEdges));
|
||||
auto acyclic_g = make_filtered_graph(g, make_bad_edge_filter(&backEdges));
|
||||
|
||||
vector<NFAVertex> ordering;
|
||||
ordering.reserve(num_verts);
|
||||
topological_sort(
|
||||
acyclic_g, back_inserter(ordering),
|
||||
color_map(make_iterator_property_map(colour.begin(), index_map))
|
||||
.vertex_index_map(index_map));
|
||||
topological_sort(acyclic_g, back_inserter(ordering),
|
||||
color_map(make_iterator_property_map(colour.begin(), index_map)));
|
||||
|
||||
reorderSpecials(g, ordering);
|
||||
|
||||
@@ -434,12 +422,12 @@ void mustBeSetBefore_int(NFAVertex u, const NGHolder &g,
|
||||
}
|
||||
}
|
||||
|
||||
auto prefix = make_filtered_graph(g.g, make_bad_edge_filter(&dead));
|
||||
auto prefix = make_filtered_graph(g, make_bad_edge_filter(&dead));
|
||||
|
||||
depth_first_visit(
|
||||
prefix, g.start, make_dfs_visitor(boost::null_visitor()),
|
||||
make_iterator_property_map(vertexColor.begin(),
|
||||
get(&NFAGraphVertexProps::index, g.g)));
|
||||
get(vertex_index, g)));
|
||||
}
|
||||
|
||||
bool mustBeSetBefore(NFAVertex u, NFAVertex v, const NGHolder &g,
|
||||
@@ -456,15 +444,14 @@ bool mustBeSetBefore(NFAVertex u, NFAVertex v, const NGHolder &g,
|
||||
mustBeSetBefore_int(u, g, vertexColor);
|
||||
|
||||
for (auto vi : vertices_range(g)) {
|
||||
auto key2 = make_pair(g[u].index,
|
||||
g[vi].index);
|
||||
DEBUG_PRINTF("adding %u %u\n", key2.first, key2.second);
|
||||
auto key2 = make_pair(g[u].index, g[vi].index);
|
||||
DEBUG_PRINTF("adding %zu %zu\n", key2.first, key2.second);
|
||||
assert(!contains(cache.cache, key2));
|
||||
bool value = vertexColor[g[vi].index] == boost::white_color;
|
||||
cache.cache[key2] = value;
|
||||
assert(contains(cache.cache, key2));
|
||||
}
|
||||
DEBUG_PRINTF("cache miss %u %u (%zu)\n", key.first, key.second,
|
||||
DEBUG_PRINTF("cache miss %zu %zu (%zu)\n", key.first, key.second,
|
||||
cache.cache.size());
|
||||
return cache.cache[key];
|
||||
}
|
||||
@@ -592,12 +579,13 @@ void fillHolder(NGHolder *outp, const NGHolder &in, const deque<NFAVertex> &vv,
|
||||
fillHolderOutEdges(out, in, v_map, u);
|
||||
}
|
||||
|
||||
out.renumberEdges();
|
||||
out.renumberVertices();
|
||||
renumber_edges(out);
|
||||
renumber_vertices(out);
|
||||
}
|
||||
|
||||
void cloneHolder(NGHolder &out, const NGHolder &in) {
|
||||
assert(hasCorrectlyNumberedVertices(in));
|
||||
assert(hasCorrectlyNumberedVertices(out));
|
||||
out.kind = in.kind;
|
||||
|
||||
// Note: depending on the state of the input graph, some stylized edges
|
||||
@@ -607,6 +595,7 @@ void cloneHolder(NGHolder &out, const NGHolder &in) {
|
||||
/* remove the existing special edges */
|
||||
clear_vertex(out.startDs, out);
|
||||
clear_vertex(out.accept, out);
|
||||
renumber_edges(out);
|
||||
|
||||
vector<NFAVertex> out_mapping(num_vertices(in));
|
||||
out_mapping[NODE_START] = out.start;
|
||||
@@ -642,8 +631,8 @@ void cloneHolder(NGHolder &out, const NGHolder &in) {
|
||||
}
|
||||
|
||||
// Safety checks.
|
||||
assert(num_vertices(in.g) == num_vertices(out.g));
|
||||
assert(num_edges(in.g) == num_edges(out.g));
|
||||
assert(num_vertices(in) == num_vertices(out));
|
||||
assert(num_edges(in) == num_edges(out));
|
||||
assert(hasCorrectlyNumberedVertices(out));
|
||||
}
|
||||
|
||||
@@ -672,9 +661,8 @@ unique_ptr<NGHolder> cloneHolder(const NGHolder &in) {
|
||||
void reverseHolder(const NGHolder &g_in, NGHolder &g) {
|
||||
// Make the BGL do the grunt work.
|
||||
ue2::unordered_map<NFAVertex, NFAVertex> vertexMap;
|
||||
boost::transpose_graph(g_in.g, g.g,
|
||||
orig_to_copy(boost::make_assoc_property_map(vertexMap)).
|
||||
vertex_index_map(get(&NFAGraphVertexProps::index, g_in.g)));
|
||||
boost::transpose_graph(g_in, g,
|
||||
orig_to_copy(boost::make_assoc_property_map(vertexMap)));
|
||||
|
||||
// The transpose_graph operation will have created extra copies of our
|
||||
// specials. We have to rewire their neighbours to the 'real' specials and
|
||||
@@ -716,8 +704,8 @@ void reverseHolder(const NGHolder &g_in, NGHolder &g) {
|
||||
|
||||
// Renumber so that g's properties (number of vertices, edges) are
|
||||
// accurate.
|
||||
g.renumberVertices();
|
||||
g.renumberEdges();
|
||||
renumber_vertices(g);
|
||||
renumber_edges(g);
|
||||
|
||||
assert(num_vertices(g) == num_vertices(g_in));
|
||||
assert(num_edges(g) == num_edges(g_in));
|
||||
@@ -729,8 +717,7 @@ bool allMatchStatesHaveReports(const NGHolder &g) {
|
||||
unordered_set<NFAVertex> reporters;
|
||||
for (auto v : inv_adjacent_vertices_range(g.accept, g)) {
|
||||
if (g[v].reports.empty()) {
|
||||
DEBUG_PRINTF("vertex %u has no reports!\n",
|
||||
g[v].index);
|
||||
DEBUG_PRINTF("vertex %zu has no reports!\n", g[v].index);
|
||||
return false;
|
||||
}
|
||||
reporters.insert(v);
|
||||
@@ -741,8 +728,7 @@ bool allMatchStatesHaveReports(const NGHolder &g) {
|
||||
continue; // stylised edge
|
||||
}
|
||||
if (g[v].reports.empty()) {
|
||||
DEBUG_PRINTF("vertex %u has no reports!\n",
|
||||
g[v].index);
|
||||
DEBUG_PRINTF("vertex %zu has no reports!\n", g[v].index);
|
||||
return false;
|
||||
}
|
||||
reporters.insert(v);
|
||||
@@ -750,7 +736,7 @@ bool allMatchStatesHaveReports(const NGHolder &g) {
|
||||
|
||||
for (auto v : vertices_range(g)) {
|
||||
if (!contains(reporters, v) && !g[v].reports.empty()) {
|
||||
DEBUG_PRINTF("vertex %u is not a match state, but has reports!\n",
|
||||
DEBUG_PRINTF("vertex %zu is not a match state, but has reports!\n",
|
||||
g[v].index);
|
||||
return false;
|
||||
}
|
||||
@@ -759,34 +745,6 @@ bool allMatchStatesHaveReports(const NGHolder &g) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasCorrectlyNumberedVertices(const NGHolder &g) {
|
||||
size_t count = num_vertices(g);
|
||||
vector<bool> ids(count, false);
|
||||
for (auto v : vertices_range(g)) {
|
||||
u32 id = g[v].index;
|
||||
if (id >= count || ids[id]) {
|
||||
return false; // duplicate
|
||||
}
|
||||
ids[id] = true;
|
||||
}
|
||||
return find(ids.begin(), ids.end(), false) == ids.end()
|
||||
&& num_vertices(g) == num_vertices(g.g);
|
||||
}
|
||||
|
||||
bool hasCorrectlyNumberedEdges(const NGHolder &g) {
|
||||
size_t count = num_edges(g);
|
||||
vector<bool> ids(count, false);
|
||||
for (const auto &e : edges_range(g)) {
|
||||
u32 id = g[e].index;
|
||||
if (id >= count || ids[id]) {
|
||||
return false; // duplicate
|
||||
}
|
||||
ids[id] = true;
|
||||
}
|
||||
return find(ids.begin(), ids.end(), false) == ids.end()
|
||||
&& num_edges(g) == num_edges(g.g);
|
||||
}
|
||||
|
||||
bool isCorrectlyTopped(const NGHolder &g) {
|
||||
if (is_triggered(g)) {
|
||||
for (const auto &e : out_edges_range(g.start, g)) {
|
||||
@@ -805,7 +763,6 @@ bool isCorrectlyTopped(const NGHolder &g) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
} // namespace ue2
|
||||
|
||||
Reference in New Issue
Block a user