From 35342030833fdc5e2a0c0ab854b5ebba4093e8ef Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Fri, 30 Jun 2017 23:45:00 +0200 Subject: [PATCH] Generalize manyToManySearch and remove duplications --- include/engine/routing_algorithms.hpp | 3 +- .../routing_algorithms/many_to_many.hpp | 14 +- .../routing_algorithms/many_to_many.cpp | 266 +++++------------- 3 files changed, 79 insertions(+), 204 deletions(-) diff --git a/include/engine/routing_algorithms.hpp b/include/engine/routing_algorithms.hpp index da7a216b0..e964028cf 100644 --- a/include/engine/routing_algorithms.hpp +++ b/include/engine/routing_algorithms.hpp @@ -157,7 +157,8 @@ RoutingAlgorithms::ManyToManySearch(const std::vector &p const std::vector &source_indices, const std::vector &target_indices) const { - return manyToManySearch(heaps, facade, phantom_nodes, source_indices, target_indices); + return routing_algorithms::manyToManySearch( + heaps, facade, phantom_nodes, source_indices, target_indices); } template diff --git a/include/engine/routing_algorithms/many_to_many.hpp b/include/engine/routing_algorithms/many_to_many.hpp index f036ecf99..a043aee33 100644 --- a/include/engine/routing_algorithms/many_to_many.hpp +++ b/include/engine/routing_algorithms/many_to_many.hpp @@ -16,25 +16,13 @@ namespace engine namespace routing_algorithms { -namespace ch -{ +template std::vector manyToManySearch(SearchEngineData &engine_working_data, const datafacade::ContiguousInternalMemoryDataFacade &facade, const std::vector &phantom_nodes, const std::vector &source_indices, const std::vector &target_indices); -} // namespace ch - -namespace mld -{ -std::vector -manyToManySearch(SearchEngineData &engine_working_data, - const datafacade::ContiguousInternalMemoryDataFacade &facade, - const std::vector &phantom_nodes, - const std::vector &source_indices, - const std::vector &target_indices); -} // namespace mld } // namespace routing_algorithms } // namespace engine diff --git a/src/engine/routing_algorithms/many_to_many.cpp b/src/engine/routing_algorithms/many_to_many.cpp index b0b6b9281..1b6cb5dce 100644 --- a/src/engine/routing_algorithms/many_to_many.cpp +++ b/src/engine/routing_algorithms/many_to_many.cpp @@ -27,20 +27,46 @@ struct NodeBucket { } }; -} // FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking using SearchSpaceWithBuckets = std::unordered_map>; -namespace ch -{ +inline bool +addLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const NodeID node, + EdgeWeight &weight, + EdgeDuration &duration) +{ // Special case for CH when contractor creates a loop edge node->node + BOOST_ASSERT(weight < 0); + + const auto loop_weight = ch::getLoopWeight(facade, node); + if (loop_weight != INVALID_EDGE_WEIGHT) + { + const auto new_weight_with_loop = weight + loop_weight; + if (new_weight_with_loop >= 0) + { + weight = new_weight_with_loop; + duration += ch::getLoopWeight(facade, node); + return true; + } + } + + // No loop found or adjusted weight is negative + return false; +} + template -void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &facade, +void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &facade, const NodeID node, const EdgeWeight weight, - const EdgeWeight duration, - typename SearchEngineData::ManyToManyQueryHeap &query_heap) + const EdgeDuration duration, + typename SearchEngineData::ManyToManyQueryHeap &query_heap) { + if (ch::stallAtNode(facade, node, weight, query_heap)) + { + return; + } + for (auto edge : facade.GetAdjacentEdgeRange(node)) { const auto &data = facade.GetEdgeData(edge); @@ -70,186 +96,22 @@ void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &facade, - const unsigned row_idx, - const unsigned number_of_targets, - typename SearchEngineData::ManyToManyQueryHeap &query_heap, - const SearchSpaceWithBuckets &search_space_with_buckets, - std::vector &weights_table, - std::vector &durations_table) -{ - const NodeID node = query_heap.DeleteMin(); - const EdgeWeight source_weight = query_heap.GetKey(node); - const EdgeWeight source_duration = query_heap.GetData(node).duration; - // check if each encountered node has an entry - const auto bucket_iterator = search_space_with_buckets.find(node); - // iterate bucket if there exists one - if (bucket_iterator != search_space_with_buckets.end()) - { - const std::vector &bucket_list = bucket_iterator->second; - for (const NodeBucket ¤t_bucket : bucket_list) - { - // get target id from bucket entry - const unsigned column_idx = current_bucket.target_id; - const EdgeWeight target_weight = current_bucket.weight; - const EdgeWeight target_duration = current_bucket.duration; - - auto ¤t_weight = weights_table[row_idx * number_of_targets + column_idx]; - auto ¤t_duration = durations_table[row_idx * number_of_targets + column_idx]; - - // check if new weight is better - const EdgeWeight new_weight = source_weight + target_weight; - if (new_weight < 0) - { - const EdgeWeight loop_weight = ch::getLoopWeight(facade, node); - const EdgeWeight new_weight_with_loop = new_weight + loop_weight; - if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0) - { - current_weight = std::min(current_weight, new_weight_with_loop); - current_duration = std::min(current_duration, - source_duration + target_duration + - ch::getLoopWeight(facade, node)); - } - } - else if (new_weight < current_weight) - { - current_weight = new_weight; - current_duration = source_duration + target_duration; - } - } - } - if (ch::stallAtNode(facade, node, source_weight, query_heap)) - { - return; - } - - relaxOutgoingEdges(facade, node, source_weight, source_duration, query_heap); +inline bool addLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade &, + const NodeID, + EdgeWeight &, + EdgeDuration &) +{ // MLD overlay does not introduce loop edges + return false; } -void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, - const unsigned column_idx, - typename SearchEngineData::ManyToManyQueryHeap &query_heap, - SearchSpaceWithBuckets &search_space_with_buckets) -{ - const NodeID node = query_heap.DeleteMin(); - const EdgeWeight target_weight = query_heap.GetKey(node); - const EdgeWeight target_duration = query_heap.GetData(node).duration; - - // store settled nodes in search space bucket - search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration); - - if (ch::stallAtNode(facade, node, target_weight, query_heap)) - { - return; - } - - relaxOutgoingEdges(facade, node, target_weight, target_duration, query_heap); -} - -std::vector -manyToManySearch(SearchEngineData &engine_working_data, - const datafacade::ContiguousInternalMemoryDataFacade &facade, - const std::vector &phantom_nodes, - const std::vector &source_indices, - const std::vector &target_indices) -{ - const auto number_of_sources = - source_indices.empty() ? phantom_nodes.size() : source_indices.size(); - const auto number_of_targets = - target_indices.empty() ? phantom_nodes.size() : target_indices.size(); - const auto number_of_entries = number_of_sources * number_of_targets; - - std::vector weights_table(number_of_entries, INVALID_EDGE_WEIGHT); - std::vector durations_table(number_of_entries, MAXIMAL_EDGE_DURATION); - - engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes()); - - auto &query_heap = *(engine_working_data.many_to_many_heap); - - SearchSpaceWithBuckets search_space_with_buckets; - - unsigned column_idx = 0; - const auto search_target_phantom = [&](const PhantomNode &phantom) { - // clear heap and insert target nodes - query_heap.Clear(); - insertTargetInHeap(query_heap, phantom); - - // explore search space - while (!query_heap.Empty()) - { - backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets); - } - ++column_idx; - }; - - // for each source do forward search - unsigned row_idx = 0; - const auto search_source_phantom = [&](const PhantomNode &phantom) { - // clear heap and insert source nodes - query_heap.Clear(); - insertSourceInHeap(query_heap, phantom); - - // explore search space - while (!query_heap.Empty()) - { - forwardRoutingStep(facade, - row_idx, - number_of_targets, - query_heap, - search_space_with_buckets, - weights_table, - durations_table); - } - ++row_idx; - }; - - if (target_indices.empty()) - { - for (const auto &phantom : phantom_nodes) - { - search_target_phantom(phantom); - } - } - else - { - for (const auto index : target_indices) - { - const auto &phantom = phantom_nodes[index]; - search_target_phantom(phantom); - } - } - - if (source_indices.empty()) - { - for (const auto &phantom : phantom_nodes) - { - search_source_phantom(phantom); - } - } - else - { - for (const auto index : source_indices) - { - const auto &phantom = phantom_nodes[index]; - search_source_phantom(phantom); - } - } - - return durations_table; -} - -} // namespace ch - -// TODO: generalize with CH version -namespace mld -{ template -void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &facade, - const NodeID node, - const EdgeWeight weight, - const EdgeWeight duration, - typename SearchEngineData::ManyToManyQueryHeap &query_heap) +void relaxOutgoingEdges( + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const NodeID node, + const EdgeWeight weight, + const EdgeDuration duration, + typename SearchEngineData::ManyToManyQueryHeap &query_heap) { const auto &partition = facade.GetMultiLevelPartition(); const auto &cells = facade.GetCellStorage(); @@ -262,8 +124,7 @@ void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, const unsigned row_idx, const unsigned number_of_targets, @@ -379,11 +240,21 @@ void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade= 0 && new_weight < current_weight) + auto new_weight = source_weight + target_weight; + auto new_duration = source_duration + target_duration; + + if (new_weight < 0) + { + if (addLoopWeight(facade, node, new_weight, new_duration)) + { + current_weight = std::min(current_weight, new_weight); + current_duration = std::min(current_duration, new_duration); + } + } + else if (new_weight < current_weight) { current_weight = new_weight; - current_duration = source_duration + target_duration; + current_duration = new_duration; } } } @@ -391,6 +262,7 @@ void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade(facade, node, source_weight, source_duration, query_heap); } +template void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, const unsigned column_idx, typename SearchEngineData::ManyToManyQueryHeap &query_heap, @@ -405,7 +277,9 @@ void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade(facade, node, target_weight, target_duration, query_heap); } +} +template std::vector manyToManySearch(SearchEngineData &engine_working_data, const datafacade::ContiguousInternalMemoryDataFacade &facade, @@ -498,7 +372,19 @@ manyToManySearch(SearchEngineData &engine_working_data, return durations_table; } -} // namespace mld +template std::vector +manyToManySearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes, + const std::vector &source_indices, + const std::vector &target_indices); + +template std::vector +manyToManySearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes, + const std::vector &source_indices, + const std::vector &target_indices); } // namespace routing_algorithms } // namespace engine