void Graph::extendPath(std::vector<int> &path, int sink, int est_dist, bool rev = 0) const{ bool tarfound = 0; while (true) { std::vector<int> next; if (rev) { next = getInEdges(path.back()); } else { next = getOutEdges(path.back()); } int good_next = -2; for (int i = 0; i < next.size(); ++i) { if (std::find(path.begin(), path.end(), next[i]) != path.end()) { return; } if (next[i] == sink || getSizeOfNode(next[i]) - (k_ - 1) < 2 * est_dist) { if (good_next > -2) { good_next = -1; } else { good_next = i; } } } if (good_next > -1) { path.push_back(next[good_next]); if (!tarfound && next[good_next] == sink) { tarfound = 1; } } else { return; } } }
int reachStatus(NFA nfa, int status_index, wchar_t c) { int i, e_index; assert(nfa); assert(status_index>=0 && status_index<Array_length(nfa->statusArray)); Status currStatus; Array_T outEdges; Edge e; currStatus = Array_get(nfa->statusArray, status_index); outEdges = getOutEdges(currStatus); if (!outEdges) return -1; for (i=0; i<Array_length(outEdges); i++) { e_index = *(int*)Array_get(outEdges, i); e = Array_get(nfa->edgeArray, e_index); if (crossEdge(e, c)) { return getStatusID(gettoStatus(e)); } } return -1; }
static void DFS(Status fromS, NFA nfa, Array_T closure, int inverse[], int color[], int set) { int i, index, from, to; Edge e; Status toS; from = getStatusID(fromS); color[from] = 1; inverse[from] = set; Array_append(closure, &from); Array_T edgeArray = getEdgeArray(nfa); Array_T outEdges_indice = getOutEdges(fromS); if (!outEdges_indice) return; for (i=0; i<Array_length(outEdges_indice); i++) { index = *(int*)Array_get(outEdges_indice, i); e = (Edge)Array_get(edgeArray, index); if (isEpsilon(e)) { toS = gettoStatus(e); to = getStatusID(toS); if (color[to] == 0) DFS(toS, nfa, closure, inverse, color, set); } } }
/** * @brief Returns all vertices, that are adjacent (connected) to *vertex* * */ std::vector<Vertex> getAdjacentVertices(const Vertex vertex){ std::vector<Vertex> adjacentVertices; for(std::pair<Vertex, Edge> e: getOutEdges(vertex)){ adjacentVertices.push_back(e.first); } return adjacentVertices; }
std::vector<DirectedFlowGraph::DirectedFlowEdge> DirectedFlowGraph::getAllEdges( const Node& start_node) { std::vector<DirectedFlowGraph::DirectedFlowEdge> out_edges, in_edges, result; out_edges = getOutEdges(start_node); in_edges = getInEdges(start_node); result.insert(result.end(), out_edges.begin(), out_edges.end()); result.insert(result.end(), in_edges.begin(), in_edges.end()); return result; }
std::string Graph::concatenateNodes(std::vector<int> const &path) const{ if (path.size() == 0) { return ""; } std::string result = getSequenceOfNode(path[0]); for (int i = 1; i < path.size(); ++i) { if (path[i] == 0) { continue; } std::vector<int> next = getOutEdges(path[i - 1]); if (std::find(next.begin(), next.end(), path[i]) == next.end()) { std::cout << "Path does not exist\n"; } result += getSequenceOfNode(path[i]).substr(k_ - 1); } return result; }
//dijkstra, but take special care if source == sink, //we do not want trivial paths! //considers seq length, not nodecount! //the limit parameter is a hard cut-off for the length of allowed paths std::vector<int> Graph::findMinSeqLenPath(int source, int sink, int limit) const{ std::map<int/*node*/, std::pair<int/*dist*/, int/*prev*/>> nodes; std::deque<int> queue; //only relevant when source == sink int cycle_len = -1; int visited = 1; nodes[source] = (std::pair<int, int>(0, -1)); queue.push_back(source); auto compare_nodes_dijkstra = [&](int a,int b)-> bool { return nodes[a].first < nodes[b].first; }; int max_visited = 100; while (!queue.empty() && visited < max_visited) { int node = queue.front(); queue.pop_front(); if (node == sink && (cycle_len > 0 || node != source)) { //we are done break; } std::vector<int> nbs = getOutEdges(node); for (int i = 0; i < nbs.size(); ++i) { int dist = nodes[node].first + getSizeOfNode(nbs[i]) - (k_ - 1); if (dist < limit) { std::map<int, std::pair<int, int>>::iterator it = nodes.find(nbs[i]); if (it == nodes.end()) { //nbs[i] has not yet been reached nodes[nbs[i]] = std::pair<int, int>(dist, node); queue.push_back(nbs[i]); ++visited; } else { //nbs[i] has already been reached //no need to push to queue! if (dist < (*it).second.first) { (*it).second.first = dist; (*it).second.second = node; } //we found a cycle if (source == sink && source == nbs[i]) { if (cycle_len < 0 || dist < cycle_len) { cycle_len = dist; (*it).second.second = node; } } } } } std::sort(queue.begin(), queue.end(), compare_nodes_dijkstra); } std::vector<int> path; path.push_back(sink); std::map<int, std::pair<int, int>>::iterator it = nodes.find(sink); if (it == nodes.end() || (source == sink && cycle_len == -1)) { path.push_back(0); path.push_back(source); } else { //sink is found path.push_back((*it).second.second); while (path.back() != source) { path.push_back(nodes[path.back()].second); } } std::reverse(path.begin(), path.end()); return path; }
// The same kind of process as DirectedPath but takes an input of // a vector of destinations, and the weight of each intersection // is not added with the hueristic estimation. // the function will return a path as soon as one of the destination // is reached , which means that this destination can be reached in // the least time. vector<unsigned> Dijkstra(unsigned startid, vector<unsigned> endid) { unordered_map<unsigned, bool> flag; //if node is visited unordered_map<unsigned, double> dist; //weight of edge unordered_map<unsigned, pair<unsigned, unsigned>> prev; //the previous node&edge of key prev[startid] = make_pair(startid, 0); priority_queue<pair<unsigned, double>, vector<pair<unsigned, double>>, comparenorm> Q; vector<unsigned> Path; vector<unsigned> testdraw;//DEBUG dist[startid] = 0; Q.push(make_pair(startid, 0)); unsigned destination = endid[0]; bool found = false; unordered_map<unsigned, unsigned>* outedges; /**************************DEBUG USE***************************/ // bool DEBUG = 0; //enable to draw the process of computing the path /***************************************************************/ while (!Q.empty()) { // vector<unsigned> testdraw; unsigned currentid = Q.top().first; Q.pop(); for (vector<unsigned>::iterator iter = endid.begin(); iter != endid.end(); iter++) { if (currentid == *iter) { destination = *iter; found = true; } } if (found) break; if (flag[currentid] != 1) { flag[currentid] = 1; outedges = &getOutEdges(currentid); for (unordered_map<unsigned, unsigned>::const_iterator iter = outedges->begin(); iter != outedges->end(); iter++) { unsigned path_segment = iter->first; unsigned nextid = iter->second; double travel_time = find_segment_travel_time(path_segment) + dist[currentid]; if (getStreetSegmentStreetID(path_segment) != getStreetSegmentStreetID(prev[currentid].second)) travel_time += 0.25; // if (DEBUG) { // testdraw.push_back(path_segment); // DrawPath(testdraw, t_color(64, 153, 255)); // } if ((dist[nextid] == 0) || (travel_time < dist[nextid])) { dist[nextid] = travel_time; prev[nextid] = make_pair(currentid, path_segment); Q.push(make_pair(nextid, dist[nextid])); } } } } unsigned iter = destination; while ((iter != startid) && (dist[destination] != 0)) { pair<unsigned, unsigned> idandpath = prev[iter]; Path.insert(Path.begin(), idandpath.second); iter = idandpath.first; } // if (DEBUG) { // DrawPath(Path, t_color(255, 0, 0)); // } return Path; }
// Use A* algorithm to calculate shortest path between intersections vector<unsigned> DirectedPath(unsigned startid, unsigned endid) { unordered_map<unsigned, bool> flag; //if node is visited unordered_map<unsigned, double> dist; //weight of edge unordered_map<unsigned, pair<unsigned, unsigned>> prev; //the previous node&edge of key prev[startid] = make_pair(startid, 0); LatLon end = getIntersectionPosition(endid); priority_queue<pair<unsigned, double>, vector<pair<unsigned, double>>, comparenorm> Q; // the node to be visited vector<unsigned> Path; Q.push(make_pair(startid, 0)); unordered_map<unsigned, unsigned>* outedges; //the out going edges of an intersection // unordered_map<unsigned, unordered_map<unsigned, pair<unsigned, unsigned>>>::iterator memo; // bool found_memo = false; // unsigned memoid = 0; /**************************DEBUG USE***************************/ bool DEBUG = 0; //enable to draw the process of computing the path /***************************************************************/ while (!Q.empty()) { unsigned currentid = Q.top().first; // accessing the weight of the edge, or distance Q.pop(); if (currentid == endid) break; if (flag[currentid] != 1) { flag[currentid] = 1; // memo = Memoize(currentid, endid); //unfinished implementation of memoization // if (memo != Memo.end()) { // found_memo = true; // memoid = currentid; // cout << "i broke out" <<endl; // break; // } // vector<unsigned> testdraw; //for debug use outedges = &getOutEdges(currentid); //obtain the outgoing edges and the other end point for (unordered_map<unsigned, unsigned>::const_iterator iter = outedges->begin(); iter != outedges->end(); iter++) { //for all the street segments around the current intersections //street segment id unsigned path_segment = iter->first; //the other end point intersection id unsigned nextid = iter->second; // how long it takes to travel through this segment double travel_time = find_segment_travel_time(path_segment) + dist[currentid]; //if the current street segment is on the same street with the next street segment if (getStreetSegmentStreetID(path_segment) != getStreetSegmentStreetID(prev[currentid].second)) travel_time += 0.25; // if (DEBUG) { // testdraw.push_back(path_segment); // DrawPath(testdraw, t_color(64, 153, 255)); // } // if the current path to next intersection is found to be faster than the // previous path, update the path and time if ((dist[nextid] == 0) || (travel_time < dist[nextid])) { dist[nextid] = travel_time; prev[nextid] = make_pair(currentid, path_segment); } // get the position of the next intersection id LatLon currentposition = getIntersectionPosition(nextid); // find the distance between the next intersection id and the end point double current_distance = find_distance_between_two_points(currentposition, end); double weight = ((dist[nextid]) + current_distance * 0.06 / 100); // put the intersection into the priority queue Q.push(make_pair(nextid, weight)); } } } // if(found_memo){ // unsigned iter = endid; // while (iter != memoid) { // pair<unsigned, unsigned> idandpath = ((memo->second).find(iter))->second; // Path.insert(Path.begin(), idandpath.second); // iter = idandpath.first; // } // endid = memoid; // } unsigned iter = endid; while ((iter != startid) && (dist[endid] != 0)) { pair<unsigned, unsigned> idandpath = prev[iter]; Path.insert(Path.begin(), idandpath.second); // if (DEBUG) { // bool OneWay = getStreetSegmentOneWay(idandpath.second); // StreetSegmentEnds ids = getStreetSegmentEnds(idandpath.second); // if (OneWay && (ids.from == iter)) { // cout << "ONEWAY PATH: " << idandpath.second << endl; // cout << "FROM: "<< ids.from << " TO: " << ids.to << endl; // cout << "INSTEAD OF: " << idandpath.first << " TO: " << iter <<endl; // bool connected = are_directly_connected(idandpath.first, iter); // cout << "ARE THEY DIRECTLY CONNECTED? " << connected << endl; // break; // } // } // Memo[iter] = prev; // prev.erase(iter); iter = idandpath.first; } if (DEBUG) { DrawPath(Path, t_color(255, 0, 0)); double computed_time = compute_path_travel_time(Path); if (computed_time == 0) cout <<"PATH FROM: "<< startid <<" TO "<< endid << " NOT FOUND"<<endl; } return Path; }