// Copyright 2017, University of Freiburg, // Chair of Algorithms and Data Structures. // Authors: Patrick Brosi // _____________________________________________________________________________ template C Dijkstra::shortestPathImpl(Node* from, const std::set*>& to, const ShortestPath::CostFunc& costFunc, const ShortestPath::HeurFunc& heurFunc, EList* resEdges, NList* resNodes) { if (from->getOutDeg() == 0) return costFunc.inf(); Settled settled; PQ pq; bool found = false; pq.emplace(from); RouteNode cur; while (!pq.empty()) { Dijkstra::ITERS++; if (settled.find(pq.top().n) != settled.end()) { pq.pop(); continue; } cur = pq.top(); pq.pop(); settled[cur.n] = cur; if (to.find(cur.n) != to.end()) { found = true; break; } relax(cur, to, costFunc, heurFunc, pq); } if (!found) return costFunc.inf(); buildPath(cur.n, settled, resNodes, resEdges); return cur.d; } // _____________________________________________________________________________ template C Dijkstra::shortestPathImpl(const std::set*> from, const std::set*>& to, const ShortestPath::CostFunc& costFunc, const ShortestPath::HeurFunc& heurFunc, EList* resEdges, NList* resNodes) { Settled settled; PQ pq; bool found = false; // put all nodes in from onto PQ for (auto n : from) pq.emplace(n); RouteNode cur; while (!pq.empty()) { Dijkstra::ITERS++; if (settled.find(pq.top().n) != settled.end()) { pq.pop(); continue; } cur = pq.top(); pq.pop(); settled[cur.n] = cur; if (to.find(cur.n) != to.end()) { found = true; break; } relax(cur, to, costFunc, heurFunc, pq); } if (!found) return costFunc.inf(); buildPath(cur.n, settled, resNodes, resEdges); return cur.d; } // _____________________________________________________________________________ template std::unordered_map*, C> Dijkstra::shortestPathImpl( Node* from, const std::set*>& to, const ShortestPath::CostFunc& costFunc, const ShortestPath::HeurFunc& heurFunc, std::unordered_map*, EList*> resEdges, std::unordered_map*, NList*> resNodes) { std::unordered_map*, C> costs; if (to.size() == 0) return costs; // init costs with inf for (auto n : to) costs[n] = costFunc.inf(); if (from->getOutDeg() == 0) return costs; Settled settled; PQ pq; size_t found = 0; pq.emplace(from); RouteNode cur; while (!pq.empty()) { Dijkstra::ITERS++; if (settled.find(pq.top().n) != settled.end()) { pq.pop(); continue; } cur = pq.top(); pq.pop(); settled[cur.n] = cur; if (to.find(cur.n) != to.end()) { found++; } if (found == to.size()) break; relax(cur, to, costFunc, heurFunc, pq); } for (auto nto : to) { if (!settled.count(nto)) continue; Node* curN = nto; costs[nto] = settled[curN].d; buildPath(nto, settled, resNodes[nto], resEdges[nto]); } return costs; } // _____________________________________________________________________________ template void Dijkstra::relax(RouteNode& cur, const std::set*>& to, const ShortestPath::CostFunc& costFunc, const ShortestPath::HeurFunc& heurFunc, PQ& pq) { for (auto edge : cur.n->getAdjListOut()) { C newC = costFunc(cur.n, edge, edge->getOtherNd(cur.n)); newC = cur.d + newC; if (costFunc.inf() <= newC) continue; const C& newH = newC + heurFunc(edge->getOtherNd(cur.n), to); pq.emplace(edge->getOtherNd(cur.n), cur.n, newC, newH, &(*edge)); } } // _____________________________________________________________________________ template void Dijkstra::buildPath(Node* curN, Settled& settled, NList* resNodes, EList* resEdges) { while (true) { const RouteNode& curNode = settled[curN]; if (resNodes) resNodes->push_back(curNode.n); if (!curNode.parent) break; if (resEdges) resEdges->push_back(curNode.e); curN = curNode.parent; } }