diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 77f16fed6..dd805b2d0 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -33,6 +33,68 @@ namespace engine namespace routing_algorithms { +static constexpr bool FORWARD_DIRECTION = true; +static constexpr bool REVERSE_DIRECTION = false; + +// Stalling +template +bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade &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 +void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &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 @@ -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, 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 void routingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, SearchEngineData::QueryHeap &forward_heap, SearchEngineData::QueryHeap &reverse_heap, NodeID &middle_node_id, - std::int32_t &upper_bound, - std::int32_t min_edge_offset, - const bool forward_direction, - const bool stalling, + EdgeWeight &upper_bound, + EdgeWeight min_edge_offset, 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(facade, node, weight, forward_heap)) + { + return; + } + + relaxOutgoingEdges(facade, node, weight, forward_heap); +} template EdgeWeight diff --git a/src/engine/routing_algorithms/alternative_path.cpp b/src/engine/routing_algorithms/alternative_path.cpp index 769094c3e..fa630d88b 100644 --- a/src/engine/routing_algorithms/alternative_path.cpp +++ b/src/engine/routing_algorithms/alternative_path.cpp @@ -47,7 +47,7 @@ struct RankedCandidateNode }; // todo: reorder parameters -template +template void alternativeRoutingStep( const datafacade::ContiguousInternalMemoryDataFacade &facade, QueryHeap &heap1, @@ -58,8 +58,8 @@ void alternativeRoutingStep( std::vector &search_space, const EdgeWeight min_edge_offset) { - QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2); - QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1); + QueryHeap &forward_heap = DIRECTION == FORWARD_DIRECTION ? heap1 : heap2; + QueryHeap &reverse_heap = DIRECTION == FORWARD_DIRECTION ? heap2 : heap1; const NodeID node = forward_heap.DeleteMin(); const EdgeWeight weight = forward_heap.GetKey(node); @@ -104,8 +104,7 @@ void alternativeRoutingStep( for (auto edge : facade.GetAdjacentEdgeRange(node)) { const auto &data = facade.GetEdgeData(edge); - const bool edge_is_forward_directed = (is_forward_directed ? data.forward : data.backward); - if (edge_is_forward_directed) + if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward) { const NodeID to = facade.GetTarget(edge); const EdgeWeight edge_weight = data.weight; @@ -179,20 +178,16 @@ void computeLengthAndSharingOfViaPath( int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT; new_reverse_heap.Insert(via_node, 0, via_node); // compute path 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()) { - routingStep(facade, - new_reverse_heap, - existing_forward_heap, - s_v_middle, - upper_bound_s_v_path_length, - min_edge_offset, - false, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_reverse_heap, + existing_forward_heap, + s_v_middle, + upper_bound_s_v_path_length, + min_edge_offset, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } // compute path by reusing backward search from node t NodeID v_t_middle = SPECIAL_NODEID; @@ -200,16 +195,14 @@ void computeLengthAndSharingOfViaPath( new_forward_heap.Insert(via_node, 0, via_node); while (!new_forward_heap.Empty()) { - routingStep(facade, - new_forward_heap, - existing_reverse_heap, - v_t_middle, - upper_bound_of_v_t_path_length, - min_edge_offset, - true, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_forward_heap, + existing_reverse_heap, + v_t_middle, + upper_bound_of_v_t_path_length, + 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; @@ -347,20 +340,16 @@ bool viaNodeCandidatePassesTTest( int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT; // compute path by reusing forward search from s 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) { - routingStep(facade, - new_reverse_heap, - existing_forward_heap, - *s_v_middle, - upper_bound_s_v_path_length, - min_edge_offset, - false, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_reverse_heap, + existing_forward_heap, + *s_v_middle, + upper_bound_s_v_path_length, + min_edge_offset, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } 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); while (new_forward_heap.Size() > 0) { - routingStep(facade, - new_forward_heap, - existing_reverse_heap, - *v_t_middle, - upper_bound_of_v_t_path_length, - min_edge_offset, - true, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_forward_heap, + existing_reverse_heap, + *v_t_middle, + upper_bound_of_v_t_path_length, + min_edge_offset, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length) @@ -549,29 +536,25 @@ bool viaNodeCandidatePassesTTest( { if (!forward_heap3.Empty()) { - routingStep(facade, - forward_heap3, - reverse_heap3, - middle, - upper_bound, - min_edge_offset, - true, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + forward_heap3, + reverse_heap3, + middle, + upper_bound, + min_edge_offset, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } if (!reverse_heap3.Empty()) { - routingStep(facade, - reverse_heap3, - forward_heap3, - middle, - upper_bound, - min_edge_offset, - false, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + reverse_heap3, + forward_heap3, + middle, + upper_bound, + min_edge_offset, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } } return (upper_bound <= t_test_path_length); @@ -644,25 +627,25 @@ alternativePathSearch(SearchEngineData &engine_working_data, { if (0 < forward_heap1.Size()) { - alternativeRoutingStep(facade, - forward_heap1, - reverse_heap1, - &middle_node, - &upper_bound_to_shortest_path_weight, - via_node_candidate_list, - forward_search_space, - min_edge_offset); + alternativeRoutingStep(facade, + forward_heap1, + reverse_heap1, + &middle_node, + &upper_bound_to_shortest_path_weight, + via_node_candidate_list, + forward_search_space, + min_edge_offset); } if (0 < reverse_heap1.Size()) { - alternativeRoutingStep(facade, - forward_heap1, - reverse_heap1, - &middle_node, - &upper_bound_to_shortest_path_weight, - via_node_candidate_list, - reverse_search_space, - min_edge_offset); + alternativeRoutingStep(facade, + forward_heap1, + reverse_heap1, + &middle_node, + &upper_bound_to_shortest_path_weight, + via_node_candidate_list, + reverse_search_space, + min_edge_offset); } } diff --git a/src/engine/routing_algorithms/direct_shortest_path.cpp b/src/engine/routing_algorithms/direct_shortest_path.cpp index ab7becf1a..1d46fd922 100644 --- a/src/engine/routing_algorithms/direct_shortest_path.cpp +++ b/src/engine/routing_algorithms/direct_shortest_path.cpp @@ -81,9 +81,6 @@ extractRoute(const datafacade::ContiguousInternalMemoryDataFacade &f 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. diff --git a/src/engine/routing_algorithms/many_to_many.cpp b/src/engine/routing_algorithms/many_to_many.cpp index 370cb50ef..6eef3b0d1 100644 --- a/src/engine/routing_algorithms/many_to_many.cpp +++ b/src/engine/routing_algorithms/many_to_many.cpp @@ -15,7 +15,7 @@ namespace engine namespace routing_algorithms { -using QueryHeap = SearchEngineData::ManyToManyQueryHeap; +using ManyToManyQueryHeap = SearchEngineData::ManyToManyQueryHeap; namespace { @@ -29,21 +29,21 @@ struct NodeBucket { } }; + // FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking using SearchSpaceWithBuckets = std::unordered_map>; -template +template void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &facade, const NodeID node, const EdgeWeight weight, const EdgeWeight duration, - QueryHeap &query_heap) + ManyToManyQueryHeap &query_heap) { for (auto edge : facade.GetAdjacentEdgeRange(node)) { const auto &data = facade.GetEdgeData(edge); - const bool direction_flag = (forward_direction ? data.forward : data.backward); - if (direction_flag) + if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward) { const NodeID to = facade.GetTarget(edge); const EdgeWeight edge_weight = data.weight; @@ -69,38 +69,10 @@ void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade -bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade &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 &facade, +void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, const unsigned row_idx, const unsigned number_of_targets, - QueryHeap &query_heap, + ManyToManyQueryHeap &query_heap, const SearchSpaceWithBuckets &search_space_with_buckets, std::vector &weights_table, std::vector &durations_table) @@ -146,17 +118,18 @@ void ForwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade(facade, node, source_weight, query_heap)) + if (stallAtNode(facade, node, source_weight, query_heap)) { return; } - relaxOutgoingEdges(facade, node, source_weight, source_duration, query_heap); + + relaxOutgoingEdges(facade, node, source_weight, source_duration, query_heap); } void backwardRoutingStep( const datafacade::ContiguousInternalMemoryDataFacade &facade, const unsigned column_idx, - QueryHeap &query_heap, + ManyToManyQueryHeap &query_heap, SearchSpaceWithBuckets &search_space_with_buckets) { const NodeID node = query_heap.DeleteMin(); @@ -166,12 +139,12 @@ void backwardRoutingStep( // store settled nodes in search space bucket search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration); - if (stallAtNode(facade, node, target_weight, query_heap)) + if (stallAtNode(facade, node, target_weight, query_heap)) { return; } - relaxOutgoingEdges(facade, node, target_weight, target_duration, query_heap); + relaxOutgoingEdges(facade, node, target_weight, target_duration, query_heap); } } @@ -245,7 +218,7 @@ manyToManySearch(SearchEngineData &engine_working_data, // explore search space while (!query_heap.Empty()) { - ForwardRoutingStep(facade, + forwardRoutingStep(facade, row_idx, number_of_targets, query_heap, diff --git a/src/engine/routing_algorithms/routing_base.cpp b/src/engine/routing_algorithms/routing_base.cpp index a73ff55ad..fc7eb4f41 100644 --- a/src/engine/routing_algorithms/routing_base.cpp +++ b/src/engine/routing_algorithms/routing_base.cpp @@ -7,125 +7,6 @@ namespace engine namespace routing_algorithms { -void routingStep(const datafacade::ContiguousInternalMemoryDataFacade &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 * route. @@ -207,34 +88,29 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade BOOST_ASSERT(reverse_heap.MinKey() >= 0); // run two-Target Dijkstra routing step. - const constexpr bool STALLING_ENABLED = true; while (0 < (forward_heap.Size() + reverse_heap.Size())) { if (!forward_heap.Empty()) { - routingStep(facade, - forward_heap, - reverse_heap, - middle, - weight, - min_edge_offset, - true, - STALLING_ENABLED, - force_loop_forward, - force_loop_reverse); + routingStep(facade, + forward_heap, + reverse_heap, + middle, + weight, + min_edge_offset, + force_loop_forward, + force_loop_reverse); } if (!reverse_heap.Empty()) { - routingStep(facade, - reverse_heap, - forward_heap, - middle, - weight, - min_edge_offset, - false, - STALLING_ENABLED, - force_loop_reverse, - force_loop_forward); + routingStep(facade, + reverse_heap, + forward_heap, + middle, + weight, + min_edge_offset, + force_loop_reverse, + force_loop_forward); } } @@ -293,7 +169,6 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade= 0); - const constexpr bool STALLING_ENABLED = true; // run two-Target Dijkstra routing step. while (0 < (forward_heap.Size() + reverse_heap.Size())) { @@ -307,14 +182,12 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade(facade, forward_heap, reverse_heap, middle, weight, min_edge_offset, - true, - STALLING_ENABLED, force_loop_forward, force_loop_reverse); } @@ -329,14 +202,12 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade(facade, reverse_heap, forward_heap, middle, weight, min_edge_offset, - false, - STALLING_ENABLED, force_loop_reverse, force_loop_forward); } @@ -378,29 +249,24 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade (forward_core_heap.MinKey() + reverse_core_heap.MinKey())) { - routingStep(facade, + routingStep(facade, forward_core_heap, reverse_core_heap, middle, weight, min_core_edge_offset, - true, - STALLING_DISABLED, force_loop_forward, force_loop_reverse); - routingStep(facade, + routingStep(facade, reverse_core_heap, forward_core_heap, middle, weight, min_core_edge_offset, - false, - STALLING_DISABLED, force_loop_reverse, force_loop_forward); } @@ -571,9 +437,6 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade packed_path; search(facade, @@ -635,9 +498,6 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade packed_path; search(facade,