vector<vector<int> > Scc(const Graph &g) { const int n = g.size(); vector<vector<int> > ret; Graph revg(n); for (int i = 0; i < n; i++) { for (Edges::const_iterator it = g[i].begin(); it != g[i].end(); it++) { revg[it->dest].push_back(Edge(it->dest, i, it->weight)); } } vector<int> st; vector<int> visit(n, 0); for (int i = 0; i < n; i++) { if (visit[i]) { continue; } SccDfs(g, i, visit, st); } visit = vector<int>(n, 0); for (int i = n - 1; i >= 0; i--) { int index = st[i]; if (visit[index]) { continue; } vector<int> nret; SccDfs(revg, index, visit, nret); ret.push_back(nret); } return ret; }
/** Remove any vertices that can't be reached by traversing the graph in * reverse from acceptEod. */ void pruneUnreachable(NGHolder &g) { deque<NFAVertex> dead; if (!hasGreaterInDegree(1, g.acceptEod, g) && !hasGreaterInDegree(0, g.accept, g) && edge(g.accept, g.acceptEod, g).second) { // Trivial case: there are no in-edges to our accepts (other than // accept->acceptEod), so all non-specials are unreachable. for (auto v : vertices_range(g)) { if (!is_special(v, g)) { dead.push_back(v); } } } else { // Walk a reverse graph from acceptEod with Boost's depth_first_visit // call. typedef reverse_graph<NFAGraph, NFAGraph&> RevNFAGraph; RevNFAGraph revg(g.g); map<NFAVertex, default_color_type> colours; depth_first_visit(revg, g.acceptEod, make_dfs_visitor(boost::null_visitor()), make_assoc_property_map(colours)); DEBUG_PRINTF("color map has %zu entries after DFV\n", colours.size()); // All non-special vertices that aren't in the colour map (because they // weren't reached) can be removed. for (auto v : vertices_range(revg)) { if (is_special(v, revg)) { continue; } if (!contains(colours, v)) { dead.push_back(v); } } } if (dead.empty()) { DEBUG_PRINTF("no unreachable vertices\n"); return; } remove_vertices(dead, g, false); DEBUG_PRINTF("removed %zu unreachable vertices\n", dead.size()); }
flat_set<NFAVertex> execute_graph(const NGHolder &running_g, const NGHolder &input_dag, const flat_set<NFAVertex> &input_start_states, const flat_set<NFAVertex> &initial_states) { DEBUG_PRINTF("g has %zu vertices, input_dag has %zu vertices\n", num_vertices(running_g), num_vertices(input_dag)); assert(hasCorrectlyNumberedVertices(running_g)); assert(in_degree(input_dag.acceptEod, input_dag) == 1); map<NFAVertex, boost::default_color_type> colours; /* could just a topo order, but really it is time to pull a slightly bigger * gun: DFS */ RevNFAGraph revg(input_dag.g); map<NFAVertex, dynamic_bitset<> > dfs_states; auto info = makeInfoTable(running_g); auto input_fs = makeStateBitset(running_g, initial_states); for (auto v : input_start_states) { dfs_states[v] = input_fs; } depth_first_visit(revg, input_dag.accept, eg_visitor(running_g, info, input_dag, dfs_states), make_assoc_property_map(colours)); auto states = getVertices(dfs_states[input_dag.accept], info); #ifdef DEBUG DEBUG_PRINTF(" output rstates:"); for (const auto &v : states) { printf(" %u", running_g[v].index); } printf("\n"); #endif return states; }