Weight-ifies alternatives related code-paths

This commit is contained in:
Daniel J. Hofmann 2017-05-11 16:36:37 +02:00
parent f8002480c2
commit e12c7756d9
6 changed files with 73 additions and 81 deletions

View File

@ -16,8 +16,6 @@ namespace osrm
namespace engine
{
const constexpr unsigned INVALID_EXIT_NR = 0;
struct PathData
{
// id of via node of the turn
@ -55,22 +53,17 @@ struct InternalRouteResult
std::vector<bool> target_traversed_in_reverse;
std::vector<bool> alt_source_traversed_in_reverse;
std::vector<bool> alt_target_traversed_in_reverse;
int shortest_path_length;
int alternative_path_length;
EdgeWeight shortest_path_weight = INVALID_EDGE_WEIGHT;
EdgeWeight alternative_path_weight = INVALID_EDGE_WEIGHT;
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_length; }
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_weight; }
bool has_alternative() const { return INVALID_EDGE_WEIGHT != alternative_path_length; }
bool has_alternative() const { return INVALID_EDGE_WEIGHT != alternative_path_weight; }
bool is_via_leg(const std::size_t leg) const
{
return (leg != unpacked_path_segments.size() - 1);
}
InternalRouteResult()
: shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT)
{
}
};
}
}

View File

@ -235,7 +235,7 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
// phantom nodes for possible uturns
sub_routes[index] =
algorithms.ShortestPathSearch(sub_routes[index].segment_end_coordinates, {false});
BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT);
BOOST_ASSERT(sub_routes[index].shortest_path_weight != INVALID_EDGE_WEIGHT);
}
api::MatchAPI match_api{facade, parameters, tidied};

View File

@ -86,7 +86,7 @@ InternalRouteResult TripPlugin::ComputeRoute(const RoutingAlgorithmsInterface &a
}
min_route = algorithms.ShortestPathSearch(min_route.segment_end_coordinates, {false});
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
BOOST_ASSERT_MSG(min_route.shortest_path_weight < INVALID_EDGE_WEIGHT, "unroutable route");
return min_route;
}

View File

@ -33,18 +33,18 @@ using SearchSpaceEdge = std::pair<NodeID, NodeID>;
struct RankedCandidateNode
{
RankedCandidateNode(const NodeID node, const int length, const int sharing)
: node(node), length(length), sharing(sharing)
RankedCandidateNode(const NodeID node, const EdgeWeight weight, const EdgeWeight sharing)
: node(node), weight(weight), sharing(sharing)
{
}
NodeID node;
int length;
int sharing;
EdgeWeight weight;
EdgeWeight sharing;
bool operator<(const RankedCandidateNode &other) const
{
return (2 * length + sharing) < (2 * other.length + other.sharing);
return (2 * weight + sharing) < (2 * other.weight + other.sharing);
}
};
@ -153,12 +153,12 @@ void retrievePackedAlternatePath(const QueryHeap &forward_heap1,
// 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
void computeLengthAndSharingOfViaPath(
void computeWeightAndSharingOfViaPath(
SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID via_node,
int *real_length_of_via_path,
int *sharing_of_via_path,
EdgeWeight *real_weight_of_via_path,
EdgeWeight *sharing_of_via_path,
const std::vector<NodeID> &packed_shortest_path,
const EdgeWeight min_edge_offset)
{
@ -176,7 +176,7 @@ void computeLengthAndSharingOfViaPath(
std::vector<NodeID> partially_unpacked_via_path;
NodeID s_v_middle = SPECIAL_NODEID;
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
EdgeWeight upper_bound_s_v_path_weight = INVALID_EDGE_WEIGHT;
new_reverse_heap.Insert(via_node, 0, via_node);
// compute path <s,..,v> by reusing forward search from s
while (!new_reverse_heap.Empty())
@ -185,14 +185,14 @@ void computeLengthAndSharingOfViaPath(
new_reverse_heap,
existing_forward_heap,
s_v_middle,
upper_bound_s_v_path_length,
upper_bound_s_v_path_weight,
min_edge_offset,
DO_NOT_FORCE_LOOPS,
DO_NOT_FORCE_LOOPS);
}
// compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = SPECIAL_NODEID;
int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT;
EdgeWeight upper_bound_of_v_t_path_weight = INVALID_EDGE_WEIGHT;
new_forward_heap.Insert(via_node, 0, via_node);
while (!new_forward_heap.Empty())
{
@ -200,12 +200,12 @@ void computeLengthAndSharingOfViaPath(
new_forward_heap,
existing_reverse_heap,
v_t_middle,
upper_bound_of_v_t_path_length,
upper_bound_of_v_t_path_weight,
min_edge_offset,
DO_NOT_FORCE_LOOPS,
DO_NOT_FORCE_LOOPS);
}
*real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
*real_weight_of_via_path = upper_bound_s_v_path_weight + upper_bound_of_v_t_path_weight;
if (SPECIAL_NODEID == s_v_middle || SPECIAL_NODEID == v_t_middle)
{
@ -326,8 +326,8 @@ bool viaNodeCandidatePassesTTest(
QueryHeap &new_forward_heap,
QueryHeap &new_reverse_heap,
const RankedCandidateNode &candidate,
const int length_of_shortest_path,
int *length_of_via_path,
const EdgeWeight weight_of_shortest_path,
EdgeWeight *weight_of_via_path,
NodeID *s_v_middle,
NodeID *v_t_middle,
const EdgeWeight min_edge_offset)
@ -338,7 +338,7 @@ bool viaNodeCandidatePassesTTest(
std::vector<NodeID> packed_v_t_path;
*s_v_middle = SPECIAL_NODEID;
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
EdgeWeight upper_bound_s_v_path_weight = INVALID_EDGE_WEIGHT;
// compute path <s,..,v> by reusing forward search from s
new_reverse_heap.Insert(candidate.node, 0, candidate.node);
while (new_reverse_heap.Size() > 0)
@ -347,20 +347,20 @@ bool viaNodeCandidatePassesTTest(
new_reverse_heap,
existing_forward_heap,
*s_v_middle,
upper_bound_s_v_path_length,
upper_bound_s_v_path_weight,
min_edge_offset,
DO_NOT_FORCE_LOOPS,
DO_NOT_FORCE_LOOPS);
}
if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length)
if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_weight)
{
return false;
}
// compute path <v,..,t> by reusing backward search from t
*v_t_middle = SPECIAL_NODEID;
int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT;
EdgeWeight upper_bound_of_v_t_path_weight = INVALID_EDGE_WEIGHT;
new_forward_heap.Insert(candidate.node, 0, candidate.node);
while (new_forward_heap.Size() > 0)
{
@ -368,18 +368,18 @@ bool viaNodeCandidatePassesTTest(
new_forward_heap,
existing_reverse_heap,
*v_t_middle,
upper_bound_of_v_t_path_length,
upper_bound_of_v_t_path_weight,
min_edge_offset,
DO_NOT_FORCE_LOOPS,
DO_NOT_FORCE_LOOPS);
}
if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length)
if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_weight)
{
return false;
}
*length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
*weight_of_via_path = upper_bound_s_v_path_weight + upper_bound_of_v_t_path_weight;
// retrieve packed paths
ch::retrievePackedPathFromHeap(
@ -398,7 +398,8 @@ bool viaNodeCandidatePassesTTest(
{
return false;
}
const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path);
const EdgeWeight T_threshold =
static_cast<EdgeWeight>(VIAPATH_EPSILON * weight_of_shortest_path);
EdgeWeight unpacked_until_weight = 0;
std::stack<SearchSpaceEdge> unpack_stack;
@ -407,14 +408,14 @@ bool viaNodeCandidatePassesTTest(
{
const EdgeID current_edge_id =
facade.FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
const EdgeWeight length_of_current_edge = facade.GetEdgeData(current_edge_id).weight;
if ((length_of_current_edge + unpacked_until_weight) >= T_threshold)
const EdgeWeight weight_of_current_edge = facade.GetEdgeData(current_edge_id).weight;
if ((weight_of_current_edge + unpacked_until_weight) >= T_threshold)
{
unpack_stack.emplace(packed_s_v_path[i - 1], packed_s_v_path[i]);
}
else
{
unpacked_until_weight += length_of_current_edge;
unpacked_until_weight += weight_of_current_edge;
s_P = packed_s_v_path[i - 1];
}
}
@ -438,17 +439,17 @@ bool viaNodeCandidatePassesTTest(
const NodeID via_path_middle_node_id = current_edge_data.turn_id;
const EdgeID second_segment_edge_id =
facade.FindEdgeInEitherDirection(via_path_middle_node_id, via_path_edge.second);
const int second_segment_length = facade.GetEdgeData(second_segment_edge_id).weight;
const auto second_segment_weight = facade.GetEdgeData(second_segment_edge_id).weight;
// 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 weight of second one.
if (unpacked_until_weight + second_segment_length >= T_threshold)
if (unpacked_until_weight + second_segment_weight >= T_threshold)
{
unpack_stack.emplace(via_path_middle_node_id, via_path_edge.second);
}
else
{
unpacked_until_weight += second_segment_length;
unpacked_until_weight += second_segment_weight;
unpack_stack.emplace(via_path_edge.first, via_path_middle_node_id);
}
}
@ -460,7 +461,7 @@ bool viaNodeCandidatePassesTTest(
}
}
EdgeWeight t_test_path_length = unpacked_until_weight;
EdgeWeight t_test_path_weight = unpacked_until_weight;
unpacked_until_weight = 0;
// Traverse path s-->v
BOOST_ASSERT(!packed_v_t_path.empty());
@ -470,14 +471,14 @@ bool viaNodeCandidatePassesTTest(
{
const EdgeID edgeID =
facade.FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
int length_of_current_edge = facade.GetEdgeData(edgeID).weight;
if (length_of_current_edge + unpacked_until_weight >= T_threshold)
auto weight_of_current_edge = facade.GetEdgeData(edgeID).weight;
if (weight_of_current_edge + unpacked_until_weight >= T_threshold)
{
unpack_stack.emplace(packed_v_t_path[i], packed_v_t_path[i + 1]);
}
else
{
unpacked_until_weight += length_of_current_edge;
unpacked_until_weight += weight_of_current_edge;
t_P = packed_v_t_path[i + 1];
}
}
@ -500,16 +501,16 @@ bool viaNodeCandidatePassesTTest(
const NodeID middleOfViaPath = current_edge_data.turn_id;
EdgeID edgeIDOfFirstSegment =
facade.FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath);
int lengthOfFirstSegment = facade.GetEdgeData(edgeIDOfFirstSegment).weight;
auto weightOfFirstSegment = facade.GetEdgeData(edgeIDOfFirstSegment).weight;
// 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 weight of first one.
if (unpacked_until_weight + lengthOfFirstSegment >= T_threshold)
if (unpacked_until_weight + weightOfFirstSegment >= T_threshold)
{
unpack_stack.emplace(via_path_edge.first, middleOfViaPath);
}
else
{
unpacked_until_weight += lengthOfFirstSegment;
unpacked_until_weight += weightOfFirstSegment;
unpack_stack.emplace(middleOfViaPath, via_path_edge.second);
}
}
@ -521,7 +522,7 @@ bool viaNodeCandidatePassesTTest(
}
}
t_test_path_length += unpacked_until_weight;
t_test_path_weight += unpacked_until_weight;
// Run actual T-Test query and compare if weight equal.
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes());
@ -558,7 +559,7 @@ bool viaNodeCandidatePassesTTest(
DO_NOT_FORCE_LOOPS);
}
}
return (upper_bound <= t_test_path_length);
return (upper_bound <= t_test_path_weight);
}
}
@ -596,7 +597,7 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
insertNodesInHeaps(forward_heap1, reverse_heap1, phantom_node_pair);
// search from s and t till new_min/(1+epsilon) > length_of_shortest_path
// search from s and t till new_min/(1+epsilon) > weight_of_shortest_path
while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
{
if (0 < forward_heap1.Size())
@ -658,8 +659,8 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
nodes_in_path.insert(middle_node);
nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end());
std::unordered_map<NodeID, int> approximated_forward_sharing;
std::unordered_map<NodeID, int> approximated_reverse_sharing;
std::unordered_map<NodeID, EdgeWeight> approximated_forward_sharing;
std::unordered_map<NodeID, EdgeWeight> approximated_reverse_sharing;
// sweep over search space, compute forward sharing for each current edge (u,v)
for (const SearchSpaceEdge &current_edge : forward_search_space)
@ -712,23 +713,24 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
if (node == middle_node)
continue;
const auto fwd_iterator = approximated_forward_sharing.find(node);
const int fwd_sharing =
const EdgeWeight fwd_sharing =
(fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
const auto rev_iterator = approximated_reverse_sharing.find(node);
const int rev_sharing =
const EdgeWeight rev_sharing =
(rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
const int approximated_sharing = fwd_sharing + rev_sharing;
const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
const bool length_passes =
(approximated_length < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON));
const EdgeWeight approximated_sharing = fwd_sharing + rev_sharing;
const EdgeWeight approximated_weight =
forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
const bool weight_passes =
(approximated_weight < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON));
const bool sharing_passes =
(approximated_sharing <= upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
const bool stretch_passes =
(approximated_length - approximated_sharing) <
(approximated_weight - approximated_sharing) <
((1. + VIAPATH_ALPHA) * (upper_bound_to_shortest_path_weight - approximated_sharing));
if (length_passes && sharing_passes && stretch_passes)
if (weight_passes && sharing_passes && stretch_passes)
{
preselected_node_list.emplace_back(node);
}
@ -747,26 +749,26 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
// prioritizing via nodes for deep inspection
for (const NodeID node : preselected_node_list)
{
int length_of_via_path = 0, sharing_of_via_path = 0;
computeLengthAndSharingOfViaPath(engine_working_data,
EdgeWeight weight_of_via_path = 0, sharing_of_via_path = 0;
computeWeightAndSharingOfViaPath(engine_working_data,
facade,
node,
&length_of_via_path,
&weight_of_via_path,
&sharing_of_via_path,
packed_shortest_path,
min_edge_offset);
const int maximum_allowed_sharing =
static_cast<int>(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
const EdgeWeight maximum_allowed_sharing =
static_cast<EdgeWeight>(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
if (sharing_of_via_path <= maximum_allowed_sharing &&
length_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON))
weight_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON))
{
ranked_candidates_list.emplace_back(node, length_of_via_path, sharing_of_via_path);
ranked_candidates_list.emplace_back(node, weight_of_via_path, sharing_of_via_path);
}
}
std::sort(ranked_candidates_list.begin(), ranked_candidates_list.end());
NodeID selected_via_node = SPECIAL_NODEID;
int length_of_via_path = INVALID_EDGE_WEIGHT;
EdgeWeight weight_of_via_path = INVALID_EDGE_WEIGHT;
NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID;
for (const RankedCandidateNode &candidate : ranked_candidates_list)
{
@ -778,7 +780,7 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
reverse_heap2,
candidate,
upper_bound_to_shortest_path_weight,
&length_of_via_path,
&weight_of_via_path,
&s_v_middle,
&v_t_middle,
min_edge_offset))
@ -808,7 +810,7 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
phantom_node_pair,
// -- unpacked output
raw_route_data.unpacked_path_segments.front());
raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight;
raw_route_data.shortest_path_weight = upper_bound_to_shortest_path_weight;
}
if (SPECIAL_NODEID != selected_via_node)
@ -837,11 +839,11 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
phantom_node_pair,
raw_route_data.unpacked_alternative);
raw_route_data.alternative_path_length = length_of_via_path;
raw_route_data.alternative_path_weight = weight_of_via_path;
}
else
{
BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT);
BOOST_ASSERT(raw_route_data.alternative_path_weight == INVALID_EDGE_WEIGHT);
}
return raw_route_data;

View File

@ -21,15 +21,14 @@ extractRoute(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &f
{
InternalRouteResult raw_route_data;
raw_route_data.segment_end_coordinates = {phantom_nodes};
// No path found for both target nodes?
if (INVALID_EDGE_WEIGHT == weight)
{
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
return raw_route_data;
}
raw_route_data.shortest_path_length = weight;
raw_route_data.shortest_path_weight = weight;
raw_route_data.unpacked_path_segments.resize(1);
raw_route_data.source_traversed_in_reverse.push_back(
(unpacked_nodes.front() != phantom_nodes.source_phantom.forward_segment_id.id));

View File

@ -185,12 +185,12 @@ void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<NodeID> &total_packed_path,
const std::vector<std::size_t> &packed_leg_begin,
const int shortest_path_length,
const EdgeWeight shortest_path_weight,
InternalRouteResult &raw_route_data)
{
raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1);
raw_route_data.shortest_path_length = shortest_path_length;
raw_route_data.shortest_path_weight = shortest_path_weight;
for (const auto current_leg : util::irange<std::size_t>(0UL, packed_leg_begin.size() - 1))
{
@ -331,8 +331,6 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
if ((INVALID_EDGE_WEIGHT == new_total_weight_to_forward) &&
(INVALID_EDGE_WEIGHT == new_total_weight_to_reverse))
{
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
return raw_route_data;
}