diff --git a/include/engine/routing_algorithms/routing_base_ch.hpp b/include/engine/routing_algorithms/routing_base_ch.hpp index 79044c8d65b..863d29cf335 100644 --- a/include/engine/routing_algorithms/routing_base_ch.hpp +++ b/include/engine/routing_algorithms/routing_base_ch.hpp @@ -24,11 +24,10 @@ namespace ch // Stalling template bool stallAtNode(const DataFacade &facade, - const NodeID node, - const EdgeWeight weight, + const typename HeapT::HeapNode &heapNode, const HeapT &query_heap) { - for (auto edge : facade.GetAdjacentEdgeRange(node)) + for (auto edge : facade.GetAdjacentEdgeRange(heapNode.node)) { const auto &data = facade.GetEdgeData(edge); if (DIRECTION == REVERSE_DIRECTION ? data.forward : data.backward) @@ -36,9 +35,10 @@ bool stallAtNode(const DataFacade &facade, 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)) + const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to); + if (toHeapNode) { - if (query_heap.GetKey(to) + edge_weight < weight) + if (toHeapNode->weight + edge_weight < heapNode.weight) { return true; } @@ -50,11 +50,10 @@ bool stallAtNode(const DataFacade &facade, template void relaxOutgoingEdges(const DataFacade &facade, - const NodeID node, - const EdgeWeight weight, + const SearchEngineData::QueryHeap::HeapNode &heapNode, SearchEngineData::QueryHeap &heap) { - for (const auto edge : facade.GetAdjacentEdgeRange(node)) + for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node)) { const auto &data = facade.GetEdgeData(edge); if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward) @@ -63,19 +62,21 @@ void relaxOutgoingEdges(const DataFacade &facade, const EdgeWeight edge_weight = data.weight; BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); - const EdgeWeight to_weight = weight + edge_weight; + const EdgeWeight to_weight = heapNode.weight + edge_weight; + const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to); // New Node discovered -> Add to Heap + Node Info Storage - if (!heap.WasInserted(to)) + if (!toHeapNode) { - heap.Insert(to, to_weight, node); + heap.Insert(to, to_weight, heapNode.node); } // Found a shorter Path -> Update weight - else if (to_weight < heap.GetKey(to)) + else if (to_weight < toHeapNode->weight) { // new parent - heap.GetData(to).parent = node; - heap.DecreaseKey(to, to_weight); + toHeapNode->data.parent = heapNode.node; + toHeapNode->weight = to_weight; + heap.DecreaseKey(*toHeapNode); } } } @@ -122,35 +123,35 @@ void routingStep(const DataFacade &facade, const bool force_loop_forward, const bool force_loop_reverse) { - const NodeID node = forward_heap.DeleteMin(); - const EdgeWeight weight = forward_heap.GetKey(node); + auto heapNode = forward_heap.DeleteMinGetHeapNode(); + const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node); - if (reverse_heap.WasInserted(node)) + if (reverseHeapNode) { - const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight; + const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.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) || + if ((force_loop_forward && heapNode.data.parent == heapNode.node) || + (force_loop_reverse && reverseHeapNode->data.parent == heapNode.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)) + for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node)) { const auto &data = facade.GetEdgeData(edge); if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward) { const NodeID to = facade.GetTarget(edge); - if (to == node) + if (to == heapNode.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; + middle_node_id = heapNode.node; upper_bound = loop_weight; } } @@ -161,7 +162,7 @@ void routingStep(const DataFacade &facade, { BOOST_ASSERT(new_weight >= 0); - middle_node_id = node; + middle_node_id = heapNode.node; upper_bound = new_weight; } } @@ -170,19 +171,19 @@ void routingStep(const DataFacade &facade, // 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) + if (heapNode.weight + min_edge_offset > upper_bound) { forward_heap.DeleteAll(); return; } // Stalling - if (STALLING && stallAtNode(facade, node, weight, forward_heap)) + if (STALLING && stallAtNode(facade, heapNode, forward_heap)) { return; } - relaxOutgoingEdges(facade, node, weight, forward_heap); + relaxOutgoingEdges(facade, heapNode, forward_heap); } template diff --git a/include/engine/routing_algorithms/routing_base_mld.hpp b/include/engine/routing_algorithms/routing_base_mld.hpp index 17c5b093126..55f366574b7 100644 --- a/include/engine/routing_algorithms/routing_base_mld.hpp +++ b/include/engine/routing_algorithms/routing_base_mld.hpp @@ -228,40 +228,42 @@ retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward template void relaxOutgoingEdges(const DataFacade &facade, typename SearchEngineData::QueryHeap &forward_heap, - const NodeID node, - const EdgeWeight weight, + const typename SearchEngineData::QueryHeap::HeapNode &heapNode, Args... args) { const auto &partition = facade.GetMultiLevelPartition(); const auto &cells = facade.GetCellStorage(); const auto &metric = facade.GetCellMetric(); - const auto level = getNodeQueryLevel(partition, node, args...); + const auto level = getNodeQueryLevel(partition, heapNode.node, args...); - if (level >= 1 && !forward_heap.GetData(node).from_clique_arc) + if (level >= 1 && !heapNode.data.from_clique_arc) { if (DIRECTION == FORWARD_DIRECTION) { // Shortcuts in forward direction - const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node)); + const auto &cell = + cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); auto destination = cell.GetDestinationNodes().begin(); - for (auto shortcut_weight : cell.GetOutWeight(node)) + for (auto shortcut_weight : cell.GetOutWeight(heapNode.node)) { BOOST_ASSERT(destination != cell.GetDestinationNodes().end()); const NodeID to = *destination; - if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to) + if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to) { - const EdgeWeight to_weight = weight + shortcut_weight; - BOOST_ASSERT(to_weight >= weight); - if (!forward_heap.WasInserted(to)) + const EdgeWeight to_weight = heapNode.weight + shortcut_weight; + BOOST_ASSERT(to_weight >= heapNode.weight); + const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); + if (!toHeapNode) { - forward_heap.Insert(to, to_weight, {node, true}); + forward_heap.Insert(to, to_weight, {heapNode.node, true}); } - else if (to_weight < forward_heap.GetKey(to)) + else if (to_weight < toHeapNode->weight) { - forward_heap.GetData(to) = {node, true}; - forward_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {heapNode.node, true}; + toHeapNode->weight = to_weight; + forward_heap.DecreaseKey(*toHeapNode); } } ++destination; @@ -270,25 +272,28 @@ void relaxOutgoingEdges(const DataFacade &facade, else { // Shortcuts in backward direction - const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node)); + const auto &cell = + cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); auto source = cell.GetSourceNodes().begin(); - for (auto shortcut_weight : cell.GetInWeight(node)) + for (auto shortcut_weight : cell.GetInWeight(heapNode.node)) { BOOST_ASSERT(source != cell.GetSourceNodes().end()); const NodeID to = *source; - if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to) + if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to) { - const EdgeWeight to_weight = weight + shortcut_weight; - BOOST_ASSERT(to_weight >= weight); - if (!forward_heap.WasInserted(to)) + const EdgeWeight to_weight = heapNode.weight + shortcut_weight; + BOOST_ASSERT(to_weight >= heapNode.weight); + const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); + if (!toHeapNode) { - forward_heap.Insert(to, to_weight, {node, true}); + forward_heap.Insert(to, to_weight, {heapNode.node, true}); } - else if (to_weight < forward_heap.GetKey(to)) + else if (to_weight < toHeapNode->weight) { - forward_heap.GetData(to) = {node, true}; - forward_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {heapNode.node, true}; + toHeapNode->weight = to_weight; + forward_heap.DecreaseKey(*toHeapNode); } } ++source; @@ -297,7 +302,7 @@ void relaxOutgoingEdges(const DataFacade &facade, } // Boundary edges - for (const auto edge : facade.GetBorderEdgeRange(level, node)) + for (const auto edge : facade.GetBorderEdgeRange(level, heapNode.node)) { const auto &edge_data = facade.GetEdgeData(edge); @@ -310,21 +315,23 @@ void relaxOutgoingEdges(const DataFacade &facade, checkParentCellRestriction(partition.GetCell(level + 1, to), args...)) { const auto node_weight = - facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? node : to); + facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? heapNode.node : to); const auto turn_penalty = facade.GetWeightPenaltyForEdgeID(edge_data.turn_id); // TODO: BOOST_ASSERT(edge_data.weight == node_weight + turn_penalty); - const EdgeWeight to_weight = weight + node_weight + turn_penalty; + const EdgeWeight to_weight = heapNode.weight + node_weight + turn_penalty; - if (!forward_heap.WasInserted(to)) + const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); + if (!toHeapNode) { - forward_heap.Insert(to, to_weight, {node, false}); + forward_heap.Insert(to, to_weight, {heapNode.node, false}); } - else if (to_weight < forward_heap.GetKey(to)) + else if (to_weight < toHeapNode->weight) { - forward_heap.GetData(to) = {node, false}; - forward_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {heapNode.node, false}; + toHeapNode->weight = to_weight; + forward_heap.DecreaseKey(*toHeapNode); } } } @@ -341,34 +348,35 @@ void routingStep(const DataFacade &facade, const bool force_loop_reverse, Args... args) { - const auto node = forward_heap.DeleteMin(); - const auto weight = forward_heap.GetKey(node); + const auto heapNode = forward_heap.DeleteMinGetHeapNode(); + const auto weight = heapNode.weight; - BOOST_ASSERT(!facade.ExcludeNode(node)); + BOOST_ASSERT(!facade.ExcludeNode(heapNode.node)); // Upper bound for the path source -> target with // weight(source -> node) = weight weight(to -> target) ≤ reverse_weight // is weight + reverse_weight // More tighter upper bound requires additional condition reverse_heap.WasRemoved(to) // with weight(to -> target) = reverse_weight and all weights ≥ 0 - if (reverse_heap.WasInserted(node)) + const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node); + if (reverseHeapNode) { - auto reverse_weight = reverse_heap.GetKey(node); + auto reverse_weight = reverseHeapNode->weight; auto path_weight = weight + reverse_weight; // MLD uses loops forcing only to prune single node paths in forward and/or // backward direction (there is no need to force loops in MLD but in CH) - if (!(force_loop_forward && forward_heap.GetData(node).parent == node) && - !(force_loop_reverse && reverse_heap.GetData(node).parent == node) && + if (!(force_loop_forward && heapNode.data.parent == heapNode.node) && + !(force_loop_reverse && reverseHeapNode->data.parent == heapNode.node) && (path_weight >= 0) && (path_weight < path_upper_bound)) { - middle_node = node; + middle_node = heapNode.node; path_upper_bound = path_weight; } } // Relax outgoing edges from node - relaxOutgoingEdges(facade, forward_heap, node, weight, args...); + relaxOutgoingEdges(facade, forward_heap, heapNode, args...); } // With (s, middle, t) we trace back the paths middle -> s and middle -> t. diff --git a/include/util/query_heap.hpp b/include/util/query_heap.hpp index 4030120cb21..dc8a2ee531f 100644 --- a/include/util/query_heap.hpp +++ b/include/util/query_heap.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -194,10 +195,26 @@ template > class QueryHeap { + private: + using HeapData = std::pair; + using HeapContainer = boost::heap::d_ary_heap, + boost::heap::mutable_, + boost::heap::compare>>; + using HeapHandle = typename HeapContainer::handle_type; + public: using WeightType = Weight; using DataType = Data; + struct HeapNode + { + HeapHandle handle; + NodeID node; + Weight weight; + Data data; + }; + template explicit QueryHeap(StorageArgs... args) : node_index(args...) { Clear(); @@ -230,6 +247,13 @@ class QueryHeap return inserted_nodes[index].data; } + HeapNode &getHeapNode(NodeID node) + { + const auto index = node_index.peek_index(node); + BOOST_ASSERT((int)index >= 0 && (int)index < (int)inserted_nodes.size()); + return inserted_nodes[index]; + } + Data const &GetData(NodeID node) const { const auto index = node_index.peek_index(node); @@ -269,6 +293,28 @@ class QueryHeap return inserted_nodes[index].node == node; } + boost::optional GetHeapNodeIfWasInserted(const NodeID node) + { + const auto index = node_index.peek_index(node); + if (index >= static_cast(inserted_nodes.size()) || + inserted_nodes[index].node != node) + { + return {}; + } + return inserted_nodes[index]; + } + + boost::optional GetHeapNodeIfWasInserted(const NodeID node) const + { + const auto index = node_index.peek_index(node); + if (index >= static_cast(inserted_nodes.size()) || + inserted_nodes[index].node != node) + { + return {}; + } + return inserted_nodes[index]; + } + NodeID Min() const { BOOST_ASSERT(!heap.empty()); @@ -290,6 +336,15 @@ class QueryHeap return inserted_nodes[removedIndex].node; } + HeapNode &DeleteMinGetHeapNode() + { + BOOST_ASSERT(!heap.empty()); + const Key removedIndex = heap.top().second; + heap.pop(); + inserted_nodes[removedIndex].handle = heap.s_handle_from_iterator(heap.end()); + return inserted_nodes[removedIndex]; + } + void DeleteAll() { auto const none_handle = heap.s_handle_from_iterator(heap.end()); @@ -308,22 +363,13 @@ class QueryHeap heap.increase(reference.handle, std::make_pair(weight, index)); } - private: - using HeapData = std::pair; - using HeapContainer = boost::heap::d_ary_heap, - boost::heap::mutable_, - boost::heap::compare>>; - using HeapHandle = typename HeapContainer::handle_type; - - struct HeapNode + void DecreaseKey(const HeapNode &heapNode) { - HeapHandle handle; - NodeID node; - Weight weight; - Data data; - }; + BOOST_ASSERT(!WasRemoved(heapNode.node)); + heap.increase(heapNode.handle, std::make_pair(heapNode.weight, (*heapNode.handle).second)); + } + private: std::vector inserted_nodes; HeapContainer heap; IndexStorage node_index; diff --git a/src/contractor/contractor_search.cpp b/src/contractor/contractor_search.cpp index f138f86eacf..f9e336c8e28 100644 --- a/src/contractor/contractor_search.cpp +++ b/src/contractor/contractor_search.cpp @@ -32,16 +32,18 @@ void relaxNode(ContractorHeap &heap, } const EdgeWeight to_weight = node_weight + data.weight; + const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to); // New Node discovered -> Add to Heap + Node Info Storage - if (!heap.WasInserted(to)) + if (!toHeapNode) { heap.Insert(to, to_weight, ContractorHeapData{current_hop, false}); } // Found a shorter Path -> Update weight - else if (to_weight < heap.GetKey(to)) + else if (to_weight < toHeapNode->weight) { - heap.DecreaseKey(to, to_weight); - heap.GetData(to).hop = current_hop; + toHeapNode->weight = to_weight; + heap.DecreaseKey(*toHeapNode); + toHeapNode->data.hop = current_hop; } } } diff --git a/src/engine/routing_algorithms/alternative_path_ch.cpp b/src/engine/routing_algorithms/alternative_path_ch.cpp index 107e98ea962..00be0794dce 100644 --- a/src/engine/routing_algorithms/alternative_path_ch.cpp +++ b/src/engine/routing_algorithms/alternative_path_ch.cpp @@ -62,11 +62,12 @@ void alternativeRoutingStep(const DataFacade &facade, 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); + // Take a copy (no ref &) of the extracted node because otherwise could be modified later if + // toHeapNode is the same + const auto heapNode = forward_heap.DeleteMinGetHeapNode(); const auto scaled_weight = - static_cast((weight + min_edge_offset) / (1. + VIAPATH_EPSILON)); + static_cast((heapNode.weight + min_edge_offset) / (1. + VIAPATH_EPSILON)); if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) && (scaled_weight > *upper_bound_to_shortest_path_weight)) { @@ -74,35 +75,36 @@ void alternativeRoutingStep(const DataFacade &facade, return; } - search_space.emplace_back(forward_heap.GetData(node).parent, node); + search_space.emplace_back(heapNode.data.parent, heapNode.node); - if (reverse_heap.WasInserted(node)) + const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node); + if (reverseHeapNode) { - search_space_intersection.emplace_back(node); - const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight; + search_space_intersection.emplace_back(heapNode.node); + const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight; if (new_weight < *upper_bound_to_shortest_path_weight) { if (new_weight >= 0) { - *middle_node = node; + *middle_node = heapNode.node; *upper_bound_to_shortest_path_weight = new_weight; } else { // check whether there is a loop present at the node - const auto loop_weight = std::get<0>(getLoopWeight(facade, node)); + const auto loop_weight = std::get<0>(getLoopWeight(facade, heapNode.node)); const EdgeWeight new_weight_with_loop = new_weight + loop_weight; if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop <= *upper_bound_to_shortest_path_weight) { - *middle_node = node; + *middle_node = heapNode.node; *upper_bound_to_shortest_path_weight = loop_weight; } } } } - for (auto edge : facade.GetAdjacentEdgeRange(node)) + for (auto edge : facade.GetAdjacentEdgeRange(heapNode.node)) { const auto &data = facade.GetEdgeData(edge); if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward) @@ -111,20 +113,22 @@ void alternativeRoutingStep(const DataFacade &facade, const EdgeWeight edge_weight = data.weight; BOOST_ASSERT(edge_weight > 0); - const EdgeWeight to_weight = weight + edge_weight; + const EdgeWeight to_weight = heapNode.weight + edge_weight; + const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); // New Node discovered -> Add to Heap + Node Info Storage - if (!forward_heap.WasInserted(to)) + if (!toHeapNode) { - forward_heap.Insert(to, to_weight, node); + forward_heap.Insert(to, to_weight, heapNode.node); } // Found a shorter Path -> Update weight - else if (to_weight < forward_heap.GetKey(to)) + else if (to_weight < toHeapNode->weight) { // new parent - forward_heap.GetData(to).parent = node; + toHeapNode->data.parent = heapNode.node; // decreased weight - forward_heap.DecreaseKey(to, to_weight); + toHeapNode->weight = to_weight; + forward_heap.DecreaseKey(*toHeapNode); } } } diff --git a/src/engine/routing_algorithms/many_to_many_ch.cpp b/src/engine/routing_algorithms/many_to_many_ch.cpp index f9fa8e50920..03ef4dc0a64 100644 --- a/src/engine/routing_algorithms/many_to_many_ch.cpp +++ b/src/engine/routing_algorithms/many_to_many_ch.cpp @@ -45,20 +45,18 @@ inline bool addLoopWeight(const DataFacade &facade, } template -void relaxOutgoingEdges(const DataFacade &facade, - const NodeID node, - const EdgeWeight weight, - const EdgeDuration duration, - const EdgeDistance distance, - typename SearchEngineData::ManyToManyQueryHeap &query_heap, - const PhantomNode &) +void relaxOutgoingEdges( + const DataFacade &facade, + const typename SearchEngineData::ManyToManyQueryHeap::HeapNode &heapNode, + typename SearchEngineData::ManyToManyQueryHeap &query_heap, + const PhantomNode &) { - if (stallAtNode(facade, node, weight, query_heap)) + if (stallAtNode(facade, heapNode, query_heap)) { return; } - for (auto edge : facade.GetAdjacentEdgeRange(node)) + for (auto edge : facade.GetAdjacentEdgeRange(heapNode.node)) { const auto &data = facade.GetEdgeData(edge); if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward) @@ -70,21 +68,23 @@ void relaxOutgoingEdges(const DataFacade &facade, const auto edge_distance = data.distance; BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); - const auto to_weight = weight + edge_weight; - const auto to_duration = duration + edge_duration; - const auto to_distance = distance + edge_distance; + const auto to_weight = heapNode.weight + edge_weight; + const auto to_duration = heapNode.data.duration + edge_duration; + const auto to_distance = heapNode.data.distance + edge_distance; + const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to); // New Node discovered -> Add to Heap + Node Info Storage - if (!query_heap.WasInserted(to)) + if (!toHeapNode) { - query_heap.Insert(to, to_weight, {node, to_duration, to_distance}); + query_heap.Insert(to, to_weight, {heapNode.node, to_duration, to_distance}); } // Found a shorter Path -> Update weight and set new parent else if (std::tie(to_weight, to_duration) < - std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration)) + std::tie(toHeapNode->weight, toHeapNode->data.duration)) { - query_heap.GetData(to) = {node, to_duration, to_distance}; - query_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {heapNode.node, to_duration, to_distance}; + toHeapNode->weight = to_weight; + query_heap.DecreaseKey(*toHeapNode); } } } @@ -101,15 +101,14 @@ void forwardRoutingStep(const DataFacade &facade, std::vector &middle_nodes_table, const PhantomNode &phantom_node) { - const auto node = query_heap.DeleteMin(); - const auto source_weight = query_heap.GetKey(node); - const auto source_duration = query_heap.GetData(node).duration; - const auto source_distance = query_heap.GetData(node).distance; + // Take a copy of the extracted node because otherwise could be modified later if toHeapNode is + // the same + const auto heapNode = query_heap.DeleteMinGetHeapNode(); // Check if each encountered node has an entry const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(), search_space_with_buckets.end(), - node, + heapNode.node, NodeBucket::Compare()); for (const auto ¤t_bucket : boost::make_iterator_range(bucket_list)) { @@ -129,18 +128,18 @@ void forwardRoutingStep(const DataFacade &facade, : distances_table[row_index * number_of_targets + column_index]; // Check if new weight is better - auto new_weight = source_weight + target_weight; - auto new_duration = source_duration + target_duration; - auto new_distance = source_distance + target_distance; + auto new_weight = heapNode.weight + target_weight; + auto new_duration = heapNode.data.duration + target_duration; + auto new_distance = heapNode.data.distance + target_distance; if (new_weight < 0) { - if (addLoopWeight(facade, node, new_weight, new_duration, new_distance)) + if (addLoopWeight(facade, heapNode.node, new_weight, new_duration, new_distance)) { current_weight = std::min(current_weight, new_weight); current_duration = std::min(current_duration, new_duration); current_distance = std::min(current_distance, new_distance); - middle_nodes_table[row_index * number_of_targets + column_index] = node; + middle_nodes_table[row_index * number_of_targets + column_index] = heapNode.node; } } else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration)) @@ -148,12 +147,11 @@ void forwardRoutingStep(const DataFacade &facade, current_weight = new_weight; current_duration = new_duration; current_distance = new_distance; - middle_nodes_table[row_index * number_of_targets + column_index] = node; + middle_nodes_table[row_index * number_of_targets + column_index] = heapNode.node; } } - relaxOutgoingEdges( - facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node); + relaxOutgoingEdges(facade, heapNode, query_heap, phantom_node); } void backwardRoutingStep(const DataFacade &facade, @@ -162,18 +160,19 @@ void backwardRoutingStep(const DataFacade &facade, std::vector &search_space_with_buckets, const PhantomNode &phantom_node) { - const auto node = query_heap.DeleteMin(); - const auto target_weight = query_heap.GetKey(node); - const auto target_duration = query_heap.GetData(node).duration; - const auto target_distance = query_heap.GetData(node).distance; - const auto parent = query_heap.GetData(node).parent; + // Take a copy (no ref &) of the extracted node because otherwise could be modified later if + // toHeapNode is the same + const auto heapNode = query_heap.DeleteMinGetHeapNode(); // Store settled nodes in search space bucket - search_space_with_buckets.emplace_back( - node, parent, column_index, target_weight, target_duration, target_distance); - - relaxOutgoingEdges( - facade, node, target_weight, target_duration, target_distance, query_heap, phantom_node); + search_space_with_buckets.emplace_back(heapNode.node, + heapNode.data.parent, + column_index, + heapNode.weight, + heapNode.data.duration, + heapNode.data.distance); + + relaxOutgoingEdges(facade, heapNode, query_heap, phantom_node); } } // namespace ch diff --git a/src/engine/routing_algorithms/many_to_many_mld.cpp b/src/engine/routing_algorithms/many_to_many_mld.cpp index ceb37f3028e..62c9d80566f 100644 --- a/src/engine/routing_algorithms/many_to_many_mld.cpp +++ b/src/engine/routing_algorithms/many_to_many_mld.cpp @@ -71,38 +71,38 @@ void relaxBorderEdges(const DataFacade &facade, const auto to_distance = distance + node_distance; // New Node discovered -> Add to Heap + Node Info Storage - if (!query_heap.WasInserted(to)) + const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to); + if (!toHeapNode) { query_heap.Insert(to, to_weight, {node, false, to_duration, to_distance}); } // Found a shorter Path -> Update weight and set new parent else if (std::tie(to_weight, to_duration, to_distance, node) < - std::tie(query_heap.GetKey(to), - query_heap.GetData(to).duration, - query_heap.GetData(to).distance, - query_heap.GetData(to).parent)) + std::tie(toHeapNode->weight, + toHeapNode->data.duration, + toHeapNode->data.distance, + toHeapNode->data.parent)) { - query_heap.GetData(to) = {node, false, to_duration, to_distance}; - query_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {node, false, to_duration, to_distance}; + toHeapNode->weight = to_weight; + query_heap.DecreaseKey(*toHeapNode); } } } } template -void relaxOutgoingEdges(const DataFacade &facade, - const NodeID node, - const EdgeWeight weight, - const EdgeDuration duration, - const EdgeDistance distance, - typename SearchEngineData::ManyToManyQueryHeap &query_heap, - Args... args) +void relaxOutgoingEdges( + const DataFacade &facade, + const typename SearchEngineData::ManyToManyQueryHeap::HeapNode &heapNode, + typename SearchEngineData::ManyToManyQueryHeap &query_heap, + Args... args) { - BOOST_ASSERT(!facade.ExcludeNode(node)); + BOOST_ASSERT(!facade.ExcludeNode(heapNode.node)); const auto &partition = facade.GetMultiLevelPartition(); - const auto level = getNodeQueryLevel(partition, node, args...); + const auto level = getNodeQueryLevel(partition, heapNode.node, args...); // Break outgoing edges relaxation if node at the restricted level if (level == INVALID_LEVEL_ID) @@ -110,40 +110,42 @@ void relaxOutgoingEdges(const DataFacade &facade, const auto &cells = facade.GetCellStorage(); const auto &metric = facade.GetCellMetric(); - const auto &node_data = query_heap.GetData(node); - if (level >= 1 && !node_data.from_clique_arc) + if (level >= 1 && !heapNode.data.from_clique_arc) { - const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node)); + const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); if (DIRECTION == FORWARD_DIRECTION) { // Shortcuts in forward direction auto destination = cell.GetDestinationNodes().begin(); - auto shortcut_durations = cell.GetOutDuration(node); - auto shortcut_distances = cell.GetOutDistance(node); - for (auto shortcut_weight : cell.GetOutWeight(node)) + auto shortcut_durations = cell.GetOutDuration(heapNode.node); + auto shortcut_distances = cell.GetOutDistance(heapNode.node); + for (auto shortcut_weight : cell.GetOutWeight(heapNode.node)) { BOOST_ASSERT(destination != cell.GetDestinationNodes().end()); BOOST_ASSERT(!shortcut_durations.empty()); BOOST_ASSERT(!shortcut_distances.empty()); const NodeID to = *destination; - if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to) + if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to) { - const auto to_weight = weight + shortcut_weight; - const auto to_duration = duration + shortcut_durations.front(); - const auto to_distance = distance + shortcut_distances.front(); - if (!query_heap.WasInserted(to)) + const auto to_weight = heapNode.weight + shortcut_weight; + const auto to_duration = heapNode.data.duration + shortcut_durations.front(); + const auto to_distance = heapNode.data.distance + shortcut_distances.front(); + const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to); + if (!toHeapNode) { - query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance}); + query_heap.Insert( + to, to_weight, {heapNode.node, true, to_duration, to_distance}); } - else if (std::tie(to_weight, to_duration, to_distance, node) < - std::tie(query_heap.GetKey(to), - query_heap.GetData(to).duration, - query_heap.GetData(to).distance, - query_heap.GetData(to).parent)) + else if (std::tie(to_weight, to_duration, to_distance, heapNode.node) < + std::tie(toHeapNode->weight, + toHeapNode->data.duration, + toHeapNode->data.distance, + toHeapNode->data.parent)) { - query_heap.GetData(to) = {node, true, to_duration, to_distance}; - query_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {heapNode.node, true, to_duration, to_distance}; + toHeapNode->weight = to_weight; + query_heap.DecreaseKey(*toHeapNode); } } ++destination; @@ -156,32 +158,35 @@ void relaxOutgoingEdges(const DataFacade &facade, else { // Shortcuts in backward direction auto source = cell.GetSourceNodes().begin(); - auto shortcut_durations = cell.GetInDuration(node); - auto shortcut_distances = cell.GetInDistance(node); - for (auto shortcut_weight : cell.GetInWeight(node)) + auto shortcut_durations = cell.GetInDuration(heapNode.node); + auto shortcut_distances = cell.GetInDistance(heapNode.node); + for (auto shortcut_weight : cell.GetInWeight(heapNode.node)) { BOOST_ASSERT(source != cell.GetSourceNodes().end()); BOOST_ASSERT(!shortcut_durations.empty()); BOOST_ASSERT(!shortcut_distances.empty()); const NodeID to = *source; - if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to) + if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to) { - const auto to_weight = weight + shortcut_weight; - const auto to_duration = duration + shortcut_durations.front(); - const auto to_distance = distance + shortcut_distances.front(); - if (!query_heap.WasInserted(to)) + const auto to_weight = heapNode.weight + shortcut_weight; + const auto to_duration = heapNode.data.duration + shortcut_durations.front(); + const auto to_distance = heapNode.data.distance + shortcut_distances.front(); + const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to); + if (!toHeapNode) { - query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance}); + query_heap.Insert( + to, to_weight, {heapNode.node, true, to_duration, to_distance}); } - else if (std::tie(to_weight, to_duration, to_distance, node) < - std::tie(query_heap.GetKey(to), - query_heap.GetData(to).duration, - query_heap.GetData(to).distance, - query_heap.GetData(to).parent)) + else if (std::tie(to_weight, to_duration, to_distance, heapNode.node) < + std::tie(toHeapNode->weight, + toHeapNode->data.duration, + toHeapNode->data.distance, + toHeapNode->data.parent)) { - query_heap.GetData(to) = {node, true, to_duration, to_distance}; - query_heap.DecreaseKey(to, to_weight); + toHeapNode->data = {heapNode.node, true, to_duration, to_distance}; + toHeapNode->weight = to_weight; + query_heap.DecreaseKey(*toHeapNode); } } ++source; @@ -193,7 +198,13 @@ void relaxOutgoingEdges(const DataFacade &facade, } } - relaxBorderEdges(facade, node, weight, duration, distance, query_heap, level); + relaxBorderEdges(facade, + heapNode.node, + heapNode.weight, + heapNode.data.duration, + heapNode.data.distance, + query_heap, + level); } // @@ -368,25 +379,17 @@ oneToManySearch(SearchEngineData &engine_working_data, while (!query_heap.Empty() && !target_nodes_index.empty()) { - // Extract node from the heap - const auto node = query_heap.DeleteMin(); - const auto weight = query_heap.GetKey(node); - const auto duration = query_heap.GetData(node).duration; - const auto distance = query_heap.GetData(node).distance; + // Extract node from the heap. Take a copy (no ref) because otherwise can be modified later + // if toHeapNode is the same + const auto heapNode = query_heap.DeleteMinGetHeapNode(); // Update values - update_values(node, weight, duration, distance); + update_values( + heapNode.node, heapNode.weight, heapNode.data.duration, heapNode.data.distance); // Relax outgoing edges - relaxOutgoingEdges(facade, - node, - weight, - duration, - distance, - query_heap, - phantom_nodes, - phantom_index, - phantom_indices); + relaxOutgoingEdges( + facade, heapNode, query_heap, phantom_nodes, phantom_index, phantom_indices); } return std::make_pair(durations, distances_table); @@ -408,15 +411,14 @@ void forwardRoutingStep(const DataFacade &facade, std::vector &middle_nodes_table, const PhantomNode &phantom_node) { - const auto node = query_heap.DeleteMin(); - const auto source_weight = query_heap.GetKey(node); - const auto source_duration = query_heap.GetData(node).duration; - const auto source_distance = query_heap.GetData(node).distance; + // Take a copy of the extracted node because otherwise could be modified later if toHeapNode is + // the same + const auto heapNode = query_heap.DeleteMinGetHeapNode(); // Check if each encountered node has an entry const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(), search_space_with_buckets.end(), - node, + heapNode.node, NodeBucket::Compare()); for (const auto ¤t_bucket : boost::make_iterator_range(bucket_list)) { @@ -439,9 +441,9 @@ void forwardRoutingStep(const DataFacade &facade, auto ¤t_distance = distances_table.empty() ? nulldistance : distances_table[location]; // Check if new weight is better - auto new_weight = source_weight + target_weight; - auto new_duration = source_duration + target_duration; - auto new_distance = source_distance + target_distance; + auto new_weight = heapNode.weight + target_weight; + auto new_duration = heapNode.data.duration + target_duration; + auto new_distance = heapNode.data.distance + target_distance; if (new_weight >= 0 && std::tie(new_weight, new_duration, new_distance) < std::tie(current_weight, current_duration, current_distance)) @@ -449,12 +451,11 @@ void forwardRoutingStep(const DataFacade &facade, current_weight = new_weight; current_duration = new_duration; current_distance = new_distance; - middle_nodes_table[location] = node; + middle_nodes_table[location] = heapNode.node; } } - relaxOutgoingEdges( - facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node); + relaxOutgoingEdges(facade, heapNode, query_heap, phantom_node); } template @@ -464,28 +465,23 @@ void backwardRoutingStep(const DataFacade &facade, std::vector &search_space_with_buckets, const PhantomNode &phantom_node) { - const auto node = query_heap.DeleteMin(); - const auto target_weight = query_heap.GetKey(node); - const auto target_duration = query_heap.GetData(node).duration; - const auto target_distance = query_heap.GetData(node).distance; - const auto parent = query_heap.GetData(node).parent; - const auto from_clique_arc = query_heap.GetData(node).from_clique_arc; + // Take a copy of the extracted node because otherwise could be modified later if toHeapNode is + // the same + const auto heapNode = query_heap.DeleteMinGetHeapNode(); // Store settled nodes in search space bucket - search_space_with_buckets.emplace_back( - node, parent, from_clique_arc, column_idx, target_weight, target_duration, target_distance); + search_space_with_buckets.emplace_back(heapNode.node, + heapNode.data.parent, + heapNode.data.from_clique_arc, + column_idx, + heapNode.weight, + heapNode.data.duration, + heapNode.data.distance); const auto &partition = facade.GetMultiLevelPartition(); const auto maximal_level = partition.GetNumberOfLevels() - 1; - relaxOutgoingEdges(facade, - node, - target_weight, - target_duration, - target_distance, - query_heap, - phantom_node, - maximal_level); + relaxOutgoingEdges(facade, heapNode, query_heap, phantom_node, maximal_level); } template