Refactoring routing algorithms, alternative computation hastened by
sweeping the search space only once. Should fix #572
This commit is contained in:
parent
7d9d0878de
commit
2dbae6ce51
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user