From 2dbae6ce5106749d30ef24886333eaa6d5d1e712 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 16:47:32 +0100 Subject: [PATCH] Refactoring routing algorithms, alternative computation hastened by sweeping the search space only once. Should fix #572 --- RoutingAlgorithms/AlternativePathRouting.h | 337 ++++++++++++--------- RoutingAlgorithms/BasicRoutingInterface.h | 72 +++-- RoutingAlgorithms/ShortestPathRouting.h | 130 ++------ 3 files changed, 259 insertions(+), 280 deletions(-) diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h index b55d1a9aa..bd542e1a3 100644 --- a/RoutingAlgorithms/AlternativePathRouting.h +++ b/RoutingAlgorithms/AlternativePathRouting.h @@ -21,23 +21,25 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef ALTERNATIVEROUTES_H_ #define ALTERNATIVEROUTES_H_ +#include +#include #include #include "BasicRoutingInterface.h" -const double VIAPATH_ALPHA = 0.25; -const double VIAPATH_EPSILON = 0.25; -const double VIAPATH_GAMMA = 0.80; +const double VIAPATH_ALPHA = 0.15; +const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer +const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest. template -class AlternativeRouting : private BasicRoutingInterface{ +class AlternativeRouting : private BasicRoutingInterface { typedef BasicRoutingInterface super; - typedef std::pair PreselectedNode; - typedef typename QueryDataT::HeapPtr HeapPtr; - typedef std::pair UnpackEdge; + typedef typename QueryDataT::Graph SearchGraph; + typedef typename QueryDataT::QueryHeap QueryHeap; + typedef std::pair SearchSpaceEdge; struct RankedCandidateNode { - RankedCandidateNode(NodeID n, int l, int s) : node(n), length(l), sharing(s) {} + RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {} NodeID node; int length; int sharing; @@ -45,9 +47,12 @@ class AlternativeRouting : private BasicRoutingInterface{ return (2*length + sharing) < (2*other.length + other.sharing); } }; + + const SearchGraph * search_graph; + public: - AlternativeRouting(QueryDataT & qd) : super(qd) { } + AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { } ~AlternativeRouting() {} @@ -59,81 +64,115 @@ public: std::vector alternativePath; std::vector viaNodeCandidates; - std::vector packedShortestPath; - std::vector nodesThatPassPreselection; + std::vector forward_search_space; + std::vector reverse_search_space; - HeapPtr & forwardHeap = super::_queryData.forwardHeap; - HeapPtr & backwardHeap = super::_queryData.backwardHeap; - HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2; - HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2; - - //Initialize Queues + //Initialize Queues, semi-expensive because access to TSS invokes a system call super::_queryData.InitializeOrClearFirstThreadLocalStorage(); - int _upperBound = INT_MAX; - NodeID middle = UINT_MAX; - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); + super::_queryData.InitializeOrClearSecondThreadLocalStorage(); + super::_queryData.InitializeOrClearThirdThreadLocalStorage(); + + QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap); + QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap); + QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2); + QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2); + + int upper_bound_to_shortest_path_distance = INT_MAX; + NodeID middle_node = UINT_MAX; + forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); if(phantomNodePair.startPhantom.isBidirected() ) { - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); + forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); } - backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); + reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); if(phantomNodePair.targetPhantom.isBidirected() ) { - backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); + reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); } - const int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) - + (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1); + const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0); + const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0); //exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath - while(forwardHeap->Size() + backwardHeap->Size() > 0){ - if(forwardHeap->Size() > 0){ - AlternativeRoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, 2*offset, true, viaNodeCandidates); + while(0 < (forward_heap1.Size() + reverse_heap1.Size())){ + if(0 < forward_heap1.Size()){ + AlternativeRoutingStep(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset); } - if(backwardHeap->Size() > 0){ - AlternativeRoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, 2*offset, false, viaNodeCandidates); + if(0 < reverse_heap1.Size()){ + AlternativeRoutingStep(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset); } } - std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end()); - int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin(); - viaNodeCandidates.resize(size); + sort_unique_resize(viaNodeCandidates); - //save (packed) shortest path of shortest path and keep it for later use. - //we need it during the checks and dont want to recompute it always - super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath); + std::vector packed_forward_path; + std::vector packed_reverse_path; - //ch-pruning of via nodes in both search spaces + super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path); + super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path); + boost::unordered_map approximated_forward_sharing; + boost::unordered_map approximated_reverse_sharing; + + unsigned index_into_forward_path = 0; + //sweep over search space, compute forward sharing for each current edge (u,v) + BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) { + const NodeID u = current_edge.first; + const NodeID v = current_edge.second; + if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) { + //current_edge is on shortest path => sharing(u):=queue.GetKey(u); + ++index_into_forward_path; + approximated_forward_sharing[v] = forward_heap1.GetKey(u); + } else { + //sharing (s) = sharing (t) + approximated_forward_sharing[v] = approximated_forward_sharing[u]; + } + } + + unsigned index_into_reverse_path = 0; + //sweep over search space, compute backward sharing + BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) { + const NodeID u = current_edge.first; + const NodeID v = current_edge.second; + if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) { + //current_edge is on shortest path => sharing(u):=queue.GetKey(u); + ++index_into_reverse_path; + approximated_reverse_sharing[v] = reverse_heap1.GetKey(u); + } else { + //sharing (s) = sharing (t) + approximated_reverse_sharing[v] = approximated_reverse_sharing[u]; + } + } + std::vector nodes_that_passed_preselection; BOOST_FOREACH(const NodeID node, viaNodeCandidates) { - if(node == middle) //subpath optimality tells us that this case is just the shortest path - continue; + int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node]; + int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node); + bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)); + bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA); + bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing); - int sharing = approximateAmountOfSharing(node, forwardHeap, backwardHeap, packedShortestPath); - int length1 = forwardHeap->GetKey(node); - int length2 = backwardHeap->GetKey(node); - bool lengthPassed = (length1+length2 < _upperBound*(1+VIAPATH_EPSILON)); - bool sharingPassed = (sharing <= _upperBound*VIAPATH_GAMMA); - bool stretchPassed = length1+length2 - sharing < (1.+VIAPATH_EPSILON)*(_upperBound-sharing); - - if(lengthPassed && sharingPassed && stretchPassed) - nodesThatPassPreselection.push_back(std::make_pair(node, length1+length2)); + if(lengthPassed && sharingPassed && stretchPassed) { + nodes_that_passed_preselection.push_back(node); + } } + std::vector & packedShortestPath = packed_forward_path; + std::reverse(packedShortestPath.begin(), packedShortestPath.end()); + packedShortestPath.push_back(middle_node); + packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end()); std::vector rankedCandidates; //prioritizing via nodes for deep inspection - BOOST_FOREACH(const PreselectedNode node, nodesThatPassPreselection) { + BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) { int lengthOfViaPath = 0, sharingOfViaPath = 0; - - computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath); - if(sharingOfViaPath <= VIAPATH_GAMMA*_upperBound) - rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath)); + computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath); + if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) { + rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath)); + } } - std::sort(rankedCandidates.begin(), rankedCandidates.end()); NodeID selectedViaNode = UINT_MAX; int lengthOfViaPath = INT_MAX; NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX; - BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){ - if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, _upperBound, &lengthOfViaPath, &s_v_middle, &v_t_middle)) { + BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){ + if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) { // select first admissable selectedViaNode = candidate.node; break; @@ -141,15 +180,15 @@ public: } //Unpack shortest path and alternative, if they exist - if(INT_MAX != _upperBound) { + if(INT_MAX != upper_bound_to_shortest_path_distance) { super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath); - rawRouteData.lengthOfShortestPath = _upperBound; + rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance; } else { rawRouteData.lengthOfShortestPath = INT_MAX; } if(selectedViaNode != UINT_MAX) { - retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath); + retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath); rawRouteData.lengthOfAlternativePath = lengthOfViaPath; } else { rawRouteData.lengthOfAlternativePath = INT_MAX; @@ -158,7 +197,7 @@ public: private: //unpack by exploring search spaces from v - inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2, + inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2, const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) { //unpack [s,v) std::vector packed_s_v_path, packed_v_t_path; @@ -170,16 +209,16 @@ private: super::UnpackPath(packed_s_v_path, unpackedPath); } - inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath, - const int offset, const std::vector & packedShortestPath) { + inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path, + const int offset, const std::vector & packed_shortest_path) { //compute and unpack and by exploring search spaces from v and intersecting against queues //only half-searches have to be done at this stage super::_queryData.InitializeOrClearSecondThreadLocalStorage(); - HeapPtr & existingForwardHeap = super::_queryData.forwardHeap; - HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap; - HeapPtr & newForwardHeap = super::_queryData.forwardHeap2; - HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2; + QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap; + QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap; + QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2; + QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2; std::vector < NodeID > packed_s_v_path; std::vector < NodeID > packed_v_t_path; @@ -189,18 +228,18 @@ private: NodeID s_v_middle = UINT_MAX; int upperBoundFor_s_v_Path = INT_MAX;//compute path by reusing forward search from s - newBackwardHeap->Insert(node.first, 0, node.first); - while (newBackwardHeap->Size() > 0) { + newBackwardHeap.Insert(via_node, 0, via_node); + while (0 < newBackwardHeap.Size()) { super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false); } //compute path by reusing backward search from node t NodeID v_t_middle = UINT_MAX; int upperBoundFor_v_t_Path = INT_MAX; - newForwardHeap->Insert(node.first, 0, node.first); - while (newForwardHeap->Size() > 0) { + newForwardHeap.Insert(via_node, 0, via_node); + while (0 < newForwardHeap.Size() ) { super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true); } - *lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path; + *real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path; if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle) return; @@ -211,35 +250,35 @@ private: //partial unpacking, compute sharing //First partially unpack s-->v until paths deviate, note length of common path. - for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packedShortestPath.size()) - 1; (i < lengthOfPackedPath); ++i) { - if (packed_s_v_path[i] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) { + if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) { + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } else { - if (packed_s_v_path[i] == packedShortestPath[i]) { + if (packed_s_v_path[i] == packed_shortest_path[i]) { super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath); - super::UnpackEdge(packedShortestPath[i], packedShortestPath[i+1], partiallyUnpackedShortestPath); + super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath); break; } } } //traverse partially unpacked edge and note common prefix for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } //Second, partially unpack v-->t in reverse order until paths deviate and note lengths int viaPathIndex = packed_v_t_path.size() - 1; - int shortestPathIndex = packedShortestPath.size() - 1; + int shortestPathIndex = packed_shortest_path.size() - 1; for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) { - if (packed_v_t_path[viaPathIndex - 1] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) { + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } else { - if (packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) { + if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) { super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath); - super::UnpackEdge(packedShortestPath[shortestPathIndex-1] , packedShortestPath[shortestPathIndex], partiallyUnpackedShortestPath); + super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath); break; } } @@ -249,16 +288,16 @@ private: shortestPathIndex = partiallyUnpackedShortestPath.size() - 1; for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) { if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } else { break; } } - //finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable + //finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable } - inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector & packedShortestPath) { + inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector & packedShortestPath) { std::vector packedAlternativePath; super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath); @@ -270,8 +309,8 @@ private: //compute forward sharing while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) { // INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")"); - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]); - sharing += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]); + sharing += search_graph->GetEdgeData(edgeID).distance; ++aindex; } @@ -279,55 +318,65 @@ private: int bindex = packedShortestPath.size()-1; //compute backward sharing while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]); - sharing += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]); + sharing += search_graph->GetEdgeData(edgeID).distance; --aindex; --bindex; } return sharing; } - inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector& searchSpaceIntersection) const { - const NodeID node = _forwardHeap->DeleteMin(); + template + inline void AlternativeRoutingStep( + QueryHeap & _forward_heap, + QueryHeap & _reverse_heap, + NodeID *middle_node, + int *upper_bound_to_shortest_path_distance, + std::vector& searchSpaceIntersection, + std::vector & search_space, + const int edgeBasedOffset + ) const { + const NodeID node = _forward_heap.DeleteMin(); + const int distance = _forward_heap.GetKey(node); + int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON); + if(scaledDistance > *upper_bound_to_shortest_path_distance){ + _forward_heap.DeleteAll(); + return; + } - const int distance = _forwardHeap->GetKey(node); - if(_backwardHeap->WasInserted(node) ){ + search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node)); + + if(_reverse_heap.WasInserted(node) ){ searchSpaceIntersection.push_back(node); - const int newDistance = _backwardHeap->GetKey(node) + distance; - if(newDistance < *_upperbound ){ + const int newDistance = _reverse_heap.GetKey(node) + distance; + if(newDistance < *upper_bound_to_shortest_path_distance ){ if(newDistance>=0 ) { - *middle = node; - *_upperbound = newDistance; + *middle_node = node; + *upper_bound_to_shortest_path_distance = newDistance; } } } - int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON); - if(scaledDistance > *_upperbound){ - _forwardHeap->DeleteAll(); - return; - } - - for ( typename QueryDataT::Graph::EdgeIterator edge = super::_queryData.graph->BeginEdges( node ); edge < super::_queryData.graph->EndEdges(node); edge++ ) { - const typename QueryDataT::Graph::EdgeData & data = super::_queryData.graph->GetEdgeData(edge); + for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) { + const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge); bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); if(forwardDirectionFlag) { - const NodeID to = super::_queryData.graph->GetTarget(edge); + const NodeID to = search_graph->GetTarget(edge); const int edgeWeight = data.distance; assert( edgeWeight > 0 ); const int toDistance = distance + edgeWeight; //New Node discovered -> Add to Heap + Node Info Storage - if ( !_forwardHeap->WasInserted( to ) ) { - _forwardHeap->Insert( to, toDistance, node ); + if ( !_forward_heap.WasInserted( to ) ) { + _forward_heap.Insert( to, toDistance, node ); } //Found a shorter Path -> Update distance - else if ( toDistance < _forwardHeap->GetKey( to ) ) { - _forwardHeap->GetData( to ).parent = node; - _forwardHeap->DecreaseKey( to, toDistance ); + else if ( toDistance < _forward_heap.GetKey( to ) ) { + _forward_heap.GetData( to ).parent = node; + _forward_heap.DecreaseKey( to, toDistance ); //new parent } } @@ -335,16 +384,17 @@ private: } //conduct T-Test - inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) { + inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) { + newForwardHeap.Clear(); + newBackwardHeap.Clear(); std::vector < NodeID > packed_s_v_path; std::vector < NodeID > packed_v_t_path; - super::_queryData.InitializeOrClearSecondThreadLocalStorage(); *s_v_middle = UINT_MAX; int upperBoundFor_s_v_Path = INT_MAX; //compute path by reusing forward search from s - newBackwardHeap->Insert(candidate.node, 0, candidate.node); - while (newBackwardHeap->Size() > 0) { + newBackwardHeap.Insert(candidate.node, 0, candidate.node); + while (newBackwardHeap.Size() > 0) { super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false); } @@ -354,8 +404,8 @@ private: //compute path by reusing backward search from t *v_t_middle = UINT_MAX; int upperBoundFor_v_t_Path = INT_MAX; - newForwardHeap->Insert(candidate.node, 0, candidate.node); - while (newForwardHeap->Size() > 0) { + newForwardHeap.Insert(candidate.node, 0, candidate.node); + while (newForwardHeap.Size() > 0) { super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true); } @@ -372,11 +422,11 @@ private: const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath; int unpackedUntilDistance = 0; - std::stack unpackStack; + std::stack unpackStack; //Traverse path s-->v for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]); - int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]); + int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance; if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i])); } else { @@ -386,17 +436,17 @@ private: } while (!unpackStack.empty()) { - const UnpackEdge viaPathEdge = unpackStack.top(); + const SearchSpaceEdge viaPathEdge = unpackStack.top(); unpackStack.pop(); - typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); + typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); if(UINT_MAX == edgeIDInViaPath) return false; - typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath); + typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath); bool IsViaEdgeShortCut = currentEdgeData.shortcut; if (IsViaEdgeShortCut) { const NodeID middleOfViaPath = currentEdgeData.id; - typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second); - int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).distance; + typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second); + int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance; //attention: !unpacking in reverse! //Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one. if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) { @@ -416,8 +466,8 @@ private: unpackedUntilDistance = 0; //Traverse path s-->v for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]); - int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]); + int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance; if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1])); } else { @@ -427,17 +477,17 @@ private: } while (!unpackStack.empty()) { - const UnpackEdge viaPathEdge = unpackStack.top(); + const SearchSpaceEdge viaPathEdge = unpackStack.top(); unpackStack.pop(); - typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); + typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); if(UINT_MAX == edgeIDInViaPath) return false; - typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath); + typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath); const bool IsViaEdgeShortCut = currentEdgeData.shortcut; if (IsViaEdgeShortCut) { const NodeID middleOfViaPath = currentEdgeData.id; - typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath); - int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData( edgeIDOfFirstSegment).distance; + typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath); + int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance; //Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one. if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) { unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath)); @@ -454,19 +504,18 @@ private: lengthOfPathT_Test_Path += unpackedUntilDistance; //Run actual T-Test query and compare if distances equal. - HeapPtr& forwardHeap = super::_queryData.forwardHeap3; - HeapPtr& backwardHeap = super::_queryData.backwardHeap3; - super::_queryData.InitializeOrClearThirdThreadLocalStorage(); + QueryHeap& forwardHeap = *super::_queryData.forwardHeap3; + QueryHeap& backwardHeap = *super::_queryData.backwardHeap3; int _upperBound = INT_MAX; NodeID middle = UINT_MAX; - forwardHeap->Insert(s_P, 0, s_P); - backwardHeap->Insert(t_P, 0, t_P); + forwardHeap.Insert(s_P, 0, s_P); + backwardHeap.Insert(t_P, 0, t_P); //exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath - while (forwardHeap->Size() + backwardHeap->Size() > 0) { - if (forwardHeap->Size() > 0) { + while (forwardHeap.Size() + backwardHeap.Size() > 0) { + if (forwardHeap.Size() > 0) { super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true); } - if (backwardHeap->Size() > 0) { + if (backwardHeap.Size() > 0) { super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false); } } diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index bbe0474e4..f329c697b 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -23,43 +23,43 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef BASICROUTINGINTERFACE_H_ #define BASICROUTINGINTERFACE_H_ +#include + #include #include #include "../Plugins/RawRouteData.h" +#include "../Util/ContainerUtils.h" template -class BasicRoutingInterface { +class BasicRoutingInterface : boost::noncopyable{ protected: QueryDataT & _queryData; public: BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { } virtual ~BasicRoutingInterface(){ }; - inline void RoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const { - const NodeID node = _forwardHeap->DeleteMin(); - const int distance = _forwardHeap->GetKey(node); -// INFO((forwardDirection ? "[forw]" : "[back]") << " settled node " << node << " at distance " << distance); - if(_backwardHeap->WasInserted(node) ){ -// INFO((forwardDirection ? "[forw]" : "[back]") << " scanned node " << node << " in both directions, upper bound: " << *_upperbound); - const int newDistance = _backwardHeap->GetKey(node) + distance; + inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const { + const NodeID node = _forwardHeap.DeleteMin(); + const int distance = _forwardHeap.GetKey(node); + if(_backwardHeap.WasInserted(node) ){ + const int newDistance = _backwardHeap.GetKey(node) + distance; if(newDistance < *_upperbound ){ if(newDistance>=0 ) { -// INFO((forwardDirection ? "[forw]" : "[back]") << " -> node " << node << " is new middle at total distance " << newDistance); *middle = node; *_upperbound = newDistance; } else { -// INFO((forwardDirection ? "[forw]" : "[back]") << " -> ignored " << node << " as new middle at total distance " << newDistance); } } } if(distance-edgeBasedOffset > *_upperbound){ - _forwardHeap->DeleteAll(); + _forwardHeap.DeleteAll(); return; } - for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) { + //Stalling + for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) { const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge); bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward; if(backwardDirectionFlag) { @@ -68,16 +68,15 @@ public: assert( edgeWeight > 0 ); - //Stalling - if(_forwardHeap->WasInserted( to )) { - if(_forwardHeap->GetKey( to ) + edgeWeight < distance) { + if(_forwardHeap.WasInserted( to )) { + if(_forwardHeap.GetKey( to ) + edgeWeight < distance) { return; } } } } - for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) { + for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) { const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge); bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); if(forwardDirectionFlag) { @@ -89,23 +88,20 @@ public: const int toDistance = distance + edgeWeight; //New Node discovered -> Add to Heap + Node Info Storage - if ( !_forwardHeap->WasInserted( to ) ) { - // INFO((forwardDirection ? "[forw]" : "[back]") << " scanning edge (" << node << "," << to << ") with distance " << toDistance << ", edge length: " << data.distance); - _forwardHeap->Insert( to, toDistance, node ); + if ( !_forwardHeap.WasInserted( to ) ) { + _forwardHeap.Insert( to, toDistance, node ); } //Found a shorter Path -> Update distance - else if ( toDistance < _forwardHeap->GetKey( to ) ) { - // INFO((forwardDirection ? "[forw]" : "[back]") << " decrease and scanning edge (" << node << "," << to << ") from " << _forwardHeap->GetKey(to) << "to " << toDistance << ", edge length: " << data.distance); - _forwardHeap->GetData( to ).parent = node; - _forwardHeap->DecreaseKey( to, toDistance ); + else if ( toDistance < _forwardHeap.GetKey( to ) ) { + _forwardHeap.GetData( to ).parent = node; + _forwardHeap.DecreaseKey( to, toDistance ); //new parent } } } } - inline void UnpackPath(std::vector & packedPath, std::vector<_PathData> & unpackedPath) const { - + inline void UnpackPath(const std::vector & packedPath, std::vector<_PathData> & unpackedPath) const { const unsigned sizeOfPackedPath = packedPath.size(); std::stack > recursionStack; @@ -118,15 +114,12 @@ public: while(!recursionStack.empty()) { edge = recursionStack.top(); recursionStack.pop(); -// INFO("Unpacking edge (" << edge.first << "," << edge.second << ")"); typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID; int smallestWeight = INT_MAX; for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){ const int weight = _queryData.graph->GetEdgeData(eit).distance; -// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")"); if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){ -// INFO("1smallest " << eit << ", " << weight); smallestEdge = eit; smallestWeight = weight; } @@ -135,9 +128,7 @@ public: if(smallestEdge == SPECIAL_EDGEID){ for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){ const int weight = _queryData.graph->GetEdgeData(eit).distance; -// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")"); if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){ -// INFO("2smallest " << eit << ", " << weight); smallestEdge = eit; smallestWeight = weight; } @@ -159,7 +150,6 @@ public: } inline void UnpackEdge(const NodeID s, const NodeID t, std::vector & unpackedPath) const { - std::stack > recursionStack; recursionStack.push(std::make_pair(s,t)); @@ -193,7 +183,6 @@ public: if(ed.shortcut) {//unpack const NodeID middle = ed.id; //again, we need to this in reversed order -// INFO("unpacking (" << middle << "," << edge.second << ") and (" << edge.first << "," << middle << ")"); recursionStack.push(std::make_pair(middle, edge.second)); recursionStack.push(std::make_pair(edge.first, middle)); } else { @@ -204,22 +193,29 @@ public: unpackedPath.push_back(t); } - inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector& packedPath) { + inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector& packedPath) const { NodeID pathNode = middle; - while(pathNode != _fHeap->GetData(pathNode).parent) { - pathNode = _fHeap->GetData(pathNode).parent; + while(pathNode != _fHeap.GetData(pathNode).parent) { + pathNode = _fHeap.GetData(pathNode).parent; packedPath.push_back(pathNode); } std::reverse(packedPath.begin(), packedPath.end()); - packedPath.push_back(middle); pathNode = middle; - while (pathNode != _bHeap->GetData(pathNode).parent){ - pathNode = _bHeap->GetData(pathNode).parent; + while (pathNode != _bHeap.GetData(pathNode).parent){ + pathNode = _bHeap.GetData(pathNode).parent; packedPath.push_back(pathNode); } } + + inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector& packed_path) const { + NodeID pathNode = middle; + while(pathNode != search_heap.GetData(pathNode).parent) { + pathNode = search_heap.GetData(pathNode).parent; + packed_path.push_back(pathNode); + } + } }; diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h index 6fc4c5996..a21673807 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -28,13 +28,14 @@ or see http://www.gnu.org/licenses/agpl.txt. template class ShortestPathRouting : public BasicRoutingInterface{ typedef BasicRoutingInterface super; + typedef typename QueryDataT::QueryHeap QueryHeap; public: - ShortestPathRouting(QueryDataT & qd) : super(qd) {} + ShortestPathRouting( QueryDataT & qd) : super(qd) {} ~ShortestPathRouting() {} - void operator()(std::vector & phantomNodesVector, RawRouteData & rawRouteData) { - BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) { + void operator()(std::vector & phantomNodesVector, RawRouteData & rawRouteData) const { + BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) { if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) { rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX; return; @@ -43,77 +44,65 @@ public: int distance1 = 0; int distance2 = 0; - bool searchFrom1stStartNode(true); - bool searchFrom2ndStartNode(true); - NodeID middle1 = ( NodeID ) UINT_MAX; - NodeID middle2 = ( NodeID ) UINT_MAX; + bool searchFrom1stStartNode = true; + bool searchFrom2ndStartNode = true; + NodeID middle1 = UINT_MAX; + NodeID middle2 = UINT_MAX; std::vector packedPath1; std::vector packedPath2; - typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap; - typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap; - - typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2; - typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2; + super::_queryData.InitializeOrClearFirstThreadLocalStorage(); + super::_queryData.InitializeOrClearSecondThreadLocalStorage(); + QueryHeap & forwardHeap = *super::_queryData.forwardHeap; + QueryHeap & backwardHeap = *super::_queryData.backwardHeap; + QueryHeap & forwardHeap2 = *super::_queryData.forwardHeap2; + QueryHeap & backwardHeap2 = *super::_queryData.backwardHeap2; //Get distance to next pair of target nodes. - BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) { - super::_queryData.InitializeOrClearFirstThreadLocalStorage(); - super::_queryData.InitializeOrClearSecondThreadLocalStorage(); - + BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) { + forwardHeap.Clear(); forwardHeap2.Clear(); + backwardHeap.Clear(); backwardHeap2.Clear(); int _localUpperbound1 = INT_MAX; int _localUpperbound2 = INT_MAX; //insert new starting nodes into forward heap, adjusted by previous distances. if(searchFrom1stStartNode) { - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); - forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); -// INFO("a 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode << " with weight " << phantomNodePair.startPhantom.weight1); -// } else { -// INFO("Skipping first start node"); + forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); + forwardHeap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); } if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) { - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); - forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); -// INFO("b 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << -phantomNodePair.startPhantom.weight1); -// } else if(!searchFrom2ndStartNode) { -// INFO("Skipping second start node"); + forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); + forwardHeap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); } -// backwardHeap->Clear(); -// backwardHeap2->Clear(); //insert new backward nodes into backward heap, unadjusted. - backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); -// INFO("1) back insert " << phantomNodePair.targetPhantom.edgeBasedNode << " with weight " << phantomNodePair.targetPhantom.weight1); + backwardHeap.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); if(phantomNodePair.targetPhantom.isBidirected() ) { -// INFO("2) back insert " << phantomNodePair.targetPhantom.edgeBasedNode+1 << " with weight " << phantomNodePair.targetPhantom.weight2); - backwardHeap2->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); + backwardHeap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); } int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) ; offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ; //run two-Target Dijkstra routing step. - while(forwardHeap->Size() + backwardHeap->Size() > 0){ - if(forwardHeap->Size() > 0){ + while(forwardHeap.Size() + backwardHeap.Size() > 0){ + if(forwardHeap.Size() > 0){ super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true); } - if(backwardHeap->Size() > 0){ + if(backwardHeap.Size() > 0){ super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false); } } - if(backwardHeap2->Size() > 0) { - while(forwardHeap2->Size() + backwardHeap2->Size() > 0){ - if(forwardHeap2->Size() > 0){ + if(backwardHeap2.Size() > 0) { + while(forwardHeap2.Size() + backwardHeap2.Size() > 0){ + if(forwardHeap2.Size() > 0){ super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true); } - if(backwardHeap2->Size() > 0){ + if(backwardHeap2.Size() > 0){ super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, 2*offset, false); } } } -// INFO("upperbound1: " << _localUpperbound1 << ", distance1: " << distance1); -// INFO("upperbound2: " << _localUpperbound2 << ", distance2: " << distance2); //No path found for both target nodes? if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) { @@ -122,46 +111,35 @@ public: } if(UINT_MAX == middle1) { searchFrom1stStartNode = false; -// INFO("Next Search will not start from 1st"); } else { -// INFO("Next Search will start from 1st"); searchFrom1stStartNode = true; } if(UINT_MAX == middle2) { searchFrom2ndStartNode = false; -// INFO("Next Search will not start from 2nd"); } else { searchFrom2ndStartNode = true; -// INFO("Next Search will start from 2nd"); } //Was at most one of the two paths not found? assert(!(INT_MAX == distance1 && INT_MAX == distance2)); -// INFO("middle1: " << middle1); - //Unpack paths if they exist std::vector temporaryPackedPath1; std::vector temporaryPackedPath2; if(INT_MAX != _localUpperbound1) { super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1); -// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) ); } -// INFO("middle2: " << middle2); if(INT_MAX != _localUpperbound2) { super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2); -// INFO("temporaryPackedPath2 ends with " << *(temporaryPackedPath2.end()-1) ); } //if one of the paths was not found, replace it with the other one. if(0 == temporaryPackedPath1.size()) { -// INFO("Deleting path 1"); temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end()); _localUpperbound1 = _localUpperbound2; } if(0 == temporaryPackedPath2.size()) { -// INFO("Deleting path 2"); temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end()); _localUpperbound2 = _localUpperbound1; } @@ -170,28 +148,21 @@ public: //Plug paths together, s.t. end of packed path is begin of temporary packed path if(0 < packedPath1.size() && 0 < packedPath2.size() ) { -// INFO("Both paths are non-empty"); if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) { -// INFO("both paths start with the same node:" << *(temporaryPackedPath1.begin())); //both new route segments start with the same node, thus one of the packedPath must go. assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) ); if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) { -// INFO("Deleting packedPath2 that ends with " << *(packedPath2.end()-1) << ", other ends with " << *(packedPath1.end()-1)); packedPath2.clear(); packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end()); distance2 = distance1; -// INFO("packedPath2 now ends with " << *(packedPath2.end()-1)); } else { -// INFO("Deleting path1 that ends with " << *(packedPath1.end()-1) << ", other ends with " << *(packedPath2.end()-1)); packedPath1.clear(); packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end()); distance1 = distance2; -// INFO("Path1 now ends with " << *(packedPath1.end()-1)); } } else { //packed paths 1 and 2 may need to switch. if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) { -// INFO("Switching"); packedPath1.swap(packedPath2); std::swap(distance1, distance2); } @@ -201,61 +172,24 @@ public: packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end()); if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) { -// INFO("both paths end in same direction on bidirected edge, make sure start only start with : " << packedPath1.back()); NodeID lastNodeID = packedPath2.back(); searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1); searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode); -// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode << ": " << (searchFrom1stStartNode ? "yes" : "no") ); -// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ": " << (searchFrom2ndStartNode ? "yes" : "no") ); } distance1 += _localUpperbound1; distance2 += _localUpperbound2; } -// INFO("length path1: " << distance1); -// INFO("length path2: " << distance2); - if(distance1 <= distance2){ - //remove consecutive duplicates -// std::cout << "unclean 1: "; -// for(unsigned i = 0; i < packedPath1.size(); ++i) -// std::cout << packedPath1[i] << " "; -// std::cout << std::endl; - -// std::cout << "cleaned 1: "; -// for(unsigned i = 0; i < packedPath1.size(); ++i) -// std::cout << packedPath1[i] << " "; -// std::cout << std::endl; -// super::UnpackPath(packedPath1, rawRouteData.computedShortestPath); - } else { + if(distance1 > distance2){ std::swap(packedPath1, packedPath2); -// std::cout << "unclean 2: "; -// for(unsigned i = 0; i < packedPath2.size(); ++i) -// std::cout << packedPath2[i] << " "; -// std::cout << std::endl; -// _RemoveConsecutiveDuplicatesFromContainer(packedPath2); -// std::cout << "cleaned 2: "; -// for(unsigned i = 0; i < packedPath2.size(); ++i) -// std::cout << packedPath2[i] << " "; -// std::cout << std::endl; -// super::UnpackPath(packedPath2, unpackedPath); } - _RemoveConsecutiveDuplicatesFromContainer(packedPath1); + remove_consecutive_duplicates_from_vector(packedPath1); super::UnpackPath(packedPath1, rawRouteData.computedShortestPath); rawRouteData.lengthOfShortestPath = std::min(distance1, distance2); -// INFO("Found via route with distance " << std::min(distance1, distance2)); return; } -private: - template - void _RemoveConsecutiveDuplicatesFromContainer(ContainerT & packedPath) { - //remove consecutive duplicates - typename ContainerT::iterator it; - // using default comparison: - it = std::unique(packedPath.begin(), packedPath.end()); - packedPath.resize(it - packedPath.begin()); - } }; #endif /* SHORTESTPATHROUTING_H_ */