ng_calc_components: check tail shell too

This commit is contained in:
Justin Viiret 2017-06-07 14:15:10 +10:00 committed by Matthew Barr
parent f6adc4f464
commit 63973175ed

View File

@ -220,37 +220,51 @@ vector<NFAEdge> findShellEdges(const NGHolder &g,
return shell_edges; return shell_edges;
} }
/** template<typename GetAdjRange>
* True if all edges out of vertices in the head shell lead to at most a single bool shellHasOnePath(const NGHolder &g, const flat_set<NFAVertex> &shell,
* outside vertex. GetAdjRange adj_range_func) {
*/ if (shell.empty()) {
static DEBUG_PRINTF("no shell\n");
bool shellHasOnePath(const NGHolder &g,
const flat_set<NFAVertex> &head_shell) {
if (head_shell.empty()) {
DEBUG_PRINTF("no head shell\n");
return false; return false;
} }
NFAVertex succ = NGHolder::null_vertex(); NFAVertex exit_vertex = NGHolder::null_vertex();
for (auto u : head_shell) { for (auto u : shell) {
for (auto v : adjacent_vertices_range(u, g)) { for (auto v : adj_range_func(u, g)) {
if (contains(head_shell, v)) { if (contains(shell, v)) {
continue; continue;
} }
if (!succ) { if (!exit_vertex) {
succ = v; exit_vertex = v;
continue; continue;
} }
if (succ == v) { if (exit_vertex == v) {
continue; continue;
} }
return false; return false;
} }
} }
return true;
}
/**
* True if all edges out of vertices in the head shell lead to at most a single
* outside vertex, or the inverse for the tail shell.
*/
static
bool shellHasOnePath(const NGHolder &g, const flat_set<NFAVertex> &head_shell,
const flat_set<NFAVertex> &tail_shell) {
if (shellHasOnePath(g, head_shell, adjacent_vertices_range<NGHolder>)) {
DEBUG_PRINTF("head shell has only one path through it\n"); DEBUG_PRINTF("head shell has only one path through it\n");
return true; return true;
} }
if (shellHasOnePath(g, tail_shell, inv_adjacent_vertices_range<NGHolder>)) {
DEBUG_PRINTF("tail shell has only one path into it\n");
return true;
}
return false;
}
/** /**
* Common code called by calc- and recalc- below. Splits the given holder into * Common code called by calc- and recalc- below. Splits the given holder into
@ -288,9 +302,9 @@ void splitIntoComponents(unique_ptr<NGHolder> g,
DEBUG_PRINTF("%zu vertices in head, %zu in tail, %zu shell edges\n", DEBUG_PRINTF("%zu vertices in head, %zu in tail, %zu shell edges\n",
head_shell.size(), tail_shell.size(), shell_edges.size()); head_shell.size(), tail_shell.size(), shell_edges.size());
// If there's only one way out of the head shell and no shell edges, we // If there are no shell edges and only one path out of the head shell or
// aren't going to find more than one component. // into the tail shell, we aren't going to find more than one component.
if (shell_edges.empty() && shellHasOnePath(*g, head_shell)) { if (shell_edges.empty() && shellHasOnePath(*g, head_shell, tail_shell)) {
DEBUG_PRINTF("single component\n"); DEBUG_PRINTF("single component\n");
comps.push_back(std::move(g)); comps.push_back(std::move(g));
return; return;