mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
ng_repeat: use undirected_graph
This commit is contained in:
parent
c7c90c7ab7
commit
3c776b25c3
@ -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 */
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user