/** * Returns true if the linkage is connected when ignoring the links * whose names are in the given list of link names. * Actually, what it does is this: it returns false if the connectivity * of the subgraph reachable from word 0 changes as a result of deleting * these links. */ static bool apply_must_form_a_cycle(PP_data *pp_data, Linkage sublinkage, pp_rule *rule) { List_o_links *lol; size_t w; for (w = 0; w < pp_data->num_words; w++) { for (lol = pp_data->word_links[w]; lol != NULL; lol = lol->next) { if (w > lol->word) continue; /* only consider each edge once */ if (!pp_linkset_match(rule->link_set, sublinkage->link_array[lol->link].link_name)) continue; clear_visited(pp_data); reachable_without_dfs(pp_data, sublinkage, w, lol->word, w); if (!pp_data->visited[lol->word]) return false; } } for (lol = pp_data->links_to_ignore; lol != NULL; lol = lol->next) { w = sublinkage->link_array[lol->link].lw; /* (w, lol->word) are the left and right ends of the edge we're considering */ if (!pp_linkset_match(rule->link_set, sublinkage->link_array[lol->link].link_name)) continue; clear_visited(pp_data); reachable_without_dfs(pp_data, sublinkage, w, lol->word, w); assert(lol->word < pp_data->num_words, "Bad word index"); if (!pp_data->visited[lol->word]) return false; } return true; }
static int apply_must_form_a_cycle(Postprocessor *pp,Sublinkage *sublinkage,pp_rule *rule) { /* Returns TRUE if the linkage is connected when ignoring the links whose names are in the given list of link names. Actually, what it does is this: it returns FALSE if the connectivity of the subgraph reachable from word 0 changes as a result of deleting these links. */ List_o_links *lol; int w; for (w=0; w<pp->pp_data.length; w++) { for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) { if (w > lol->word) continue; /* only consider each edge once */ if (!pp_linkset_match(rule->link_set, sublinkage->link[lol->link]->name)) continue; memset(pp->visited, 0, pp->pp_data.length*(sizeof pp->visited[0])); reachable_without_dfs(pp, sublinkage, w, lol->word, w); if (!pp->visited[lol->word]) return FALSE; } } for (lol = pp->pp_data.links_to_ignore; lol != NULL; lol = lol->next) { w = sublinkage->link[lol->link]->l; /* (w, lol->word) are the left and right ends of the edge we're considering */ if (!pp_linkset_match(rule->link_set, sublinkage->link[lol->link]->name)) continue; memset(pp->visited, 0, pp->pp_data.length*(sizeof pp->visited[0])); reachable_without_dfs(pp, sublinkage, w, lol->word, w); if (!pp->visited[lol->word]) return FALSE; } return TRUE; }
static void reachable_without_dfs(Postprocessor *pp, Sublinkage *sublinkage, int a, int b, int w) { /* This is a depth first search of words reachable from w, excluding any direct edge between word a and word b. */ List_o_links *lol; pp->visited[w] = TRUE; for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) { if (!pp->visited[lol->word] && !(w == a && lol->word == b) && ! (w == b && lol->word == a)) { reachable_without_dfs(pp, sublinkage, a, b, lol->word); } } }
/** * For each link in the linkage that is in the must_form_a_cycle list, * we want to make sure that that link is in a cycle. We do this * simply by deleting the link, then seeing if the end points of that * link are still connected. */ static void reachable_without_dfs(PP_data *pp_data, Linkage sublinkage, size_t a, size_t b, size_t w) { /* This is a depth first search of words reachable from w, excluding * any direct edge between word a and word b. */ List_o_links *lol; assert(w < pp_data->num_words, "Bad word index"); pp_data->visited[w] = true; for (lol = pp_data->word_links[w]; lol != NULL; lol = lol->next) { assert(lol->word < pp_data->num_words, "Bad word index"); if (!pp_data->visited[lol->word] && !(w == a && lol->word == b) && !(w == b && lol->word == a)) { reachable_without_dfs(pp_data, sublinkage, a, b, lol->word); } } }