Refactor routeStep
This commit is contained in:
parent
7da86b5984
commit
30ff0fa977
@ -33,6 +33,68 @@ namespace engine
|
|||||||
|
|
||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
static constexpr bool FORWARD_DIRECTION = true;
|
||||||
|
static constexpr bool REVERSE_DIRECTION = false;
|
||||||
|
|
||||||
|
// Stalling
|
||||||
|
template <bool DIRECTION, typename HeapT>
|
||||||
|
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const NodeID node,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
HeapT &query_heap)
|
||||||
|
{
|
||||||
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
|
if (DIRECTION == REVERSE_DIRECTION ? data.forward : data.backward)
|
||||||
|
{
|
||||||
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
if (query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
if (query_heap.GetKey(to) + edge_weight < weight)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool DIRECTION>
|
||||||
|
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const NodeID node,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
SearchEngineData::QueryHeap &heap)
|
||||||
|
{
|
||||||
|
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
|
{
|
||||||
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
|
||||||
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if (!heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
heap.Insert(to, to_weight, node);
|
||||||
|
}
|
||||||
|
// Found a shorter Path -> Update weight
|
||||||
|
else if (to_weight < heap.GetKey(to))
|
||||||
|
{
|
||||||
|
// new parent
|
||||||
|
heap.GetData(to).parent = node;
|
||||||
|
heap.DecreaseKey(to, to_weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
min_edge_offset is needed in case we use multiple
|
min_edge_offset is needed in case we use multiple
|
||||||
@ -63,16 +125,81 @@ using edges (y, a) with weight -100, (y, b) with weight 0 and,
|
|||||||
Since we are dealing with a graph that contains _negative_ edges,
|
Since we are dealing with a graph that contains _negative_ edges,
|
||||||
we need to add an offset to the termination criterion.
|
we need to add an offset to the termination criterion.
|
||||||
*/
|
*/
|
||||||
|
static constexpr bool ENABLE_STALLING = true;
|
||||||
|
static constexpr bool DISABLE_STALLING = false;
|
||||||
|
static constexpr bool DO_NOT_FORCE_LOOPS = false;
|
||||||
|
template<bool DIRECTION, bool STALLING=ENABLE_STALLING>
|
||||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
NodeID &middle_node_id,
|
NodeID &middle_node_id,
|
||||||
std::int32_t &upper_bound,
|
EdgeWeight &upper_bound,
|
||||||
std::int32_t min_edge_offset,
|
EdgeWeight min_edge_offset,
|
||||||
const bool forward_direction,
|
|
||||||
const bool stalling,
|
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse);
|
const bool force_loop_reverse)
|
||||||
|
{
|
||||||
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
|
const EdgeWeight weight = forward_heap.GetKey(node);
|
||||||
|
|
||||||
|
if (reverse_heap.WasInserted(node))
|
||||||
|
{
|
||||||
|
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
||||||
|
if (new_weight < upper_bound)
|
||||||
|
{
|
||||||
|
// if loops are forced, they are so at the source
|
||||||
|
if ((force_loop_forward && forward_heap.GetData(node).parent == node) ||
|
||||||
|
(force_loop_reverse && reverse_heap.GetData(node).parent == node) ||
|
||||||
|
// in this case we are looking at a bi-directional way where the source
|
||||||
|
// and target phantom are on the same edge based node
|
||||||
|
new_weight < 0)
|
||||||
|
{
|
||||||
|
// check whether there is a loop present at the node
|
||||||
|
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
|
{
|
||||||
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
if (to == node)
|
||||||
|
{
|
||||||
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
const EdgeWeight loop_weight = new_weight + edge_weight;
|
||||||
|
if (loop_weight >= 0 && loop_weight < upper_bound)
|
||||||
|
{
|
||||||
|
middle_node_id = node;
|
||||||
|
upper_bound = loop_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(new_weight >= 0);
|
||||||
|
|
||||||
|
middle_node_id = node;
|
||||||
|
upper_bound = new_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we don't terminate too early if we initialize the weight
|
||||||
|
// for the nodes in the forward heap with the forward/reverse offset
|
||||||
|
BOOST_ASSERT(min_edge_offset <= 0);
|
||||||
|
if (weight + min_edge_offset > upper_bound)
|
||||||
|
{
|
||||||
|
forward_heap.DeleteAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stalling
|
||||||
|
if (STALLING && stallAtNode<DIRECTION>(facade, node, weight, forward_heap))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
relaxOutgoingEdges<DIRECTION>(facade, node, weight, forward_heap);
|
||||||
|
}
|
||||||
|
|
||||||
template <bool UseDuration>
|
template <bool UseDuration>
|
||||||
EdgeWeight
|
EdgeWeight
|
||||||
|
@ -47,7 +47,7 @@ struct RankedCandidateNode
|
|||||||
};
|
};
|
||||||
|
|
||||||
// todo: reorder parameters
|
// todo: reorder parameters
|
||||||
template <bool is_forward_directed>
|
template <bool DIRECTION>
|
||||||
void alternativeRoutingStep(
|
void alternativeRoutingStep(
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
QueryHeap &heap1,
|
QueryHeap &heap1,
|
||||||
@ -58,8 +58,8 @@ void alternativeRoutingStep(
|
|||||||
std::vector<SearchSpaceEdge> &search_space,
|
std::vector<SearchSpaceEdge> &search_space,
|
||||||
const EdgeWeight min_edge_offset)
|
const EdgeWeight min_edge_offset)
|
||||||
{
|
{
|
||||||
QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2);
|
QueryHeap &forward_heap = DIRECTION == FORWARD_DIRECTION ? heap1 : heap2;
|
||||||
QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1);
|
QueryHeap &reverse_heap = DIRECTION == FORWARD_DIRECTION ? heap2 : heap1;
|
||||||
|
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const EdgeWeight weight = forward_heap.GetKey(node);
|
const EdgeWeight weight = forward_heap.GetKey(node);
|
||||||
@ -104,8 +104,7 @@ void alternativeRoutingStep(
|
|||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
const bool edge_is_forward_directed = (is_forward_directed ? data.forward : data.backward);
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
if (edge_is_forward_directed)
|
|
||||||
{
|
{
|
||||||
const NodeID to = facade.GetTarget(edge);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
@ -179,20 +178,16 @@ void computeLengthAndSharingOfViaPath(
|
|||||||
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
|
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
|
||||||
new_reverse_heap.Insert(via_node, 0, via_node);
|
new_reverse_heap.Insert(via_node, 0, via_node);
|
||||||
// compute path <s,..,v> by reusing forward search from s
|
// compute path <s,..,v> by reusing forward search from s
|
||||||
const bool constexpr STALLING_ENABLED = true;
|
|
||||||
const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
|
||||||
while (!new_reverse_heap.Empty())
|
while (!new_reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<REVERSE_DIRECTION>(facade,
|
||||||
new_reverse_heap,
|
new_reverse_heap,
|
||||||
existing_forward_heap,
|
existing_forward_heap,
|
||||||
s_v_middle,
|
s_v_middle,
|
||||||
upper_bound_s_v_path_length,
|
upper_bound_s_v_path_length,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
false,
|
DO_NOT_FORCE_LOOPS,
|
||||||
STALLING_ENABLED,
|
DO_NOT_FORCE_LOOPS);
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
DO_NOT_FORCE_LOOPS);
|
|
||||||
}
|
}
|
||||||
// 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 = SPECIAL_NODEID;
|
NodeID v_t_middle = SPECIAL_NODEID;
|
||||||
@ -200,16 +195,14 @@ void computeLengthAndSharingOfViaPath(
|
|||||||
new_forward_heap.Insert(via_node, 0, via_node);
|
new_forward_heap.Insert(via_node, 0, via_node);
|
||||||
while (!new_forward_heap.Empty())
|
while (!new_forward_heap.Empty())
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<FORWARD_DIRECTION>(facade,
|
||||||
new_forward_heap,
|
new_forward_heap,
|
||||||
existing_reverse_heap,
|
existing_reverse_heap,
|
||||||
v_t_middle,
|
v_t_middle,
|
||||||
upper_bound_of_v_t_path_length,
|
upper_bound_of_v_t_path_length,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
true,
|
DO_NOT_FORCE_LOOPS,
|
||||||
STALLING_ENABLED,
|
DO_NOT_FORCE_LOOPS);
|
||||||
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_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
|
||||||
|
|
||||||
@ -347,20 +340,16 @@ bool viaNodeCandidatePassesTTest(
|
|||||||
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
|
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
|
||||||
// compute path <s,..,v> by reusing forward search from s
|
// compute path <s,..,v> by reusing forward search from s
|
||||||
new_reverse_heap.Insert(candidate.node, 0, candidate.node);
|
new_reverse_heap.Insert(candidate.node, 0, candidate.node);
|
||||||
const bool constexpr STALLING_ENABLED = true;
|
|
||||||
const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
|
||||||
while (new_reverse_heap.Size() > 0)
|
while (new_reverse_heap.Size() > 0)
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<REVERSE_DIRECTION>(facade,
|
||||||
new_reverse_heap,
|
new_reverse_heap,
|
||||||
existing_forward_heap,
|
existing_forward_heap,
|
||||||
*s_v_middle,
|
*s_v_middle,
|
||||||
upper_bound_s_v_path_length,
|
upper_bound_s_v_path_length,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
false,
|
DO_NOT_FORCE_LOOPS,
|
||||||
STALLING_ENABLED,
|
DO_NOT_FORCE_LOOPS);
|
||||||
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_length)
|
||||||
@ -374,16 +363,14 @@ bool viaNodeCandidatePassesTTest(
|
|||||||
new_forward_heap.Insert(candidate.node, 0, candidate.node);
|
new_forward_heap.Insert(candidate.node, 0, candidate.node);
|
||||||
while (new_forward_heap.Size() > 0)
|
while (new_forward_heap.Size() > 0)
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<FORWARD_DIRECTION>(facade,
|
||||||
new_forward_heap,
|
new_forward_heap,
|
||||||
existing_reverse_heap,
|
existing_reverse_heap,
|
||||||
*v_t_middle,
|
*v_t_middle,
|
||||||
upper_bound_of_v_t_path_length,
|
upper_bound_of_v_t_path_length,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
true,
|
DO_NOT_FORCE_LOOPS,
|
||||||
STALLING_ENABLED,
|
DO_NOT_FORCE_LOOPS);
|
||||||
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_length)
|
||||||
@ -549,29 +536,25 @@ bool viaNodeCandidatePassesTTest(
|
|||||||
{
|
{
|
||||||
if (!forward_heap3.Empty())
|
if (!forward_heap3.Empty())
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<FORWARD_DIRECTION>(facade,
|
||||||
forward_heap3,
|
forward_heap3,
|
||||||
reverse_heap3,
|
reverse_heap3,
|
||||||
middle,
|
middle,
|
||||||
upper_bound,
|
upper_bound,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
true,
|
DO_NOT_FORCE_LOOPS,
|
||||||
STALLING_ENABLED,
|
DO_NOT_FORCE_LOOPS);
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
DO_NOT_FORCE_LOOPS);
|
|
||||||
}
|
}
|
||||||
if (!reverse_heap3.Empty())
|
if (!reverse_heap3.Empty())
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<REVERSE_DIRECTION>(facade,
|
||||||
reverse_heap3,
|
reverse_heap3,
|
||||||
forward_heap3,
|
forward_heap3,
|
||||||
middle,
|
middle,
|
||||||
upper_bound,
|
upper_bound,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
false,
|
DO_NOT_FORCE_LOOPS,
|
||||||
STALLING_ENABLED,
|
DO_NOT_FORCE_LOOPS);
|
||||||
DO_NOT_FORCE_LOOPS,
|
|
||||||
DO_NOT_FORCE_LOOPS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (upper_bound <= t_test_path_length);
|
return (upper_bound <= t_test_path_length);
|
||||||
@ -644,25 +627,25 @@ alternativePathSearch(SearchEngineData &engine_working_data,
|
|||||||
{
|
{
|
||||||
if (0 < forward_heap1.Size())
|
if (0 < forward_heap1.Size())
|
||||||
{
|
{
|
||||||
alternativeRoutingStep<true>(facade,
|
alternativeRoutingStep<FORWARD_DIRECTION>(facade,
|
||||||
forward_heap1,
|
forward_heap1,
|
||||||
reverse_heap1,
|
reverse_heap1,
|
||||||
&middle_node,
|
&middle_node,
|
||||||
&upper_bound_to_shortest_path_weight,
|
&upper_bound_to_shortest_path_weight,
|
||||||
via_node_candidate_list,
|
via_node_candidate_list,
|
||||||
forward_search_space,
|
forward_search_space,
|
||||||
min_edge_offset);
|
min_edge_offset);
|
||||||
}
|
}
|
||||||
if (0 < reverse_heap1.Size())
|
if (0 < reverse_heap1.Size())
|
||||||
{
|
{
|
||||||
alternativeRoutingStep<false>(facade,
|
alternativeRoutingStep<REVERSE_DIRECTION>(facade,
|
||||||
forward_heap1,
|
forward_heap1,
|
||||||
reverse_heap1,
|
reverse_heap1,
|
||||||
&middle_node,
|
&middle_node,
|
||||||
&upper_bound_to_shortest_path_weight,
|
&upper_bound_to_shortest_path_weight,
|
||||||
via_node_candidate_list,
|
via_node_candidate_list,
|
||||||
reverse_search_space,
|
reverse_search_space,
|
||||||
min_edge_offset);
|
min_edge_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,9 +81,6 @@ extractRoute(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &f
|
|||||||
|
|
||||||
return raw_route_data;
|
return raw_route_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevents forcing of loops, since offsets are set correctly
|
|
||||||
static const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a striped down version of the general shortest path algorithm.
|
/// This is a striped down version of the general shortest path algorithm.
|
||||||
|
@ -15,7 +15,7 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
using QueryHeap = SearchEngineData::ManyToManyQueryHeap;
|
using ManyToManyQueryHeap = SearchEngineData::ManyToManyQueryHeap;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -29,21 +29,21 @@ struct NodeBucket
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
|
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
|
||||||
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
||||||
|
|
||||||
template <bool forward_direction>
|
template <bool DIRECTION>
|
||||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const NodeID node,
|
const NodeID node,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
QueryHeap &query_heap)
|
ManyToManyQueryHeap &query_heap)
|
||||||
{
|
{
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
const bool direction_flag = (forward_direction ? data.forward : data.backward);
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
if (direction_flag)
|
|
||||||
{
|
{
|
||||||
const NodeID to = facade.GetTarget(edge);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
@ -69,38 +69,10 @@ void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<alg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stalling
|
void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
template <bool forward_direction>
|
|
||||||
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
|
||||||
const NodeID node,
|
|
||||||
const EdgeWeight weight,
|
|
||||||
QueryHeap &query_heap)
|
|
||||||
{
|
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
|
||||||
if (reverse_flag)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
|
||||||
if (query_heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
if (query_heap.GetKey(to) + edge_weight < weight)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
|
||||||
const unsigned row_idx,
|
const unsigned row_idx,
|
||||||
const unsigned number_of_targets,
|
const unsigned number_of_targets,
|
||||||
QueryHeap &query_heap,
|
ManyToManyQueryHeap &query_heap,
|
||||||
const SearchSpaceWithBuckets &search_space_with_buckets,
|
const SearchSpaceWithBuckets &search_space_with_buckets,
|
||||||
std::vector<EdgeWeight> &weights_table,
|
std::vector<EdgeWeight> &weights_table,
|
||||||
std::vector<EdgeWeight> &durations_table)
|
std::vector<EdgeWeight> &durations_table)
|
||||||
@ -146,17 +118,18 @@ void ForwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<alg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stallAtNode<true>(facade, node, source_weight, query_heap))
|
if (stallAtNode<FORWARD_DIRECTION>(facade, node, source_weight, query_heap))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
relaxOutgoingEdges<true>(facade, node, source_weight, source_duration, query_heap);
|
|
||||||
|
relaxOutgoingEdges<FORWARD_DIRECTION>(facade, node, source_weight, source_duration, query_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backwardRoutingStep(
|
void backwardRoutingStep(
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const unsigned column_idx,
|
const unsigned column_idx,
|
||||||
QueryHeap &query_heap,
|
ManyToManyQueryHeap &query_heap,
|
||||||
SearchSpaceWithBuckets &search_space_with_buckets)
|
SearchSpaceWithBuckets &search_space_with_buckets)
|
||||||
{
|
{
|
||||||
const NodeID node = query_heap.DeleteMin();
|
const NodeID node = query_heap.DeleteMin();
|
||||||
@ -166,12 +139,12 @@ void backwardRoutingStep(
|
|||||||
// store settled nodes in search space bucket
|
// store settled nodes in search space bucket
|
||||||
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
|
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
|
||||||
|
|
||||||
if (stallAtNode<false>(facade, node, target_weight, query_heap))
|
if (stallAtNode<REVERSE_DIRECTION>(facade, node, target_weight, query_heap))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<false>(facade, node, target_weight, target_duration, query_heap);
|
relaxOutgoingEdges<REVERSE_DIRECTION>(facade, node, target_weight, target_duration, query_heap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +218,7 @@ manyToManySearch(SearchEngineData &engine_working_data,
|
|||||||
// explore search space
|
// explore search space
|
||||||
while (!query_heap.Empty())
|
while (!query_heap.Empty())
|
||||||
{
|
{
|
||||||
ForwardRoutingStep(facade,
|
forwardRoutingStep(facade,
|
||||||
row_idx,
|
row_idx,
|
||||||
number_of_targets,
|
number_of_targets,
|
||||||
query_heap,
|
query_heap,
|
||||||
|
@ -7,125 +7,6 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
|
||||||
NodeID &middle_node_id,
|
|
||||||
EdgeWeight &upper_bound,
|
|
||||||
EdgeWeight min_edge_offset,
|
|
||||||
const bool forward_direction,
|
|
||||||
const bool stalling,
|
|
||||||
const bool force_loop_forward,
|
|
||||||
const bool force_loop_reverse)
|
|
||||||
{
|
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
|
||||||
const EdgeWeight weight = forward_heap.GetKey(node);
|
|
||||||
|
|
||||||
if (reverse_heap.WasInserted(node))
|
|
||||||
{
|
|
||||||
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
|
||||||
if (new_weight < upper_bound)
|
|
||||||
{
|
|
||||||
// if loops are forced, they are so at the source
|
|
||||||
if ((force_loop_forward && forward_heap.GetData(node).parent == node) ||
|
|
||||||
(force_loop_reverse && reverse_heap.GetData(node).parent == node) ||
|
|
||||||
// in this case we are looking at a bi-directional way where the source
|
|
||||||
// and target phantom are on the same edge based node
|
|
||||||
new_weight < 0)
|
|
||||||
{
|
|
||||||
// check whether there is a loop present at the node
|
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
|
||||||
if (forward_directionFlag)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
if (to == node)
|
|
||||||
{
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
const EdgeWeight loop_weight = new_weight + edge_weight;
|
|
||||||
if (loop_weight >= 0 && loop_weight < upper_bound)
|
|
||||||
{
|
|
||||||
middle_node_id = node;
|
|
||||||
upper_bound = loop_weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(new_weight >= 0);
|
|
||||||
|
|
||||||
middle_node_id = node;
|
|
||||||
upper_bound = new_weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we don't terminate too early if we initialize the weight
|
|
||||||
// for the nodes in the forward heap with the forward/reverse offset
|
|
||||||
BOOST_ASSERT(min_edge_offset <= 0);
|
|
||||||
if (weight + min_edge_offset > upper_bound)
|
|
||||||
{
|
|
||||||
forward_heap.DeleteAll();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stalling
|
|
||||||
if (stalling)
|
|
||||||
{
|
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
|
||||||
if (reverse_flag)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
|
||||||
|
|
||||||
if (forward_heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
if (forward_heap.GetKey(to) + edge_weight < weight)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
|
||||||
if (forward_directionFlag)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
|
||||||
const EdgeWeight to_weight = weight + edge_weight;
|
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if (!forward_heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
forward_heap.Insert(to, to_weight, node);
|
|
||||||
}
|
|
||||||
// Found a shorter Path -> Update weight
|
|
||||||
else if (to_weight < forward_heap.GetKey(to))
|
|
||||||
{
|
|
||||||
// new parent
|
|
||||||
forward_heap.GetData(to).parent = node;
|
|
||||||
forward_heap.DecreaseKey(to, to_weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unpacks a single edge (NodeID->NodeID) from the CH graph down to it's original non-shortcut
|
* Unpacks a single edge (NodeID->NodeID) from the CH graph down to it's original non-shortcut
|
||||||
* route.
|
* route.
|
||||||
@ -207,34 +88,29 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>
|
|||||||
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
|
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
|
||||||
|
|
||||||
// run two-Target Dijkstra routing step.
|
// run two-Target Dijkstra routing step.
|
||||||
const constexpr bool STALLING_ENABLED = true;
|
|
||||||
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
||||||
{
|
{
|
||||||
if (!forward_heap.Empty())
|
if (!forward_heap.Empty())
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<FORWARD_DIRECTION>(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
middle,
|
middle,
|
||||||
weight,
|
weight,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
true,
|
force_loop_forward,
|
||||||
STALLING_ENABLED,
|
force_loop_reverse);
|
||||||
force_loop_forward,
|
|
||||||
force_loop_reverse);
|
|
||||||
}
|
}
|
||||||
if (!reverse_heap.Empty())
|
if (!reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<REVERSE_DIRECTION>(facade,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
middle,
|
middle,
|
||||||
weight,
|
weight,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
false,
|
force_loop_reverse,
|
||||||
STALLING_ENABLED,
|
force_loop_forward);
|
||||||
force_loop_reverse,
|
|
||||||
force_loop_forward);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +169,6 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::Core
|
|||||||
// we only every insert negative offsets for nodes in the forward heap
|
// we only every insert negative offsets for nodes in the forward heap
|
||||||
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
|
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
|
||||||
|
|
||||||
const constexpr bool STALLING_ENABLED = true;
|
|
||||||
// run two-Target Dijkstra routing step.
|
// run two-Target Dijkstra routing step.
|
||||||
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
||||||
{
|
{
|
||||||
@ -307,14 +182,12 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<FORWARD_DIRECTION>(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
middle,
|
middle,
|
||||||
weight,
|
weight,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
true,
|
|
||||||
STALLING_ENABLED,
|
|
||||||
force_loop_forward,
|
force_loop_forward,
|
||||||
force_loop_reverse);
|
force_loop_reverse);
|
||||||
}
|
}
|
||||||
@ -329,14 +202,12 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<REVERSE_DIRECTION>(facade,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
middle,
|
middle,
|
||||||
weight,
|
weight,
|
||||||
min_edge_offset,
|
min_edge_offset,
|
||||||
false,
|
|
||||||
STALLING_ENABLED,
|
|
||||||
force_loop_reverse,
|
force_loop_reverse,
|
||||||
force_loop_forward);
|
force_loop_forward);
|
||||||
}
|
}
|
||||||
@ -378,29 +249,24 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::Core
|
|||||||
BOOST_ASSERT(min_core_edge_offset <= 0);
|
BOOST_ASSERT(min_core_edge_offset <= 0);
|
||||||
|
|
||||||
// run two-target Dijkstra routing step on core with termination criterion
|
// run two-target Dijkstra routing step on core with termination criterion
|
||||||
const constexpr bool STALLING_DISABLED = false;
|
|
||||||
while (0 < forward_core_heap.Size() && 0 < reverse_core_heap.Size() &&
|
while (0 < forward_core_heap.Size() && 0 < reverse_core_heap.Size() &&
|
||||||
weight > (forward_core_heap.MinKey() + reverse_core_heap.MinKey()))
|
weight > (forward_core_heap.MinKey() + reverse_core_heap.MinKey()))
|
||||||
{
|
{
|
||||||
routingStep(facade,
|
routingStep<FORWARD_DIRECTION, DISABLE_STALLING>(facade,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
middle,
|
middle,
|
||||||
weight,
|
weight,
|
||||||
min_core_edge_offset,
|
min_core_edge_offset,
|
||||||
true,
|
|
||||||
STALLING_DISABLED,
|
|
||||||
force_loop_forward,
|
force_loop_forward,
|
||||||
force_loop_reverse);
|
force_loop_reverse);
|
||||||
|
|
||||||
routingStep(facade,
|
routingStep<REVERSE_DIRECTION, DISABLE_STALLING>(facade,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
middle,
|
middle,
|
||||||
weight,
|
weight,
|
||||||
min_core_edge_offset,
|
min_core_edge_offset,
|
||||||
false,
|
|
||||||
STALLING_DISABLED,
|
|
||||||
force_loop_reverse,
|
force_loop_reverse,
|
||||||
force_loop_forward);
|
force_loop_forward);
|
||||||
}
|
}
|
||||||
@ -571,9 +437,6 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorith
|
|||||||
target_phantom.reverse_segment_id.id);
|
target_phantom.reverse_segment_id.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool constexpr DO_NOT_FORCE_LOOPS =
|
|
||||||
false; // prevents forcing of loops, since offsets are set correctly
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
search(facade,
|
search(facade,
|
||||||
@ -635,9 +498,6 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorith
|
|||||||
target_phantom.reverse_segment_id.id);
|
target_phantom.reverse_segment_id.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool constexpr DO_NOT_FORCE_LOOPS =
|
|
||||||
false; // prevents forcing of loops, since offsets are set correctly
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
search(facade,
|
search(facade,
|
||||||
|
Loading…
Reference in New Issue
Block a user