From 3c776b25c3766a3154c7c5e62b3bf0c82e6a52c2 Mon Sep 17 00:00:00 2001 From: Justin Viiret Date: Thu, 14 Dec 2017 13:49:45 +1100 Subject: [PATCH] ng_repeat: use undirected_graph --- src/nfagraph/ng_repeat.cpp | 64 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/nfagraph/ng_repeat.cpp b/src/nfagraph/ng_repeat.cpp index 96c553de..048ee43f 100644 --- a/src/nfagraph/ng_repeat.cpp +++ b/src/nfagraph/ng_repeat.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, Intel Corporation + * Copyright (c) 2015-2018, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -48,6 +48,7 @@ #include "util/dump_charclass.h" #include "util/graph_range.h" #include "util/graph_small_color_map.h" +#include "util/graph_undirected.h" #include "util/report_manager.h" #include "util/unordered.h" @@ -73,40 +74,41 @@ namespace ue2 { namespace { -/** \brief Filter that retains only edges between vertices with the same - * reachability. */ +/** + * \brief Filter that retains only edges between vertices with the same + * reachability. Special vertices are dropped. + */ template struct ReachFilter { - ReachFilter() {} + ReachFilter() = default; explicit ReachFilter(const Graph *g_in) : g(g_in) {} // Convenience typedefs. - typedef typename boost::graph_traits Traits; - typedef typename Traits::vertex_descriptor VertexDescriptor; - typedef typename Traits::edge_descriptor EdgeDescriptor; + using Traits = typename boost::graph_traits; + using VertexDescriptor = typename Traits::vertex_descriptor; + using EdgeDescriptor = typename Traits::edge_descriptor; + + bool operator()(const VertexDescriptor &v) const { + assert(g); + // Disallow special vertices, as otherwise we will try to remove them + // later. + return !is_special(v, *g); + } bool operator()(const EdgeDescriptor &e) const { assert(g); - - VertexDescriptor u = source(e, *g), v = target(e, *g); - - // Disallow special vertices, as otherwise we will try to remove them - // later. - if (is_special(u, *g) || is_special(v, *g)) { - return false; - } - // Vertices must have the same reach. + auto u = source(e, *g), v = target(e, *g); const CharReach &cr_u = (*g)[u].char_reach; const CharReach &cr_v = (*g)[v].char_reach; - return cr_u == cr_v; } const Graph *g = nullptr; }; -typedef boost::filtered_graph> RepeatGraph; +using RepeatGraph = boost::filtered_graph, + ReachFilter>; struct ReachSubgraph { vector vertices; @@ -300,10 +302,9 @@ void splitSubgraph(const NGHolder &g, const deque &verts, unordered_map verts_map; // in g -> in verts_g fillHolder(&verts_g, g, verts, &verts_map); - unordered_map old2new; - auto ug = createUnGraph(verts_g, true, true, old2new); + const auto ug = make_undirected_graph(verts_g); - unordered_map repeatMap; + unordered_map repeatMap; size_t num = connected_components(ug, make_assoc_property_map(repeatMap)); DEBUG_PRINTF("found %zu connected repeat components\n", num); @@ -312,7 +313,8 @@ void splitSubgraph(const NGHolder &g, const deque &verts, vector rs(num); for (auto v : verts) { - NFAUndirectedVertex vu = old2new.at(verts_map.at(v)); + assert(!is_special(v, g)); + auto vu = verts_map.at(v); auto rit = repeatMap.find(vu); if (rit == repeatMap.end()) { continue; /* not part of a repeat */ @@ -323,8 +325,14 @@ void splitSubgraph(const NGHolder &g, const deque &verts, } for (const auto &rsi : rs) { + if (rsi.vertices.empty()) { + // Empty elements can happen when connected_components finds a + // subgraph consisting entirely of specials (which aren't added to + // ReachSubgraph in the loop above). There's nothing we can do with + // these, so we skip them. + continue; + } DEBUG_PRINTF("repeat with %zu vertices\n", rsi.vertices.size()); - assert(!rsi.vertices.empty()); if (rsi.vertices.size() >= minNumVertices) { DEBUG_PRINTF("enqueuing\n"); q.push(rsi); @@ -1023,17 +1031,16 @@ static void buildReachSubgraphs(const NGHolder &g, vector &rs, const u32 minNumVertices) { const ReachFilter fil(&g); - const RepeatGraph rg(g, fil); + const RepeatGraph rg(g, fil, fil); if (!isCompBigEnough(rg, minNumVertices)) { DEBUG_PRINTF("component not big enough, bailing\n"); return; } - unordered_map old2new; - auto ug = createUnGraph(rg, true, true, old2new); + const auto ug = make_undirected_graph(rg); - unordered_map repeatMap; + unordered_map repeatMap; unsigned int num; num = connected_components(ug, make_assoc_property_map(repeatMap)); @@ -1045,8 +1052,7 @@ void buildReachSubgraphs(const NGHolder &g, vector &rs, rs.resize(num); for (auto v : topoOrder) { - NFAUndirectedVertex vu = old2new[v]; - auto rit = repeatMap.find(vu); + auto rit = repeatMap.find(v); if (rit == repeatMap.end()) { continue; /* not part of a repeat */ }