aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp
diff options
context:
space:
mode:
authorIvan Blinkov <ivan@blinkov.ru>2022-02-10 16:47:11 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:47:11 +0300
commit5b283123c882433dafbaf6b338adeea16c1a0ea0 (patch)
tree339adc63bce23800021202ae4a8328a843dc447a /contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp
parent1aeb9a455974457866f78722ad98114bafc84e8a (diff)
downloadydb-5b283123c882433dafbaf6b338adeea16c1a0ea0.tar.gz
Restoring authorship annotation for Ivan Blinkov <ivan@blinkov.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp')
-rw-r--r--contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp394
1 files changed, 197 insertions, 197 deletions
diff --git a/contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp b/contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp
index e51307d296..8aaaf99fde 100644
--- a/contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp
+++ b/contrib/libs/hyperscan/src/nfagraph/ng_misc_opt.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, Intel Corporation
+ * Copyright (c) 2015-2017, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -69,20 +69,20 @@
#include "util/charreach.h"
#include "util/container.h"
#include "util/graph_range.h"
-#include "util/graph_small_color_map.h"
-#include "util/flat_containers.h"
+#include "util/graph_small_color_map.h"
+#include "util/flat_containers.h"
#include "ue2common.h"
-#include <boost/dynamic_bitset.hpp>
-#include <boost/graph/depth_first_search.hpp>
-#include <boost/graph/filtered_graph.hpp>
-
+#include <boost/dynamic_bitset.hpp>
+#include <boost/graph/depth_first_search.hpp>
+#include <boost/graph/filtered_graph.hpp>
+
#include <map>
#include <set>
#include <vector>
using namespace std;
-using boost::make_filtered_graph;
+using boost::make_filtered_graph;
namespace ue2 {
@@ -101,8 +101,8 @@ void findCandidates(NGHolder &g, const vector<NFAVertex> &ordering,
// For `v' to be a candidate, its predecessors must all have the same
// successor set as `v'.
- auto succ_v = succs(v, g);
- flat_set<NFAVertex> succ_u;
+ auto succ_v = succs(v, g);
+ flat_set<NFAVertex> succ_u;
for (auto u : inv_adjacent_vertices_range(v, g)) {
succ_u.clear();
@@ -111,7 +111,7 @@ void findCandidates(NGHolder &g, const vector<NFAVertex> &ordering,
goto next_cand;
}
}
- DEBUG_PRINTF("vertex %zu is a candidate\n", g[v].index);
+ DEBUG_PRINTF("vertex %zu is a candidate\n", g[v].index);
cand->push_back(v);
next_cand:;
}
@@ -132,8 +132,8 @@ void findCandidates_rev(NGHolder &g, const vector<NFAVertex> &ordering,
// For `v' to be a candidate, its predecessors must all have the same
// successor set as `v'.
- auto pred_v = preds(v, g);
- flat_set<NFAVertex> pred_u;
+ auto pred_v = preds(v, g);
+ flat_set<NFAVertex> pred_u;
for (auto u : adjacent_vertices_range(v, g)) {
pred_u.clear();
@@ -142,7 +142,7 @@ void findCandidates_rev(NGHolder &g, const vector<NFAVertex> &ordering,
goto next_cand;
}
}
- DEBUG_PRINTF("vertex %zu is a candidate\n", g[v].index);
+ DEBUG_PRINTF("vertex %zu is a candidate\n", g[v].index);
cand->push_back(v);
next_cand:;
}
@@ -179,7 +179,7 @@ void succCRIntersection(const NGHolder &g, NFAVertex v, CharReach &add) {
static
set<NFAVertex> findSustainSet(const NGHolder &g, NFAVertex p,
bool ignore_starts, const CharReach &new_cr) {
- auto cand = preds<set<NFAVertex>>(p, g);
+ auto cand = preds<set<NFAVertex>>(p, g);
if (ignore_starts) {
cand.erase(g.startDs);
}
@@ -215,7 +215,7 @@ set<NFAVertex> findSustainSet(const NGHolder &g, NFAVertex p,
static
set<NFAVertex> findSustainSet_rev(const NGHolder &g, NFAVertex p,
const CharReach &new_cr) {
- auto cand = succs<set<NFAVertex>>(p, g);
+ auto cand = succs<set<NFAVertex>>(p, g);
/* remove elements from cand until the sustain set property holds */
bool changed;
do {
@@ -245,7 +245,7 @@ set<NFAVertex> findSustainSet_rev(const NGHolder &g, NFAVertex p,
static
bool enlargeCyclicVertex(NGHolder &g, som_type som, NFAVertex v) {
- DEBUG_PRINTF("considering vertex %zu\n", g[v].index);
+ DEBUG_PRINTF("considering vertex %zu\n", g[v].index);
const CharReach &v_cr = g[v].char_reach;
CharReach add;
@@ -264,7 +264,7 @@ bool enlargeCyclicVertex(NGHolder &g, som_type som, NFAVertex v) {
if (p == v) {
continue;
}
- DEBUG_PRINTF("looking at pred %zu\n", g[p].index);
+ DEBUG_PRINTF("looking at pred %zu\n", g[p].index);
bool ignore_sds = som; /* if we are tracking som, entries into a state
from sds are significant. */
@@ -294,13 +294,13 @@ bool enlargeCyclicVertex(NGHolder &g, som_type som, NFAVertex v) {
/* the cr can be increased */
g[v].char_reach = add;
- DEBUG_PRINTF("vertex %zu was widened\n", g[v].index);
+ DEBUG_PRINTF("vertex %zu was widened\n", g[v].index);
return true;
}
static
bool enlargeCyclicVertex_rev(NGHolder &g, NFAVertex v) {
- DEBUG_PRINTF("considering vertex %zu\n", g[v].index);
+ DEBUG_PRINTF("considering vertex %zu\n", g[v].index);
const CharReach &v_cr = g[v].char_reach;
CharReach add;
@@ -319,7 +319,7 @@ bool enlargeCyclicVertex_rev(NGHolder &g, NFAVertex v) {
if (p == v) {
continue;
}
- DEBUG_PRINTF("looking at succ %zu\n", g[p].index);
+ DEBUG_PRINTF("looking at succ %zu\n", g[p].index);
set<NFAVertex> sustain = findSustainSet_rev(g, p, add);
DEBUG_PRINTF("sustain set is %zu\n", sustain.size());
@@ -344,7 +344,7 @@ bool enlargeCyclicVertex_rev(NGHolder &g, NFAVertex v) {
/* the cr can be increased */
g[v].char_reach = add;
- DEBUG_PRINTF("vertex %zu was widened\n", g[v].index);
+ DEBUG_PRINTF("vertex %zu was widened\n", g[v].index);
return true;
}
@@ -393,7 +393,7 @@ bool improveGraph(NGHolder &g, som_type som) {
* enlargeCyclicCR. */
CharReach reduced_cr(NFAVertex v, const NGHolder &g,
const map<NFAVertex, BoundedRepeatSummary> &br_cyclic) {
- DEBUG_PRINTF("find minimal cr for %zu\n", g[v].index);
+ DEBUG_PRINTF("find minimal cr for %zu\n", g[v].index);
CharReach v_cr = g[v].char_reach;
if (proper_in_degree(v, g) != 1) {
return v_cr;
@@ -551,178 +551,178 @@ bool mergeCyclicDotStars(NGHolder &g) {
return true;
}
-struct PrunePathsInfo {
- explicit PrunePathsInfo(const NGHolder &g)
- : color_map(make_small_color_map(g)), bad(num_vertices(g)) {}
-
- void clear() {
- no_explore.clear();
- color_map.fill(small_color::white);
- bad.reset();
- }
-
- flat_set<NFAEdge> no_explore;
- using color_map_type = decltype(make_small_color_map(NGHolder()));
- color_map_type color_map;
- boost::dynamic_bitset<> bad;
-};
-
-/**
- * Finds the set of vertices that cannot be on if v is not on, setting their
- * indices in bitset PrunePathsInfo::bad.
- */
-static
-void findDependentVertices(const NGHolder &g, PrunePathsInfo &info,
- NFAVertex v) {
- /* We need to exclude any vertex that may be reached on a path which is
- * incompatible with the vertex v being on. */
-
- /* A vertex u is bad if:
- * 1) its reach may be incompatible with v (not a subset)
- * 2) it if there is an edge from a bad vertex b and there is either not an
- * edge v->u or not an edge b->v.
- * Note: 2) means v is never bad as it has a selfloop
- *
- * Can do this with a DFS from all the initial bad states with a conditional
- * check down edges. Alternately can just filter these edges out of the
- * graph first.
- */
- for (NFAVertex t : adjacent_vertices_range(v, g)) {
- for (NFAEdge e : in_edges_range(t, g)) {
- NFAVertex s = source(e, g);
- if (edge(s, v, g).second) {
- info.no_explore.insert(e);
- }
- }
- }
-
- auto filtered_g =
- make_filtered_graph(g, make_bad_edge_filter(&info.no_explore));
-
- // We use a bitset to track bad vertices, rather than filling a (potentially
- // very large) set structure.
- auto recorder = make_vertex_index_bitset_recorder(info.bad);
-
- for (NFAVertex b : vertices_range(g)) {
- if (b != g.start && g[b].char_reach.isSubsetOf(g[v].char_reach)) {
- continue;
- }
- boost::depth_first_visit(filtered_g, b, recorder, info.color_map);
- }
-}
-
-static
-bool willBeEnabledConcurrently(NFAVertex main_cyclic, NFAVertex v,
- const NGHolder &g) {
- return is_subset_of(preds(main_cyclic, g), preds(v, g));
-}
-
-static
-bool sometimesEnabledConcurrently(NFAVertex main_cyclic, NFAVertex v,
- const NGHolder &g) {
- return has_intersection(preds(main_cyclic, g), preds(v, g));
-}
-
-static
-bool pruneUsingSuccessors(NGHolder &g, PrunePathsInfo &info, NFAVertex u,
- som_type som) {
- if (som && (is_virtual_start(u, g) || u == g.startDs)) {
- return false;
- }
-
- bool changed = false;
- DEBUG_PRINTF("using cyclic %zu as base\n", g[u].index);
- info.clear();
- findDependentVertices(g, info, u);
- vector<NFAVertex> u_succs;
- for (NFAVertex v : adjacent_vertices_range(u, g)) {
- if (som && is_virtual_start(v, g)) {
- /* as v is virtual start, its som has been reset so can not override
- * existing in progress matches. */
- continue;
- }
- u_succs.push_back(v);
- }
-
- stable_sort(u_succs.begin(), u_succs.end(),
- [&](NFAVertex a, NFAVertex b) {
- return g[a].char_reach.count() > g[b].char_reach.count();
- });
-
- flat_set<NFAEdge> dead;
-
- for (NFAVertex v : u_succs) {
- DEBUG_PRINTF(" using %zu as killer\n", g[v].index);
- /* Need to distinguish between vertices that are switched on after the
- * cyclic vs vertices that are switched on concurrently with the cyclic
- * if (subject to a suitable reach) */
- bool v_peer_of_cyclic = willBeEnabledConcurrently(u, v, g);
- for (NFAVertex s : adjacent_vertices_range(v, g)) {
- DEBUG_PRINTF(" looking at preds of %zu\n", g[s].index);
- for (NFAEdge e : in_edges_range(s, g)) {
- NFAVertex p = source(e, g);
- if (info.bad.test(g[p].index) || p == v || p == u
- || p == g.accept) {
- DEBUG_PRINTF("%zu not a cand\n", g[p].index);
- continue;
- }
- if (is_any_accept(s, g) && g[p].reports != g[v].reports) {
- DEBUG_PRINTF("%zu bad reports\n", g[p].index);
- continue;
- }
- /* the out-edges of a vertex that may be enabled on the same
- * byte as the cyclic can only be killed by the out-edges of a
- * peer vertex which will be enabled with the cyclic (a non-peer
- * may not be switched on until another byte is processed). */
- if (!v_peer_of_cyclic
- && sometimesEnabledConcurrently(u, p, g)) {
- DEBUG_PRINTF("%zu can only be squashed by a proper peer\n",
- g[p].index);
- continue;
- }
-
- if (g[p].char_reach.isSubsetOf(g[v].char_reach)) {
- dead.insert(e);
- changed = true;
- DEBUG_PRINTF("removing edge %zu->%zu\n", g[p].index,
- g[s].index);
- } else if (is_subset_of(succs(p, g), succs(u, g))) {
- if (is_match_vertex(p, g)
- && !is_subset_of(g[p].reports, g[v].reports)) {
- continue;
- }
- DEBUG_PRINTF("updating reach on %zu\n", g[p].index);
- changed |= (g[p].char_reach & g[v].char_reach).any();
- g[p].char_reach &= ~g[v].char_reach;
- }
-
- }
- }
- remove_edges(dead, g);
- dead.clear();
- }
-
- DEBUG_PRINTF("changed %d\n", (int)changed);
- return changed;
-}
-
-bool prunePathsRedundantWithSuccessorOfCyclics(NGHolder &g, som_type som) {
- /* TODO: the reverse form of this is also possible */
- bool changed = false;
- PrunePathsInfo info(g);
-
- for (NFAVertex v : vertices_range(g)) {
- if (hasSelfLoop(v, g) && g[v].char_reach.all()) {
- changed |= pruneUsingSuccessors(g, info, v, som);
- }
- }
-
- if (changed) {
- pruneUseless(g);
- clearReports(g);
- }
-
- return changed;
-}
-
+struct PrunePathsInfo {
+ explicit PrunePathsInfo(const NGHolder &g)
+ : color_map(make_small_color_map(g)), bad(num_vertices(g)) {}
+
+ void clear() {
+ no_explore.clear();
+ color_map.fill(small_color::white);
+ bad.reset();
+ }
+
+ flat_set<NFAEdge> no_explore;
+ using color_map_type = decltype(make_small_color_map(NGHolder()));
+ color_map_type color_map;
+ boost::dynamic_bitset<> bad;
+};
+
+/**
+ * Finds the set of vertices that cannot be on if v is not on, setting their
+ * indices in bitset PrunePathsInfo::bad.
+ */
+static
+void findDependentVertices(const NGHolder &g, PrunePathsInfo &info,
+ NFAVertex v) {
+ /* We need to exclude any vertex that may be reached on a path which is
+ * incompatible with the vertex v being on. */
+
+ /* A vertex u is bad if:
+ * 1) its reach may be incompatible with v (not a subset)
+ * 2) it if there is an edge from a bad vertex b and there is either not an
+ * edge v->u or not an edge b->v.
+ * Note: 2) means v is never bad as it has a selfloop
+ *
+ * Can do this with a DFS from all the initial bad states with a conditional
+ * check down edges. Alternately can just filter these edges out of the
+ * graph first.
+ */
+ for (NFAVertex t : adjacent_vertices_range(v, g)) {
+ for (NFAEdge e : in_edges_range(t, g)) {
+ NFAVertex s = source(e, g);
+ if (edge(s, v, g).second) {
+ info.no_explore.insert(e);
+ }
+ }
+ }
+
+ auto filtered_g =
+ make_filtered_graph(g, make_bad_edge_filter(&info.no_explore));
+
+ // We use a bitset to track bad vertices, rather than filling a (potentially
+ // very large) set structure.
+ auto recorder = make_vertex_index_bitset_recorder(info.bad);
+
+ for (NFAVertex b : vertices_range(g)) {
+ if (b != g.start && g[b].char_reach.isSubsetOf(g[v].char_reach)) {
+ continue;
+ }
+ boost::depth_first_visit(filtered_g, b, recorder, info.color_map);
+ }
+}
+
+static
+bool willBeEnabledConcurrently(NFAVertex main_cyclic, NFAVertex v,
+ const NGHolder &g) {
+ return is_subset_of(preds(main_cyclic, g), preds(v, g));
+}
+
+static
+bool sometimesEnabledConcurrently(NFAVertex main_cyclic, NFAVertex v,
+ const NGHolder &g) {
+ return has_intersection(preds(main_cyclic, g), preds(v, g));
+}
+
+static
+bool pruneUsingSuccessors(NGHolder &g, PrunePathsInfo &info, NFAVertex u,
+ som_type som) {
+ if (som && (is_virtual_start(u, g) || u == g.startDs)) {
+ return false;
+ }
+
+ bool changed = false;
+ DEBUG_PRINTF("using cyclic %zu as base\n", g[u].index);
+ info.clear();
+ findDependentVertices(g, info, u);
+ vector<NFAVertex> u_succs;
+ for (NFAVertex v : adjacent_vertices_range(u, g)) {
+ if (som && is_virtual_start(v, g)) {
+ /* as v is virtual start, its som has been reset so can not override
+ * existing in progress matches. */
+ continue;
+ }
+ u_succs.push_back(v);
+ }
+
+ stable_sort(u_succs.begin(), u_succs.end(),
+ [&](NFAVertex a, NFAVertex b) {
+ return g[a].char_reach.count() > g[b].char_reach.count();
+ });
+
+ flat_set<NFAEdge> dead;
+
+ for (NFAVertex v : u_succs) {
+ DEBUG_PRINTF(" using %zu as killer\n", g[v].index);
+ /* Need to distinguish between vertices that are switched on after the
+ * cyclic vs vertices that are switched on concurrently with the cyclic
+ * if (subject to a suitable reach) */
+ bool v_peer_of_cyclic = willBeEnabledConcurrently(u, v, g);
+ for (NFAVertex s : adjacent_vertices_range(v, g)) {
+ DEBUG_PRINTF(" looking at preds of %zu\n", g[s].index);
+ for (NFAEdge e : in_edges_range(s, g)) {
+ NFAVertex p = source(e, g);
+ if (info.bad.test(g[p].index) || p == v || p == u
+ || p == g.accept) {
+ DEBUG_PRINTF("%zu not a cand\n", g[p].index);
+ continue;
+ }
+ if (is_any_accept(s, g) && g[p].reports != g[v].reports) {
+ DEBUG_PRINTF("%zu bad reports\n", g[p].index);
+ continue;
+ }
+ /* the out-edges of a vertex that may be enabled on the same
+ * byte as the cyclic can only be killed by the out-edges of a
+ * peer vertex which will be enabled with the cyclic (a non-peer
+ * may not be switched on until another byte is processed). */
+ if (!v_peer_of_cyclic
+ && sometimesEnabledConcurrently(u, p, g)) {
+ DEBUG_PRINTF("%zu can only be squashed by a proper peer\n",
+ g[p].index);
+ continue;
+ }
+
+ if (g[p].char_reach.isSubsetOf(g[v].char_reach)) {
+ dead.insert(e);
+ changed = true;
+ DEBUG_PRINTF("removing edge %zu->%zu\n", g[p].index,
+ g[s].index);
+ } else if (is_subset_of(succs(p, g), succs(u, g))) {
+ if (is_match_vertex(p, g)
+ && !is_subset_of(g[p].reports, g[v].reports)) {
+ continue;
+ }
+ DEBUG_PRINTF("updating reach on %zu\n", g[p].index);
+ changed |= (g[p].char_reach & g[v].char_reach).any();
+ g[p].char_reach &= ~g[v].char_reach;
+ }
+
+ }
+ }
+ remove_edges(dead, g);
+ dead.clear();
+ }
+
+ DEBUG_PRINTF("changed %d\n", (int)changed);
+ return changed;
+}
+
+bool prunePathsRedundantWithSuccessorOfCyclics(NGHolder &g, som_type som) {
+ /* TODO: the reverse form of this is also possible */
+ bool changed = false;
+ PrunePathsInfo info(g);
+
+ for (NFAVertex v : vertices_range(g)) {
+ if (hasSelfLoop(v, g) && g[v].char_reach.all()) {
+ changed |= pruneUsingSuccessors(g, info, v, som);
+ }
+ }
+
+ if (changed) {
+ pruneUseless(g);
+ clearReports(g);
+ }
+
+ return changed;
+}
+
} // namespace ue2