diff options
author | bnagaev <bnagaev@yandex-team.ru> | 2022-02-10 16:47:04 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:04 +0300 |
commit | d6449ba66291ff0c0d352c82e6eb3efb4c8a7e8d (patch) | |
tree | d5dca6d44593f5e52556a1cc7b1ab0386e096ebe /contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp | |
parent | 1861d4c1402bb2c67a3e6b43b51706081b74508a (diff) | |
download | ydb-d6449ba66291ff0c0d352c82e6eb3efb4c8a7e8d.tar.gz |
Restoring authorship annotation for <bnagaev@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp')
-rw-r--r-- | contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp | 628 |
1 files changed, 314 insertions, 314 deletions
diff --git a/contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp b/contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp index 6c90326ce4..e952ff445e 100644 --- a/contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp +++ b/contrib/libs/hyperscan/src/nfagraph/ng_depth.cpp @@ -1,398 +1,398 @@ -/* +/* * 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: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /** * \file - * \brief NFA graph vertex depth calculations. - */ -#include "ng_depth.h" -#include "ng_util.h" -#include "ue2common.h" -#include "util/graph_range.h" + * \brief NFA graph vertex depth calculations. + */ +#include "ng_depth.h" +#include "ng_util.h" +#include "ue2common.h" +#include "util/graph_range.h" #include "util/graph_small_color_map.h" - -#include <deque> -#include <vector> - + +#include <deque> +#include <vector> + #include <boost/graph/breadth_first_search.hpp> -#include <boost/graph/dag_shortest_paths.hpp> -#include <boost/graph/depth_first_search.hpp> -#include <boost/graph/filtered_graph.hpp> +#include <boost/graph/dag_shortest_paths.hpp> +#include <boost/graph/depth_first_search.hpp> +#include <boost/graph/filtered_graph.hpp> #include <boost/graph/property_maps/constant_property_map.hpp> -#include <boost/graph/reverse_graph.hpp> -#include <boost/graph/topological_sort.hpp> +#include <boost/graph/reverse_graph.hpp> +#include <boost/graph/topological_sort.hpp> #include <boost/range/adaptor/reversed.hpp> - -using namespace std; -using boost::filtered_graph; + +using namespace std; +using boost::filtered_graph; using boost::make_filtered_graph; -using boost::make_constant_property; -using boost::reverse_graph; +using boost::make_constant_property; +using boost::reverse_graph; using boost::adaptors::reverse; - -namespace ue2 { - -namespace { - -/** Distance value used to indicate that the vertex can't be reached. */ -static constexpr int DIST_UNREACHABLE = INT_MAX; - -/** - * Distance value used to indicate that the distance to a vertex is infinite - * (for example, it's the max distance and there's a cycle in the path) or so - * large that we should consider it effectively infinite. - */ -static constexpr int DIST_INFINITY = INT_MAX - 1; - -// -// Filters -// - -template <class GraphT> -struct NodeFilter { - typedef typename GraphT::edge_descriptor EdgeT; - NodeFilter() {} // BGL filters must be default-constructible. - NodeFilter(const vector<bool> *bad_in, const GraphT *g_in) - : bad(bad_in), g(g_in) { } - bool operator()(const EdgeT &e) const { - assert(g && bad); - - u32 src_idx = (*g)[source(e, *g)].index; - u32 tar_idx = (*g)[target(e, *g)].index; - - if (tar_idx == NODE_START_DOTSTAR) { - return false; - } - - return !(*bad)[src_idx] && !(*bad)[tar_idx]; - } - -private: - const vector<bool> *bad = nullptr; - const GraphT *g = nullptr; -}; - -template <class GraphT> -struct StartFilter { - typedef typename GraphT::edge_descriptor EdgeT; - StartFilter() {} // BGL filters must be default-constructible. - explicit StartFilter(const GraphT *g_in) : g(g_in) { } - bool operator()(const EdgeT &e) const { - assert(g); - - u32 src_idx = (*g)[source(e, *g)].index; - u32 tar_idx = (*g)[target(e, *g)].index; - - // Remove our stylised edges from anchored start to startDs. - if (src_idx == NODE_START && tar_idx == NODE_START_DOTSTAR) { - return false; - } - // Also remove the equivalent in the reversed direction. - if (src_idx == NODE_ACCEPT_EOD && tar_idx == NODE_ACCEPT) { - return false; - } - return true; - } - -private: - const GraphT *g = nullptr; -}; - -} // namespace - + +namespace ue2 { + +namespace { + +/** Distance value used to indicate that the vertex can't be reached. */ +static constexpr int DIST_UNREACHABLE = INT_MAX; + +/** + * Distance value used to indicate that the distance to a vertex is infinite + * (for example, it's the max distance and there's a cycle in the path) or so + * large that we should consider it effectively infinite. + */ +static constexpr int DIST_INFINITY = INT_MAX - 1; + +// +// Filters +// + +template <class GraphT> +struct NodeFilter { + typedef typename GraphT::edge_descriptor EdgeT; + NodeFilter() {} // BGL filters must be default-constructible. + NodeFilter(const vector<bool> *bad_in, const GraphT *g_in) + : bad(bad_in), g(g_in) { } + bool operator()(const EdgeT &e) const { + assert(g && bad); + + u32 src_idx = (*g)[source(e, *g)].index; + u32 tar_idx = (*g)[target(e, *g)].index; + + if (tar_idx == NODE_START_DOTSTAR) { + return false; + } + + return !(*bad)[src_idx] && !(*bad)[tar_idx]; + } + +private: + const vector<bool> *bad = nullptr; + const GraphT *g = nullptr; +}; + +template <class GraphT> +struct StartFilter { + typedef typename GraphT::edge_descriptor EdgeT; + StartFilter() {} // BGL filters must be default-constructible. + explicit StartFilter(const GraphT *g_in) : g(g_in) { } + bool operator()(const EdgeT &e) const { + assert(g); + + u32 src_idx = (*g)[source(e, *g)].index; + u32 tar_idx = (*g)[target(e, *g)].index; + + // Remove our stylised edges from anchored start to startDs. + if (src_idx == NODE_START && tar_idx == NODE_START_DOTSTAR) { + return false; + } + // Also remove the equivalent in the reversed direction. + if (src_idx == NODE_ACCEPT_EOD && tar_idx == NODE_ACCEPT) { + return false; + } + return true; + } + +private: + const GraphT *g = nullptr; +}; + +} // namespace + template<class Graph> -static +static vector<bool> findLoopReachable(const Graph &g, const typename Graph::vertex_descriptor src) { vector<bool> deadNodes(num_vertices(g)); - + using Edge = typename Graph::edge_descriptor; using Vertex = typename Graph::vertex_descriptor; using EdgeSet = set<Edge>; - EdgeSet deadEdges; - BackEdges<EdgeSet> be(deadEdges); - + EdgeSet deadEdges; + BackEdges<EdgeSet> be(deadEdges); + auto colors = make_small_color_map(g); - + depth_first_search(g, be, colors, src); auto af = make_bad_edge_filter(&deadEdges); auto acyclic_g = make_filtered_graph(g, af); - + vector<Vertex> topoOrder; /* actually reverse topological order */ - topoOrder.reserve(deadNodes.size()); + topoOrder.reserve(deadNodes.size()); topological_sort(acyclic_g, back_inserter(topoOrder), color_map(colors)); - - for (const auto &e : deadEdges) { + + for (const auto &e : deadEdges) { size_t srcIdx = g[source(e, g)].index; - if (srcIdx != NODE_START_DOTSTAR) { - deadNodes[srcIdx] = true; - } - } - + if (srcIdx != NODE_START_DOTSTAR) { + deadNodes[srcIdx] = true; + } + } + for (auto v : reverse(topoOrder)) { - for (const auto &e : in_edges_range(v, g)) { - if (deadNodes[g[source(e, g)].index]) { - deadNodes[g[v].index] = true; - break; - } - } - } + for (const auto &e : in_edges_range(v, g)) { + if (deadNodes[g[source(e, g)].index]) { + deadNodes[g[v].index] = true; + break; + } + } + } return deadNodes; -} - -template <class GraphT> -static +} + +template <class GraphT> +static void calcDepthFromSource(const GraphT &g, - typename GraphT::vertex_descriptor srcVertex, + typename GraphT::vertex_descriptor srcVertex, const vector<bool> &deadNodes, vector<int> &dMin, vector<int> &dMax) { - typedef typename GraphT::edge_descriptor EdgeT; - + typedef typename GraphT::edge_descriptor EdgeT; + const size_t numVerts = num_vertices(g); - - NodeFilter<GraphT> nf(&deadNodes, &g); - StartFilter<GraphT> sf(&g); - - /* minimum distance needs to run on a graph with .*start unreachable - * from start */ - typedef filtered_graph<GraphT, StartFilter<GraphT> > StartFilteredGraph; - const StartFilteredGraph mindist_g(g, sf); - - /* maximum distance needs to run on a graph without cycles & nodes - * reachable from cycles */ - typedef filtered_graph<GraphT, NodeFilter<GraphT> > NodeFilteredGraph; - const NodeFilteredGraph maxdist_g(g, nf); - - // Record distance of each vertex from source using one of the following - // algorithms. - - /* note: filtered graphs have same num_{vertices,edges} as base */ - - dMin.assign(numVerts, DIST_UNREACHABLE); - dMax.assign(numVerts, DIST_UNREACHABLE); - dMin[mindist_g[srcVertex].index] = 0; - - using boost::make_iterator_property_map; - + + NodeFilter<GraphT> nf(&deadNodes, &g); + StartFilter<GraphT> sf(&g); + + /* minimum distance needs to run on a graph with .*start unreachable + * from start */ + typedef filtered_graph<GraphT, StartFilter<GraphT> > StartFilteredGraph; + const StartFilteredGraph mindist_g(g, sf); + + /* maximum distance needs to run on a graph without cycles & nodes + * reachable from cycles */ + typedef filtered_graph<GraphT, NodeFilter<GraphT> > NodeFilteredGraph; + const NodeFilteredGraph maxdist_g(g, nf); + + // Record distance of each vertex from source using one of the following + // algorithms. + + /* note: filtered graphs have same num_{vertices,edges} as base */ + + dMin.assign(numVerts, DIST_UNREACHABLE); + dMax.assign(numVerts, DIST_UNREACHABLE); + dMin[mindist_g[srcVertex].index] = 0; + + using boost::make_iterator_property_map; + auto min_index_map = get(vertex_index, mindist_g); - - breadth_first_search(mindist_g, srcVertex, - visitor(make_bfs_visitor(record_distances( + + breadth_first_search(mindist_g, srcVertex, + visitor(make_bfs_visitor(record_distances( make_iterator_property_map(dMin.begin(), min_index_map), boost::on_tree_edge()))) .color_map(make_small_color_map(mindist_g))); - + auto max_index_map = get(vertex_index, maxdist_g); - - dag_shortest_paths(maxdist_g, srcVertex, + + dag_shortest_paths(maxdist_g, srcVertex, distance_map(make_iterator_property_map(dMax.begin(), max_index_map)) .weight_map(make_constant_property<EdgeT>(-1)) .color_map(make_small_color_map(maxdist_g))); - - for (size_t i = 0; i < numVerts; i++) { - if (dMin[i] > DIST_UNREACHABLE) { - dMin[i] = DIST_UNREACHABLE; - } - DEBUG_PRINTF("%zu: dm %d %d\n", i, dMin[i], dMax[i]); - if (dMax[i] >= DIST_UNREACHABLE && dMin[i] < DIST_UNREACHABLE) { - dMax[i] = -DIST_INFINITY; /* max depths currently negative */ - DEBUG_PRINTF("bumping max to %d\n", dMax[i]); - } else if (dMax[i] >= DIST_UNREACHABLE - || dMax[i] < -DIST_UNREACHABLE) { - dMax[i] = -DIST_UNREACHABLE; - DEBUG_PRINTF("bumping max to %d\n", dMax[i]); - } - } -} - -/** - * \brief Convert the integer distance we use in our shortest path calculations - * to a \ref depth value. - */ -static -depth depthFromDistance(int val) { - assert(val >= 0); - if (val >= DIST_UNREACHABLE) { - return depth::unreachable(); - } else if (val == DIST_INFINITY) { - return depth::infinity(); - } - return depth((u32)val); -} - -static -DepthMinMax getDepths(u32 idx, const vector<int> &dMin, - const vector<int> &dMax) { - DepthMinMax d(depthFromDistance(dMin[idx]), - depthFromDistance(-1 * dMax[idx])); - DEBUG_PRINTF("idx=%u, depths=%s\n", idx, d.str().c_str()); - assert(d.min <= d.max); - return d; -} - -template<class Graph, class Output> -static + + for (size_t i = 0; i < numVerts; i++) { + if (dMin[i] > DIST_UNREACHABLE) { + dMin[i] = DIST_UNREACHABLE; + } + DEBUG_PRINTF("%zu: dm %d %d\n", i, dMin[i], dMax[i]); + if (dMax[i] >= DIST_UNREACHABLE && dMin[i] < DIST_UNREACHABLE) { + dMax[i] = -DIST_INFINITY; /* max depths currently negative */ + DEBUG_PRINTF("bumping max to %d\n", dMax[i]); + } else if (dMax[i] >= DIST_UNREACHABLE + || dMax[i] < -DIST_UNREACHABLE) { + dMax[i] = -DIST_UNREACHABLE; + DEBUG_PRINTF("bumping max to %d\n", dMax[i]); + } + } +} + +/** + * \brief Convert the integer distance we use in our shortest path calculations + * to a \ref depth value. + */ +static +depth depthFromDistance(int val) { + assert(val >= 0); + if (val >= DIST_UNREACHABLE) { + return depth::unreachable(); + } else if (val == DIST_INFINITY) { + return depth::infinity(); + } + return depth((u32)val); +} + +static +DepthMinMax getDepths(u32 idx, const vector<int> &dMin, + const vector<int> &dMax) { + DepthMinMax d(depthFromDistance(dMin[idx]), + depthFromDistance(-1 * dMax[idx])); + DEBUG_PRINTF("idx=%u, depths=%s\n", idx, d.str().c_str()); + assert(d.min <= d.max); + return d; +} + +template<class Graph, class Output> +static void calcAndStoreDepth(const Graph &g, - const typename Graph::vertex_descriptor src, - const vector<bool> &deadNodes, - vector<int> &dMin /* util */, - vector<int> &dMax /* util */, - vector<Output> &depths, - DepthMinMax Output::*store) { + const typename Graph::vertex_descriptor src, + const vector<bool> &deadNodes, + vector<int> &dMin /* util */, + vector<int> &dMax /* util */, + vector<Output> &depths, + DepthMinMax Output::*store) { calcDepthFromSource(g, src, deadNodes, dMin, dMax); - - for (auto v : vertices_range(g)) { - u32 idx = g[v].index; - assert(idx < depths.size()); - Output &d = depths.at(idx); - d.*store = getDepths(idx, dMin, dMax); - } -} - + + for (auto v : vertices_range(g)) { + u32 idx = g[v].index; + assert(idx < depths.size()); + Output &d = depths.at(idx); + d.*store = getDepths(idx, dMin, dMax); + } +} + vector<NFAVertexDepth> calcDepths(const NGHolder &g) { - assert(hasCorrectlyNumberedVertices(g)); - const size_t numVertices = num_vertices(g); - + assert(hasCorrectlyNumberedVertices(g)); + const size_t numVertices = num_vertices(g); + vector<NFAVertexDepth> depths(numVertices); - vector<int> dMin; - vector<int> dMax; - - /* - * create a filtered graph for max depth calculations: all nodes/edges - * reachable from a loop need to be removed - */ + vector<int> dMin; + vector<int> dMax; + + /* + * create a filtered graph for max depth calculations: all nodes/edges + * reachable from a loop need to be removed + */ auto deadNodes = findLoopReachable(g, g.start); - - DEBUG_PRINTF("doing start\n"); + + DEBUG_PRINTF("doing start\n"); calcAndStoreDepth(g, g.start, deadNodes, dMin, dMax, depths, &NFAVertexDepth::fromStart); - DEBUG_PRINTF("doing startds\n"); + DEBUG_PRINTF("doing startds\n"); calcAndStoreDepth(g, g.startDs, deadNodes, dMin, dMax, depths, &NFAVertexDepth::fromStartDotStar); return depths; -} - +} + vector<NFAVertexRevDepth> calcRevDepths(const NGHolder &g) { - assert(hasCorrectlyNumberedVertices(g)); - const size_t numVertices = num_vertices(g); - + assert(hasCorrectlyNumberedVertices(g)); + const size_t numVertices = num_vertices(g); + vector<NFAVertexRevDepth> depths(numVertices); - vector<int> dMin; - vector<int> dMax; - - /* reverse the graph before walking it */ + vector<int> dMin; + vector<int> dMax; + + /* reverse the graph before walking it */ typedef reverse_graph<NGHolder, const NGHolder &> RevNFAGraph; const RevNFAGraph rg(g); - + assert(num_vertices(g) == num_vertices(rg)); - /* - * create a filtered graph for max depth calculations: all nodes/edges - * reachable from a loop need to be removed - */ + /* + * create a filtered graph for max depth calculations: all nodes/edges + * reachable from a loop need to be removed + */ auto deadNodes = findLoopReachable(rg, g.acceptEod); - - DEBUG_PRINTF("doing accept\n"); - calcAndStoreDepth<RevNFAGraph, NFAVertexRevDepth>( + + DEBUG_PRINTF("doing accept\n"); + calcAndStoreDepth<RevNFAGraph, NFAVertexRevDepth>( rg, g.accept, deadNodes, dMin, dMax, depths, - &NFAVertexRevDepth::toAccept); - DEBUG_PRINTF("doing accepteod\n"); - deadNodes[NODE_ACCEPT] = true; // Hide accept->acceptEod edge. - calcAndStoreDepth<RevNFAGraph, NFAVertexRevDepth>( + &NFAVertexRevDepth::toAccept); + DEBUG_PRINTF("doing accepteod\n"); + deadNodes[NODE_ACCEPT] = true; // Hide accept->acceptEod edge. + calcAndStoreDepth<RevNFAGraph, NFAVertexRevDepth>( rg, g.acceptEod, deadNodes, dMin, dMax, depths, - &NFAVertexRevDepth::toAcceptEod); + &NFAVertexRevDepth::toAcceptEod); return depths; -} - +} + vector<NFAVertexBidiDepth> calcBidiDepths(const NGHolder &g) { - assert(hasCorrectlyNumberedVertices(g)); - const size_t numVertices = num_vertices(g); - + assert(hasCorrectlyNumberedVertices(g)); + const size_t numVertices = num_vertices(g); + vector<NFAVertexBidiDepth> depths(numVertices); - vector<int> dMin; - vector<int> dMax; - - /* - * create a filtered graph for max depth calculations: all nodes/edges - * reachable from a loop need to be removed - */ + vector<int> dMin; + vector<int> dMax; + + /* + * create a filtered graph for max depth calculations: all nodes/edges + * reachable from a loop need to be removed + */ auto deadNodes = findLoopReachable(g, g.start); - - DEBUG_PRINTF("doing start\n"); + + DEBUG_PRINTF("doing start\n"); calcAndStoreDepth<NGHolder, NFAVertexBidiDepth>( g, g.start, deadNodes, dMin, dMax, depths, - &NFAVertexBidiDepth::fromStart); - DEBUG_PRINTF("doing startds\n"); + &NFAVertexBidiDepth::fromStart); + DEBUG_PRINTF("doing startds\n"); calcAndStoreDepth<NGHolder, NFAVertexBidiDepth>( g, g.startDs, deadNodes, dMin, dMax, depths, - &NFAVertexBidiDepth::fromStartDotStar); - - /* Now go backwards */ + &NFAVertexBidiDepth::fromStartDotStar); + + /* Now go backwards */ typedef reverse_graph<NGHolder, const NGHolder &> RevNFAGraph; const RevNFAGraph rg(g); deadNodes = findLoopReachable(rg, g.acceptEod); - - DEBUG_PRINTF("doing accept\n"); - calcAndStoreDepth<RevNFAGraph, NFAVertexBidiDepth>( + + DEBUG_PRINTF("doing accept\n"); + calcAndStoreDepth<RevNFAGraph, NFAVertexBidiDepth>( rg, g.accept, deadNodes, dMin, dMax, depths, - &NFAVertexBidiDepth::toAccept); - DEBUG_PRINTF("doing accepteod\n"); - deadNodes[NODE_ACCEPT] = true; // Hide accept->acceptEod edge. - calcAndStoreDepth<RevNFAGraph, NFAVertexBidiDepth>( + &NFAVertexBidiDepth::toAccept); + DEBUG_PRINTF("doing accepteod\n"); + deadNodes[NODE_ACCEPT] = true; // Hide accept->acceptEod edge. + calcAndStoreDepth<RevNFAGraph, NFAVertexBidiDepth>( rg, g.acceptEod, deadNodes, dMin, dMax, depths, - &NFAVertexBidiDepth::toAcceptEod); + &NFAVertexBidiDepth::toAcceptEod); return depths; -} - +} + vector<DepthMinMax> calcDepthsFrom(const NGHolder &g, const NFAVertex src) { - assert(hasCorrectlyNumberedVertices(g)); - const size_t numVertices = num_vertices(g); - + assert(hasCorrectlyNumberedVertices(g)); + const size_t numVertices = num_vertices(g); + auto deadNodes = findLoopReachable(g, g.start); - - vector<int> dMin, dMax; + + vector<int> dMin, dMax; calcDepthFromSource(g, src, deadNodes, dMin, dMax); - + vector<DepthMinMax> depths(numVertices); - - for (auto v : vertices_range(g)) { + + for (auto v : vertices_range(g)) { auto idx = g[v].index; - depths.at(idx) = getDepths(idx, dMin, dMax); - } + depths.at(idx) = getDepths(idx, dMin, dMax); + } return depths; -} - -} // namespace ue2 +} + +} // namespace ue2 |