/** * 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; }
/** * Takes a linkage and returns: * . for each link, the domain structure of that link * . a list of the violation strings * NB: linkage->link[i]->l=-1 means that this connector is to be ignored. */ PP_node *do_post_process(Postprocessor *pp, Linkage sublinkage, bool is_long) { const char *msg; if (pp == NULL) return NULL; // XXX wtf .. why is this not leaking memory ? pp->pp_data.links_to_ignore = NULL; pp->pp_data.num_words = sublinkage->num_words; /* Grab more memory if needed */ if (pp->vlength <= pp->pp_data.num_words) { size_t newsz; pp->vlength += pp->pp_data.num_words; newsz = pp->vlength * sizeof(bool); pp->visited = (bool *) realloc(pp->visited, newsz); } clear_visited(pp); /* In the name of responsible memory management, we retain a copy of the * returned data structure pp_node as a field in pp, so that we can clear * it out after every call, without relying on the user to do so. */ clear_pp_node(pp); /* For long sentences, we can save some time by pruning the rules * which can't possibly be used during postprocessing the linkages * of this sentence. For short sentences, this is pointless. */ if (is_long && pp->q_pruned_rules == false) { prune_irrelevant_rules(pp); } pp->q_pruned_rules = true; switch (internal_process(pp, sublinkage, &msg)) { case -1: /* some global test failed even before we had to build the domains */ pp->n_global_rules_firing++; pp->pp_node->violation = msg; report_pp_stats(pp); return pp->pp_node; break; case 1: /* one of the "normal" post processing tests failed */ pp->n_local_rules_firing++; pp->pp_node->violation = msg; break; case 0: /* This linkage is legal according to the post processing rules */ pp->pp_node->violation = NULL; break; } report_pp_stats(pp); build_type_array(pp); return pp->pp_node; }
void MemoryDump::clear_visited(Node &node) { if (node.visited < 0) return; node.visited = -1; for (auto c : node.children) { clear_visited(*c.node); } }
double MemoryDump::update_subtree_size() { total_size = 0; for (auto node : top_nodes) { std::set<uintptr_t> path; pre_update_subtree_size(*node.node, path); clear_visited(*node.node); } for (auto node : top_nodes) { std::set<uintptr_t> path; total_size += update_subtree_size(*node.node, path); } clear_visited(); set_critical(top_nodes); clear_visited(); return total_size; }
int main() { // add edges add_edge(0, 1); add_edge(0, 2); add_edge(1, 3); add_edge(2, 4); add_edge(4, 5); add_edge(3, 5); add_edge(3, 2); add_edge(5, 6); add_edge(5, 7); printf(solve_maze(ENTRY) ? "There's a solution.\n" : "No solution :(\n"); // now let's make it fail remove_edge(5, 7); clear_visited(); printf(solve_maze(ENTRY) ? "There's a solution.\n" : "No solution :(\n"); return 0; }
static void build_domains(Postprocessor *pp, Linkage sublinkage) { size_t link, i, d; const char *s; PP_data *pp_data = &pp->pp_data; pp_data->N_domains = 0; for (link = 0; link<sublinkage->num_links; link++) { assert (sublinkage->link_array[link].lw != SIZE_MAX); if (NULL == sublinkage->link_array[link].link_name) continue; s = sublinkage->link_array[link].link_name; if (pp_linkset_match(pp->knowledge->ignore_these_links, s)) continue; if (pp_linkset_match(pp->knowledge->domain_starter_links, s)) { setup_domain_array(pp, s, link); if (pp_linkset_match(pp->knowledge->domain_contains_links, s)) add_link_to_domain(pp_data, link); clear_visited(pp_data); depth_first_search(pp, sublinkage, sublinkage->link_array[link].rw, sublinkage->link_array[link].lw, link); } else if (pp_linkset_match(pp->knowledge->urfl_domain_starter_links, s)) { setup_domain_array(pp, s, link); /* always add the starter link to its urfl domain */ add_link_to_domain(pp_data, link); clear_visited(pp_data); bad_depth_first_search(pp, sublinkage,sublinkage->link_array[link].rw, sublinkage->link_array[link].lw, link); } else if (pp_linkset_match(pp->knowledge->urfl_only_domain_starter_links, s)) { setup_domain_array(pp, s, link); /* do not add the starter link to its urfl_only domain */ clear_visited(pp_data); d_depth_first_search(pp, sublinkage, sublinkage->link_array[link].lw, sublinkage->link_array[link].lw, sublinkage->link_array[link].rw, link); } else if (pp_linkset_match(pp->knowledge->left_domain_starter_links, s)) { setup_domain_array(pp, s, link); /* do not add the starter link to a left domain */ clear_visited(pp_data); left_depth_first_search(pp, sublinkage, sublinkage->link_array[link].lw, sublinkage->link_array[link].rw, link); } } /* sort the domains by size */ qsort((void *) pp_data->domain_array, pp_data->N_domains, sizeof(Domain), (int (*)(const void *, const void *)) domain_compare); /* sanity check: all links in all domains have a legal domain name */ for (d = 0; d < pp_data->N_domains; d++) { i = find_domain_name(pp, pp_data->domain_array[d].string); if (i == SIZE_MAX) prt_error("Error: post_process(): Need an entry for %s in LINK_TYPE_TABLE", pp_data->domain_array[d].string); pp_data->domain_array[d].type = i; } }
bool MemoryDump::write_output(const cmd_opt &opt) { try { std::ofstream ofile(opt.ofile, std::ofstream::trunc); min_size = total_size * opt.threshold; if (exporter == nullptr || export_type != opt.export_type) { delete exporter; export_type = opt.export_type; switch (export_type) { case EXPORT_DOT: exporter = new ExporterDot(total_size); break; case EXPORT_GML: exporter = new ExporterGML(total_size); break; case EXPORT_GRAPHML: exporter = new ExporterGraphML(); break; default: exporter = new ExporterDot(total_size); export_type = EXPORT_DOT; } } else { switch (export_type) { case EXPORT_DOT: case EXPORT_GML: exporter->set_total_size(total_size); break; default: break; } } exporter->write_preamble(ofile); std::vector<Node*> selected_nodes; if (opt.nodes.empty() && opt.labels.empty()) { for (const auto &c : top_nodes) { selected_nodes.push_back(c.node); } } else { /* find the node pointed by opt.node */ for (const auto &path : opt.nodes) { auto node = find_node(path.node); if (node == nullptr) { std::cout << "No node found for path " << path.literal << std::endl; continue; } selected_nodes.push_back(node); } for (const auto &label : opt.labels) { auto node = nodes.find(label); if (node != nodes.end()) { std::cout << "Found node by label " << std::hex << label << std::dec << std::endl; selected_nodes.push_back(&node->second); } else { std::cout << "Label " << std::hex << label << std::dec << " was not found\n"; } } } std::set<uintptr_t> declared_nodes; for (auto & node : selected_nodes) { write_node(*node, ofile, opt); declared_nodes.insert(node->label); draw_tree(*node, ofile, opt, declared_nodes); } for (auto & node : selected_nodes) { clear_visited(*node); } exporter->write_appendix(ofile); } catch (...) { std::cout << "Unexpected error hanppend while writing output" << std::endl; } return true; }
void MemoryDump::clear_visited() { for (const auto &node : top_nodes) { clear_visited(*node.node); } }
ACTION unmark( Object **opp ) { clear_visited( *opp ); return CONTINUE; }