ng_repeat: use undirected_graph

This commit is contained in:
Justin Viiret 2017-12-14 13:49:45 +11:00 committed by Chang, Harry
parent c7c90c7ab7
commit 3c776b25c3

View File

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@ -48,6 +48,7 @@
#include "util/dump_charclass.h" #include "util/dump_charclass.h"
#include "util/graph_range.h" #include "util/graph_range.h"
#include "util/graph_small_color_map.h" #include "util/graph_small_color_map.h"
#include "util/graph_undirected.h"
#include "util/report_manager.h" #include "util/report_manager.h"
#include "util/unordered.h" #include "util/unordered.h"
@ -73,40 +74,41 @@ namespace ue2 {
namespace { 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<class Graph> template<class Graph>
struct ReachFilter { struct ReachFilter {
ReachFilter() {} ReachFilter() = default;
explicit ReachFilter(const Graph *g_in) : g(g_in) {} explicit ReachFilter(const Graph *g_in) : g(g_in) {}
// Convenience typedefs. // Convenience typedefs.
typedef typename boost::graph_traits<Graph> Traits; using Traits = typename boost::graph_traits<Graph>;
typedef typename Traits::vertex_descriptor VertexDescriptor; using VertexDescriptor = typename Traits::vertex_descriptor;
typedef typename Traits::edge_descriptor EdgeDescriptor; 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 { bool operator()(const EdgeDescriptor &e) const {
assert(g); 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. // 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_u = (*g)[u].char_reach;
const CharReach &cr_v = (*g)[v].char_reach; const CharReach &cr_v = (*g)[v].char_reach;
return cr_u == cr_v; return cr_u == cr_v;
} }
const Graph *g = nullptr; const Graph *g = nullptr;
}; };
typedef boost::filtered_graph<NGHolder, ReachFilter<NGHolder>> RepeatGraph; using RepeatGraph = boost::filtered_graph<NGHolder, ReachFilter<NGHolder>,
ReachFilter<NGHolder>>;
struct ReachSubgraph { struct ReachSubgraph {
vector<NFAVertex> vertices; vector<NFAVertex> vertices;
@ -300,10 +302,9 @@ void splitSubgraph(const NGHolder &g, const deque<NFAVertex> &verts,
unordered_map<NFAVertex, NFAVertex> verts_map; // in g -> in verts_g unordered_map<NFAVertex, NFAVertex> verts_map; // in g -> in verts_g
fillHolder(&verts_g, g, verts, &verts_map); fillHolder(&verts_g, g, verts, &verts_map);
unordered_map<NFAVertex, NFAUndirectedVertex> old2new; const auto ug = make_undirected_graph(verts_g);
auto ug = createUnGraph(verts_g, true, true, old2new);
unordered_map<NFAUndirectedVertex, u32> repeatMap; unordered_map<NFAVertex, u32> repeatMap;
size_t num = connected_components(ug, make_assoc_property_map(repeatMap)); size_t num = connected_components(ug, make_assoc_property_map(repeatMap));
DEBUG_PRINTF("found %zu connected repeat components\n", num); DEBUG_PRINTF("found %zu connected repeat components\n", num);
@ -312,7 +313,8 @@ void splitSubgraph(const NGHolder &g, const deque<NFAVertex> &verts,
vector<ReachSubgraph> rs(num); vector<ReachSubgraph> rs(num);
for (auto v : verts) { 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); auto rit = repeatMap.find(vu);
if (rit == repeatMap.end()) { if (rit == repeatMap.end()) {
continue; /* not part of a repeat */ continue; /* not part of a repeat */
@ -323,8 +325,14 @@ void splitSubgraph(const NGHolder &g, const deque<NFAVertex> &verts,
} }
for (const auto &rsi : rs) { 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()); DEBUG_PRINTF("repeat with %zu vertices\n", rsi.vertices.size());
assert(!rsi.vertices.empty());
if (rsi.vertices.size() >= minNumVertices) { if (rsi.vertices.size() >= minNumVertices) {
DEBUG_PRINTF("enqueuing\n"); DEBUG_PRINTF("enqueuing\n");
q.push(rsi); q.push(rsi);
@ -1023,17 +1031,16 @@ static
void buildReachSubgraphs(const NGHolder &g, vector<ReachSubgraph> &rs, void buildReachSubgraphs(const NGHolder &g, vector<ReachSubgraph> &rs,
const u32 minNumVertices) { const u32 minNumVertices) {
const ReachFilter<NGHolder> fil(&g); const ReachFilter<NGHolder> fil(&g);
const RepeatGraph rg(g, fil); const RepeatGraph rg(g, fil, fil);
if (!isCompBigEnough(rg, minNumVertices)) { if (!isCompBigEnough(rg, minNumVertices)) {
DEBUG_PRINTF("component not big enough, bailing\n"); DEBUG_PRINTF("component not big enough, bailing\n");
return; return;
} }
unordered_map<RepeatGraph::vertex_descriptor, NFAUndirectedVertex> old2new; const auto ug = make_undirected_graph(rg);
auto ug = createUnGraph(rg, true, true, old2new);
unordered_map<NFAUndirectedVertex, u32> repeatMap; unordered_map<NFAVertex, u32> repeatMap;
unsigned int num; unsigned int num;
num = connected_components(ug, make_assoc_property_map(repeatMap)); num = connected_components(ug, make_assoc_property_map(repeatMap));
@ -1045,8 +1052,7 @@ void buildReachSubgraphs(const NGHolder &g, vector<ReachSubgraph> &rs,
rs.resize(num); rs.resize(num);
for (auto v : topoOrder) { for (auto v : topoOrder) {
NFAUndirectedVertex vu = old2new[v]; auto rit = repeatMap.find(v);
auto rit = repeatMap.find(vu);
if (rit == repeatMap.end()) { if (rit == repeatMap.end()) {
continue; /* not part of a repeat */ continue; /* not part of a repeat */
} }