BasePath* YenTopKShortestPathsAlg::next() { //1. Prepare for removing vertices and arcs BasePath* cur_path = *(m_quPathCandidates.begin());//m_quPathCandidates.top(); //m_quPathCandidates.pop(); m_quPathCandidates.erase(m_quPathCandidates.begin()); m_vResultList.push_back(cur_path); size_t count = m_vResultList.size(); BaseVertex* cur_derivation_pt = m_mpDerivationVertexIndex.find(cur_path)->second; std::vector<BaseVertex*> sub_path_of_derivation_pt; cur_path->SubPath(sub_path_of_derivation_pt, cur_derivation_pt); size_t sub_path_length = sub_path_of_derivation_pt.size(); //2. Remove the vertices and arcs in the graph for (size_t ii=0; ii<count-1; ++ii) { BasePath* cur_result_path = m_vResultList.at(ii); std::vector<BaseVertex*> cur_result_sub_path_of_derivation_pt; if (!cur_result_path->SubPath(cur_result_sub_path_of_derivation_pt, cur_derivation_pt)) continue; if (sub_path_length != cur_result_sub_path_of_derivation_pt.size()) continue; bool is_equal = true; for (size_t i=0; i<sub_path_length; ++i) { if (sub_path_of_derivation_pt.at(i) != cur_result_sub_path_of_derivation_pt.at(i)) { is_equal = false; break; } } if (!is_equal) continue; // BaseVertex* cur_succ_vertex = cur_result_path->GetVertex(sub_path_length+1); m_pGraph->remove_edge(std::make_pair(cur_derivation_pt->getID(), cur_succ_vertex->getID())); } //2.1 remove vertices and edges along the current result int path_length = cur_path->length(); for(int i=0; i<path_length-1; ++i) { m_pGraph->remove_vertex(cur_path->GetVertex(i)->getID()); m_pGraph->remove_edge(std::make_pair( cur_path->GetVertex(i)->getID(), cur_path->GetVertex(i+1)->getID())); } //3. Calculate the shortest tree rooted at target vertex in the graph DijkstraShortestPathAlg reverse_tree(m_pGraph); reverse_tree.get_shortest_path_flower(m_pTargetVertex); //4. Recover the deleted vertices and update the cost and identify the new candidates results bool is_done = false; for(int i=path_length-2; i>=0 && !is_done; --i) { //4.1 Get the vertex to be recovered BaseVertex* cur_recover_vertex = cur_path->GetVertex(i); m_pGraph->recover_removed_vertex(cur_recover_vertex->getID()); //4.2 Check if we should stop continuing in the next iteration if (cur_recover_vertex->getID() == cur_derivation_pt->getID()) { is_done = true; } //4.3 Calculate cost using forward star form BasePath* sub_path = reverse_tree.update_cost_forward(cur_recover_vertex); //4.4 Get one candidate result if possible if (sub_path != NULL) { ++m_nGeneratedPathNum; //4.4.1 Get the prefix from the concerned path double cost = 0; reverse_tree.correct_cost_backward(cur_recover_vertex); std::vector<BaseVertex*> pre_path_list; for (int j=0; j<path_length; ++j) { BaseVertex* cur_vertex = cur_path->GetVertex(j); if (cur_vertex->getID() == cur_recover_vertex->getID()) { //j = path_length; break; }else { cost += m_pGraph->get_original_edge_weight( cur_path->GetVertex(j), cur_path->GetVertex(1+j)); pre_path_list.push_back(cur_vertex); } } // for (size_t j=0; j<sub_path->length(); ++j) { pre_path_list.push_back(sub_path->GetVertex(j)); } //4.4.2 Compose a candidate sub_path = new Path(pre_path_list, cost+sub_path->Weight()); //4.4.3 Put it in the candidate pool if new if (m_mpDerivationVertexIndex.find(sub_path) == m_mpDerivationVertexIndex.end()) { m_quPathCandidates.insert(sub_path); m_mpDerivationVertexIndex[sub_path] = cur_recover_vertex; } } //4.5 Restore the edge BaseVertex* succ_vertex = cur_path->GetVertex(i+1); m_pGraph->recover_removed_edge(std::make_pair(cur_recover_vertex->getID(), succ_vertex->getID())); //4.6 Update cost if necessary double cost_1 = m_pGraph->get_edge_weight(cur_recover_vertex, succ_vertex) + reverse_tree.get_start_distance_at(succ_vertex); if (reverse_tree.get_start_distance_at(cur_recover_vertex) > cost_1) { reverse_tree.set_start_distance_at(cur_recover_vertex, cost_1); reverse_tree.set_predecessor_vertex(cur_recover_vertex, succ_vertex); reverse_tree.correct_cost_backward(cur_recover_vertex); } } //5. Restore everything m_pGraph->recover_removed_edges(); m_pGraph->recover_removed_vertices(); return cur_path; }
/* Check */ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <parse_tree.h> #include <aurochs.h> static unsigned char *load_file(char *name, size_t *size)/*{{{*/ { size_t m; struct stat st; unsigned char *data; FILE *f; unsigned char *retval; retval = 0; if(!stat(name, &st)) { m = st.st_size; *size = m; data = malloc(m); if(data) { f = fopen(name, "rb"); if(f) { if(1 == fread(data, m, 1, f)) { retval = data; data = 0; } fclose(f); } if(data) free(data); } } return retval; }/*}}}*/ int main(int argc, char **argv) { unsigned char *peg_data; char *peg_fn; size_t peg_data_size; nog_program_t *pg; packer_t pk; staloc_t *st; int rc; rc = 0; argv ++; argc --; if(!argc) { printf("No PEG data\n"); exit(EXIT_FAILURE); } peg_fn = *(argv ++); argc --; printf("Loading peg_data from file %s\n", peg_fn); peg_data = load_file(peg_fn, &peg_data_size); if(!peg_data) { printf("Can't load peg data.\n"); exit(EXIT_FAILURE); } /* Create a stack allocator */ st = staloc_create(&alloc_stdlib); if(!st) { printf("Can't create stack allocator.\n"); exit(EXIT_FAILURE); } if(pack_init_from_string(&pk, peg_data, peg_data_size)) { printf("peg_data[0] = %d\n", peg_data[0]); pg = nog_unpack_program(&st->s_alloc, &pk); printf("Unpacked to %p\n", pg); if(pg) { peg_context_t *cx; size_t m; int i; int error_pos; char *fn; unsigned char *buf; int rc; rc = 0; for(i = 0; i < argc; i ++) { fn = argv[i]; peg_builder_t pb; staloc_t *s2; s2 = staloc_create(&alloc_stdlib); buf = load_file(fn, &m); printf("Loaded file %s to %p\n", fn, buf); if(buf) { ptree_init(&pb, &s2->s_alloc); cx = peg_create_context(&alloc_stdlib, pg, &pb, &s2->s_alloc, buf, m); printf("Created context %p\n", cx); if(cx) { tree tr; if(nog_execute(cx, pg, &tr)) { printf("Parsed as %p.\n", tr); ptree_dump_tree(cx->cx_builder_info, stdout, buf, tr, 0); } else { printf("Doesn't parse.\n"); error_pos = nog_error_position(cx, pg); printf("Error at %d\n", error_pos); } peg_delete_context(cx); } } staloc_dispose(s2); free(buf); } #if 0 i = foobar_parse_start(cx, - m); if(getenv("DUMP_CONTEXT")) dump_context(stdout, cx); if(!i) { printf("%05d RESULT OK\n", count); tree *tr0; if(getenv("DUMP_TREE")) { tr0 = create_node("Root"); (void) foobar_build_start(cx, &tr0->t_element.t_node, -m); reverse_tree(tr0); dump_tree(stdout, cx->cx_input, tr0, 0); } } else { error_pos = error_position(cx); if(i > 0) { printf("%05d RESULT NOPREFIX; ERROR AT %d\n", count, error_pos); rc = 1; } else { printf("%05d RESULT PREFIX %d; ERROR AT %d\n", count, m + i, error_pos); } } fflush(stdout); delete_context(cx); fclose(f); } #endif /* nog_free_program(&st->s_alloc, pg); */ staloc_dispose(st); } }