Refactoring routing algorithms, alternative computation hastened by

sweeping the search space only once. Should fix #572
This commit is contained in:
DennisOSRM 2013-02-03 16:47:32 +01:00
parent 7d9d0878de
commit 2dbae6ce51
3 changed files with 259 additions and 280 deletions

View File

@ -21,23 +21,25 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef ALTERNATIVEROUTES_H_ #ifndef ALTERNATIVEROUTES_H_
#define ALTERNATIVEROUTES_H_ #define ALTERNATIVEROUTES_H_
#include <boost/unordered_map.hpp>
#include <vector>
#include <cmath> #include <cmath>
#include "BasicRoutingInterface.h" #include "BasicRoutingInterface.h"
const double VIAPATH_ALPHA = 0.25; const double VIAPATH_ALPHA = 0.15;
const double VIAPATH_EPSILON = 0.25; const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
const double VIAPATH_GAMMA = 0.80; const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
template<class QueryDataT> template<class QueryDataT>
class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{ class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
typedef BasicRoutingInterface<QueryDataT> super; typedef BasicRoutingInterface<QueryDataT> super;
typedef std::pair<NodeID, int> PreselectedNode; typedef typename QueryDataT::Graph SearchGraph;
typedef typename QueryDataT::HeapPtr HeapPtr; typedef typename QueryDataT::QueryHeap QueryHeap;
typedef std::pair<NodeID, NodeID> UnpackEdge; typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
struct RankedCandidateNode { 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; NodeID node;
int length; int length;
int sharing; int sharing;
@ -45,9 +47,12 @@ class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{
return (2*length + sharing) < (2*other.length + other.sharing); return (2*length + sharing) < (2*other.length + other.sharing);
} }
}; };
const SearchGraph * search_graph;
public: public:
AlternativeRouting(QueryDataT & qd) : super(qd) { } AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
~AlternativeRouting() {} ~AlternativeRouting() {}
@ -59,81 +64,115 @@ public:
std::vector<NodeID> alternativePath; std::vector<NodeID> alternativePath;
std::vector<NodeID> viaNodeCandidates; std::vector<NodeID> viaNodeCandidates;
std::vector <NodeID> packedShortestPath; std::vector<SearchSpaceEdge> forward_search_space;
std::vector<PreselectedNode> nodesThatPassPreselection; std::vector<SearchSpaceEdge> reverse_search_space;
HeapPtr & forwardHeap = super::_queryData.forwardHeap; //Initialize Queues, semi-expensive because access to TSS invokes a system call
HeapPtr & backwardHeap = super::_queryData.backwardHeap;
HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
//Initialize Queues
super::_queryData.InitializeOrClearFirstThreadLocalStorage(); super::_queryData.InitializeOrClearFirstThreadLocalStorage();
int _upperBound = INT_MAX; super::_queryData.InitializeOrClearSecondThreadLocalStorage();
NodeID middle = UINT_MAX; super::_queryData.InitializeOrClearThirdThreadLocalStorage();
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
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() ) { 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() ) { 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) const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
+ (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1); 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 //exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while(forwardHeap->Size() + backwardHeap->Size() > 0){ while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
if(forwardHeap->Size() > 0){ if(0 < forward_heap1.Size()){
AlternativeRoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, 2*offset, true, viaNodeCandidates); AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
} }
if(backwardHeap->Size() > 0){ if(0 < reverse_heap1.Size()){
AlternativeRoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, 2*offset, false, viaNodeCandidates); AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
} }
} }
std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end()); sort_unique_resize(viaNodeCandidates);
int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin();
viaNodeCandidates.resize(size);
//save (packed) shortest path of shortest path and keep it for later use. std::vector<NodeID> packed_forward_path;
//we need it during the checks and dont want to recompute it always std::vector<NodeID> packed_reverse_path;
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath);
//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<NodeID, int> approximated_forward_sharing;
boost::unordered_map<NodeID, int> 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<NodeID> nodes_that_passed_preselection;
BOOST_FOREACH(const NodeID node, viaNodeCandidates) { BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
if(node == middle) //subpath optimality tells us that this case is just the shortest path int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
continue; 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); if(lengthPassed && sharingPassed && stretchPassed) {
int length1 = forwardHeap->GetKey(node); nodes_that_passed_preselection.push_back(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));
} }
std::vector<NodeID> & 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<RankedCandidateNode > rankedCandidates; std::vector<RankedCandidateNode > rankedCandidates;
//prioritizing via nodes for deep inspection //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; int lengthOfViaPath = 0, sharingOfViaPath = 0;
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath);
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath); if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) {
if(sharingOfViaPath <= VIAPATH_GAMMA*_upperBound) rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath));
rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath)); }
} }
std::sort(rankedCandidates.begin(), rankedCandidates.end()); std::sort(rankedCandidates.begin(), rankedCandidates.end());
NodeID selectedViaNode = UINT_MAX; NodeID selectedViaNode = UINT_MAX;
int lengthOfViaPath = INT_MAX; int lengthOfViaPath = INT_MAX;
NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX; NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){ BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){
if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, _upperBound, &lengthOfViaPath, &s_v_middle, &v_t_middle)) { 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 // select first admissable
selectedViaNode = candidate.node; selectedViaNode = candidate.node;
break; break;
@ -141,15 +180,15 @@ public:
} }
//Unpack shortest path and alternative, if they exist //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); super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = _upperBound; rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
} else { } else {
rawRouteData.lengthOfShortestPath = INT_MAX; rawRouteData.lengthOfShortestPath = INT_MAX;
} }
if(selectedViaNode != UINT_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; rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
} else { } else {
rawRouteData.lengthOfAlternativePath = INT_MAX; rawRouteData.lengthOfAlternativePath = INT_MAX;
@ -158,7 +197,7 @@ public:
private: private:
//unpack <s,..,v,..,t> by exploring search spaces from v //unpack <s,..,v,..,t> 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) { const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
//unpack [s,v) //unpack [s,v)
std::vector<NodeID> packed_s_v_path, packed_v_t_path; std::vector<NodeID> packed_s_v_path, packed_v_t_path;
@ -170,16 +209,16 @@ private:
super::UnpackPath(packed_s_v_path, unpackedPath); super::UnpackPath(packed_s_v_path, unpackedPath);
} }
inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath, inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path,
const int offset, const std::vector<NodeID> & packedShortestPath) { const int offset, const std::vector<NodeID> & packed_shortest_path) {
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues //compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
//only half-searches have to be done at this stage //only half-searches have to be done at this stage
super::_queryData.InitializeOrClearSecondThreadLocalStorage(); super::_queryData.InitializeOrClearSecondThreadLocalStorage();
HeapPtr & existingForwardHeap = super::_queryData.forwardHeap; QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap; QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2; QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2; QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2;
std::vector < NodeID > packed_s_v_path; std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path; std::vector < NodeID > packed_v_t_path;
@ -189,18 +228,18 @@ private:
NodeID s_v_middle = UINT_MAX; NodeID s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
newBackwardHeap->Insert(node.first, 0, node.first); newBackwardHeap.Insert(via_node, 0, via_node);
while (newBackwardHeap->Size() > 0) { while (0 < newBackwardHeap.Size()) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false); super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
} }
//compute path <v,..,t> by reusing backward search from node t //compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = UINT_MAX; NodeID v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX; int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap->Insert(node.first, 0, node.first); newForwardHeap.Insert(via_node, 0, via_node);
while (newForwardHeap->Size() > 0) { while (0 < newForwardHeap.Size() ) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true); 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) if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
return; return;
@ -211,35 +250,35 @@ private:
//partial unpacking, compute sharing //partial unpacking, compute sharing
//First partially unpack s-->v until paths deviate, note length of common path. //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) { 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] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) { if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} else { } 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(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; break;
} }
} }
} }
//traverse partially unpacked edge and note common prefix //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) { 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]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} }
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths //Second, partially unpack v-->t in reverse order until paths deviate and note lengths
int viaPathIndex = packed_v_t_path.size() - 1; 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 ) { for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
if (packed_v_t_path[viaPathIndex - 1] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) { if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} else { } 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(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; break;
} }
} }
@ -249,16 +288,16 @@ private:
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1; shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) { for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[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]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
} else { } else {
break; 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<NodeID> & packedShortestPath) { inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
std::vector<NodeID> packedAlternativePath; std::vector<NodeID> packedAlternativePath;
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath); super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
@ -270,8 +309,8 @@ private:
//compute forward sharing //compute forward sharing
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) { while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
// INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")"); // INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")");
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance; sharing += search_graph->GetEdgeData(edgeID).distance;
++aindex; ++aindex;
} }
@ -279,55 +318,65 @@ private:
int bindex = packedShortestPath.size()-1; int bindex = packedShortestPath.size()-1;
//compute backward sharing //compute backward sharing
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) { 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]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance; sharing += search_graph->GetEdgeData(edgeID).distance;
--aindex; --bindex; --aindex; --bindex;
} }
return sharing; return sharing;
} }
inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector<NodeID>& searchSpaceIntersection) const { template<bool forwardDirection>
const NodeID node = _forwardHeap->DeleteMin(); inline void AlternativeRoutingStep(
QueryHeap & _forward_heap,
QueryHeap & _reverse_heap,
NodeID *middle_node,
int *upper_bound_to_shortest_path_distance,
std::vector<NodeID>& searchSpaceIntersection,
std::vector<SearchSpaceEdge> & 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); search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node));
if(_backwardHeap->WasInserted(node) ){
if(_reverse_heap.WasInserted(node) ){
searchSpaceIntersection.push_back(node); searchSpaceIntersection.push_back(node);
const int newDistance = _backwardHeap->GetKey(node) + distance; const int newDistance = _reverse_heap.GetKey(node) + distance;
if(newDistance < *_upperbound ){ if(newDistance < *upper_bound_to_shortest_path_distance ){
if(newDistance>=0 ) { if(newDistance>=0 ) {
*middle = node; *middle_node = node;
*_upperbound = newDistance; *upper_bound_to_shortest_path_distance = newDistance;
} }
} }
} }
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON); for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
if(scaledDistance > *_upperbound){ const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
_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);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) { if(forwardDirectionFlag) {
const NodeID to = super::_queryData.graph->GetTarget(edge); const NodeID to = search_graph->GetTarget(edge);
const int edgeWeight = data.distance; const int edgeWeight = data.distance;
assert( edgeWeight > 0 ); assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight; const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage //New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap->WasInserted( to ) ) { if ( !_forward_heap.WasInserted( to ) ) {
_forwardHeap->Insert( to, toDistance, node ); _forward_heap.Insert( to, toDistance, node );
} }
//Found a shorter Path -> Update distance //Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap->GetKey( to ) ) { else if ( toDistance < _forward_heap.GetKey( to ) ) {
_forwardHeap->GetData( to ).parent = node; _forward_heap.GetData( to ).parent = node;
_forwardHeap->DecreaseKey( to, toDistance ); _forward_heap.DecreaseKey( to, toDistance );
//new parent //new parent
} }
} }
@ -335,16 +384,17 @@ private:
} }
//conduct T-Test //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_s_v_path;
std::vector < NodeID > packed_v_t_path; std::vector < NodeID > packed_v_t_path;
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
*s_v_middle = UINT_MAX; *s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX; int upperBoundFor_s_v_Path = INT_MAX;
//compute path <s,..,v> by reusing forward search from s //compute path <s,..,v> by reusing forward search from s
newBackwardHeap->Insert(candidate.node, 0, candidate.node); newBackwardHeap.Insert(candidate.node, 0, candidate.node);
while (newBackwardHeap->Size() > 0) { while (newBackwardHeap.Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false); super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
} }
@ -354,8 +404,8 @@ private:
//compute path <v,..,t> by reusing backward search from t //compute path <v,..,t> by reusing backward search from t
*v_t_middle = UINT_MAX; *v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX; int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap->Insert(candidate.node, 0, candidate.node); newForwardHeap.Insert(candidate.node, 0, candidate.node);
while (newForwardHeap->Size() > 0) { while (newForwardHeap.Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true); 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; const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
int unpackedUntilDistance = 0; int unpackedUntilDistance = 0;
std::stack<UnpackEdge> unpackStack; std::stack<SearchSpaceEdge> unpackStack;
//Traverse path s-->v //Traverse path s-->v
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) { 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]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance; int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i])); unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
} else { } else {
@ -386,17 +436,17 @@ private:
} }
while (!unpackStack.empty()) { while (!unpackStack.empty()) {
const UnpackEdge viaPathEdge = unpackStack.top(); const SearchSpaceEdge viaPathEdge = unpackStack.top();
unpackStack.pop(); 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) if(UINT_MAX == edgeIDInViaPath)
return false; return false;
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath); typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
bool IsViaEdgeShortCut = currentEdgeData.shortcut; bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) { if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id; const NodeID middleOfViaPath = currentEdgeData.id;
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second); typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).distance; int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
//attention: !unpacking in reverse! //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. //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) { if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
@ -416,8 +466,8 @@ private:
unpackedUntilDistance = 0; unpackedUntilDistance = 0;
//Traverse path s-->v //Traverse path s-->v
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) { 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]); typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance; int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1])); unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
} else { } else {
@ -427,17 +477,17 @@ private:
} }
while (!unpackStack.empty()) { while (!unpackStack.empty()) {
const UnpackEdge viaPathEdge = unpackStack.top(); const SearchSpaceEdge viaPathEdge = unpackStack.top();
unpackStack.pop(); 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) if(UINT_MAX == edgeIDInViaPath)
return false; 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; const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) { if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id; const NodeID middleOfViaPath = currentEdgeData.id;
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath); typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData( edgeIDOfFirstSegment).distance; 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. //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) { if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath)); unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
@ -454,19 +504,18 @@ private:
lengthOfPathT_Test_Path += unpackedUntilDistance; lengthOfPathT_Test_Path += unpackedUntilDistance;
//Run actual T-Test query and compare if distances equal. //Run actual T-Test query and compare if distances equal.
HeapPtr& forwardHeap = super::_queryData.forwardHeap3; QueryHeap& forwardHeap = *super::_queryData.forwardHeap3;
HeapPtr& backwardHeap = super::_queryData.backwardHeap3; QueryHeap& backwardHeap = *super::_queryData.backwardHeap3;
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
int _upperBound = INT_MAX; int _upperBound = INT_MAX;
NodeID middle = UINT_MAX; NodeID middle = UINT_MAX;
forwardHeap->Insert(s_P, 0, s_P); forwardHeap.Insert(s_P, 0, s_P);
backwardHeap->Insert(t_P, 0, t_P); backwardHeap.Insert(t_P, 0, t_P);
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath //exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while (forwardHeap->Size() + backwardHeap->Size() > 0) { while (forwardHeap.Size() + backwardHeap.Size() > 0) {
if (forwardHeap->Size() > 0) { if (forwardHeap.Size() > 0) {
super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true); super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true);
} }
if (backwardHeap->Size() > 0) { if (backwardHeap.Size() > 0) {
super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false); super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false);
} }
} }

View File

@ -23,43 +23,43 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef BASICROUTINGINTERFACE_H_ #ifndef BASICROUTINGINTERFACE_H_
#define BASICROUTINGINTERFACE_H_ #define BASICROUTINGINTERFACE_H_
#include <boost/noncopyable.hpp>
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include "../Plugins/RawRouteData.h" #include "../Plugins/RawRouteData.h"
#include "../Util/ContainerUtils.h"
template<class QueryDataT> template<class QueryDataT>
class BasicRoutingInterface { class BasicRoutingInterface : boost::noncopyable{
protected: protected:
QueryDataT & _queryData; QueryDataT & _queryData;
public: public:
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { } BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
virtual ~BasicRoutingInterface(){ }; virtual ~BasicRoutingInterface(){ };
inline void RoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const { 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 NodeID node = _forwardHeap.DeleteMin();
const int distance = _forwardHeap->GetKey(node); const int distance = _forwardHeap.GetKey(node);
// INFO((forwardDirection ? "[forw]" : "[back]") << " settled node " << node << " at distance " << distance); if(_backwardHeap.WasInserted(node) ){
if(_backwardHeap->WasInserted(node) ){ const int newDistance = _backwardHeap.GetKey(node) + distance;
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanned node " << node << " in both directions, upper bound: " << *_upperbound);
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound ){ if(newDistance < *_upperbound ){
if(newDistance>=0 ) { if(newDistance>=0 ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> node " << node << " is new middle at total distance " << newDistance);
*middle = node; *middle = node;
*_upperbound = newDistance; *_upperbound = newDistance;
} else { } else {
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> ignored " << node << " as new middle at total distance " << newDistance);
} }
} }
} }
if(distance-edgeBasedOffset > *_upperbound){ if(distance-edgeBasedOffset > *_upperbound){
_forwardHeap->DeleteAll(); _forwardHeap.DeleteAll();
return; 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); const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward; bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) { if(backwardDirectionFlag) {
@ -68,16 +68,15 @@ public:
assert( edgeWeight > 0 ); assert( edgeWeight > 0 );
//Stalling if(_forwardHeap.WasInserted( to )) {
if(_forwardHeap->WasInserted( to )) { if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
return; 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); const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) { if(forwardDirectionFlag) {
@ -89,23 +88,20 @@ public:
const int toDistance = distance + edgeWeight; const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage //New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap->WasInserted( to ) ) { if ( !_forwardHeap.WasInserted( to ) ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanning edge (" << node << "," << to << ") with distance " << toDistance << ", edge length: " << data.distance); _forwardHeap.Insert( to, toDistance, node );
_forwardHeap->Insert( to, toDistance, node );
} }
//Found a shorter Path -> Update distance //Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap->GetKey( to ) ) { 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->GetData( to ).parent = node; _forwardHeap.DecreaseKey( to, toDistance );
_forwardHeap->DecreaseKey( to, toDistance );
//new parent //new parent
} }
} }
} }
} }
inline void UnpackPath(std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const { inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const unsigned sizeOfPackedPath = packedPath.size(); const unsigned sizeOfPackedPath = packedPath.size();
std::stack<std::pair<NodeID, NodeID> > recursionStack; std::stack<std::pair<NodeID, NodeID> > recursionStack;
@ -118,15 +114,12 @@ public:
while(!recursionStack.empty()) { while(!recursionStack.empty()) {
edge = recursionStack.top(); edge = recursionStack.top();
recursionStack.pop(); recursionStack.pop();
// INFO("Unpacking edge (" << edge.first << "," << edge.second << ")");
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID; typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX; int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){ 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; 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){ if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
// INFO("1smallest " << eit << ", " << weight);
smallestEdge = eit; smallestEdge = eit;
smallestWeight = weight; smallestWeight = weight;
} }
@ -135,9 +128,7 @@ public:
if(smallestEdge == SPECIAL_EDGEID){ if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){ 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; 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){ if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
// INFO("2smallest " << eit << ", " << weight);
smallestEdge = eit; smallestEdge = eit;
smallestWeight = weight; smallestWeight = weight;
} }
@ -159,7 +150,6 @@ public:
} }
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const { inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
std::stack<std::pair<NodeID, NodeID> > recursionStack; std::stack<std::pair<NodeID, NodeID> > recursionStack;
recursionStack.push(std::make_pair(s,t)); recursionStack.push(std::make_pair(s,t));
@ -193,7 +183,6 @@ public:
if(ed.shortcut) {//unpack if(ed.shortcut) {//unpack
const NodeID middle = ed.id; const NodeID middle = ed.id;
//again, we need to this in reversed order //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(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle)); recursionStack.push(std::make_pair(edge.first, middle));
} else { } else {
@ -204,22 +193,29 @@ public:
unpackedPath.push_back(t); unpackedPath.push_back(t);
} }
inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) { inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
NodeID pathNode = middle; NodeID pathNode = middle;
while(pathNode != _fHeap->GetData(pathNode).parent) { while(pathNode != _fHeap.GetData(pathNode).parent) {
pathNode = _fHeap->GetData(pathNode).parent; pathNode = _fHeap.GetData(pathNode).parent;
packedPath.push_back(pathNode); packedPath.push_back(pathNode);
} }
std::reverse(packedPath.begin(), packedPath.end()); std::reverse(packedPath.begin(), packedPath.end());
packedPath.push_back(middle); packedPath.push_back(middle);
pathNode = middle; pathNode = middle;
while (pathNode != _bHeap->GetData(pathNode).parent){ while (pathNode != _bHeap.GetData(pathNode).parent){
pathNode = _bHeap->GetData(pathNode).parent; pathNode = _bHeap.GetData(pathNode).parent;
packedPath.push_back(pathNode); packedPath.push_back(pathNode);
} }
} }
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
NodeID pathNode = middle;
while(pathNode != search_heap.GetData(pathNode).parent) {
pathNode = search_heap.GetData(pathNode).parent;
packed_path.push_back(pathNode);
}
}
}; };

View File

@ -28,13 +28,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
template<class QueryDataT> template<class QueryDataT>
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{ class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super; typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::QueryHeap QueryHeap;
public: public:
ShortestPathRouting(QueryDataT & qd) : super(qd) {} ShortestPathRouting( QueryDataT & qd) : super(qd) {}
~ShortestPathRouting() {} ~ShortestPathRouting() {}
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) { void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) { BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) { if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX; rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return; return;
@ -43,77 +44,65 @@ public:
int distance1 = 0; int distance1 = 0;
int distance2 = 0; int distance2 = 0;
bool searchFrom1stStartNode(true); bool searchFrom1stStartNode = true;
bool searchFrom2ndStartNode(true); bool searchFrom2ndStartNode = true;
NodeID middle1 = ( NodeID ) UINT_MAX; NodeID middle1 = UINT_MAX;
NodeID middle2 = ( NodeID ) UINT_MAX; NodeID middle2 = UINT_MAX;
std::vector<NodeID> packedPath1; std::vector<NodeID> packedPath1;
std::vector<NodeID> packedPath2; std::vector<NodeID> packedPath2;
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap; super::_queryData.InitializeOrClearFirstThreadLocalStorage();
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap; super::_queryData.InitializeOrClearSecondThreadLocalStorage();
typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
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. //Get distance to next pair of target nodes.
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) { BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
super::_queryData.InitializeOrClearFirstThreadLocalStorage(); forwardHeap.Clear(); forwardHeap2.Clear();
super::_queryData.InitializeOrClearSecondThreadLocalStorage(); backwardHeap.Clear(); backwardHeap2.Clear();
int _localUpperbound1 = INT_MAX; int _localUpperbound1 = INT_MAX;
int _localUpperbound2 = INT_MAX; int _localUpperbound2 = INT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances. //insert new starting nodes into forward heap, adjusted by previous distances.
if(searchFrom1stStartNode) { if(searchFrom1stStartNode) {
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
forwardHeap2->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");
} }
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) { if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); 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); 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");
} }
// backwardHeap->Clear();
// backwardHeap2->Clear();
//insert new backward nodes into backward heap, unadjusted. //insert new backward nodes into backward heap, unadjusted.
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); backwardHeap.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("1) back insert " << phantomNodePair.targetPhantom.edgeBasedNode << " with weight " << phantomNodePair.targetPhantom.weight1);
if(phantomNodePair.targetPhantom.isBidirected() ) { 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) ; 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) ; offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ;
//run two-Target Dijkstra routing step. //run two-Target Dijkstra routing step.
while(forwardHeap->Size() + backwardHeap->Size() > 0){ while(forwardHeap.Size() + backwardHeap.Size() > 0){
if(forwardHeap->Size() > 0){ if(forwardHeap.Size() > 0){
super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true); 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); super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false);
} }
} }
if(backwardHeap2->Size() > 0) { if(backwardHeap2.Size() > 0) {
while(forwardHeap2->Size() + backwardHeap2->Size() > 0){ while(forwardHeap2.Size() + backwardHeap2.Size() > 0){
if(forwardHeap2->Size() > 0){ if(forwardHeap2.Size() > 0){
super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true); 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); 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? //No path found for both target nodes?
if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) { if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) {
@ -122,46 +111,35 @@ public:
} }
if(UINT_MAX == middle1) { if(UINT_MAX == middle1) {
searchFrom1stStartNode = false; searchFrom1stStartNode = false;
// INFO("Next Search will not start from 1st");
} else { } else {
// INFO("Next Search will start from 1st");
searchFrom1stStartNode = true; searchFrom1stStartNode = true;
} }
if(UINT_MAX == middle2) { if(UINT_MAX == middle2) {
searchFrom2ndStartNode = false; searchFrom2ndStartNode = false;
// INFO("Next Search will not start from 2nd");
} else { } else {
searchFrom2ndStartNode = true; searchFrom2ndStartNode = true;
// INFO("Next Search will start from 2nd");
} }
//Was at most one of the two paths not found? //Was at most one of the two paths not found?
assert(!(INT_MAX == distance1 && INT_MAX == distance2)); assert(!(INT_MAX == distance1 && INT_MAX == distance2));
// INFO("middle1: " << middle1);
//Unpack paths if they exist //Unpack paths if they exist
std::vector<NodeID> temporaryPackedPath1; std::vector<NodeID> temporaryPackedPath1;
std::vector<NodeID> temporaryPackedPath2; std::vector<NodeID> temporaryPackedPath2;
if(INT_MAX != _localUpperbound1) { if(INT_MAX != _localUpperbound1) {
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1); super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1);
// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) );
} }
// INFO("middle2: " << middle2);
if(INT_MAX != _localUpperbound2) { if(INT_MAX != _localUpperbound2) {
super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2); 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 one of the paths was not found, replace it with the other one.
if(0 == temporaryPackedPath1.size()) { if(0 == temporaryPackedPath1.size()) {
// INFO("Deleting path 1");
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end()); temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
_localUpperbound1 = _localUpperbound2; _localUpperbound1 = _localUpperbound2;
} }
if(0 == temporaryPackedPath2.size()) { if(0 == temporaryPackedPath2.size()) {
// INFO("Deleting path 2");
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end()); temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
_localUpperbound2 = _localUpperbound1; _localUpperbound2 = _localUpperbound1;
} }
@ -170,28 +148,21 @@ public:
//Plug paths together, s.t. end of packed path is begin of temporary packed path //Plug paths together, s.t. end of packed path is begin of temporary packed path
if(0 < packedPath1.size() && 0 < packedPath2.size() ) { if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
// INFO("Both paths are non-empty");
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) { 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. //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)) ); assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) { if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
// INFO("Deleting packedPath2 that ends with " << *(packedPath2.end()-1) << ", other ends with " << *(packedPath1.end()-1));
packedPath2.clear(); packedPath2.clear();
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end()); packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
distance2 = distance1; distance2 = distance1;
// INFO("packedPath2 now ends with " << *(packedPath2.end()-1));
} else { } else {
// INFO("Deleting path1 that ends with " << *(packedPath1.end()-1) << ", other ends with " << *(packedPath2.end()-1));
packedPath1.clear(); packedPath1.clear();
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end()); packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
distance1 = distance2; distance1 = distance2;
// INFO("Path1 now ends with " << *(packedPath1.end()-1));
} }
} else { } else {
//packed paths 1 and 2 may need to switch. //packed paths 1 and 2 may need to switch.
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) { if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
// INFO("Switching");
packedPath1.swap(packedPath2); packedPath1.swap(packedPath2);
std::swap(distance1, distance2); std::swap(distance1, distance2);
} }
@ -201,61 +172,24 @@ public:
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end()); packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) { 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(); NodeID lastNodeID = packedPath2.back();
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1); searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode); 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; distance1 += _localUpperbound1;
distance2 += _localUpperbound2; distance2 += _localUpperbound2;
} }
// INFO("length path1: " << distance1); if(distance1 > distance2){
// 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 {
std::swap(packedPath1, packedPath2); 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); super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2); rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
// INFO("Found via route with distance " << std::min(distance1, distance2));
return; return;
} }
private:
template<class ContainerT>
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_ */ #endif /* SHORTESTPATHROUTING_H_ */