diff --git a/routing_algorithms/direct_shortest_path.hpp b/routing_algorithms/direct_shortest_path.hpp index c64264e4a..09e39c73e 100644 --- a/routing_algorithms/direct_shortest_path.hpp +++ b/routing_algorithms/direct_shortest_path.hpp @@ -64,143 +64,39 @@ class DirectShortestPathRouting final { (void)uturn_indicators; // unused - engine_working_data.InitializeOrClearFirstThreadLocalStorage( - super::facade->GetNumberOfNodes()); - engine_working_data.InitializeOrClearSecondThreadLocalStorage( - super::facade->GetNumberOfNodes()); - - QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); - QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); - - QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2); - QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2); - // Get distance to next pair of target nodes. BOOST_ASSERT_MSG(1 == phantom_nodes_vector.size(), "Direct Shortest Path Query only accepts a single source and target pair. Multiple ones have been specified."); - const auto& phantom_node_pair = phantom_nodes_vector.front(); + engine_working_data.InitializeOrClearFirstThreadLocalStorage( + super::facade->GetNumberOfNodes()); + QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); forward_heap.Clear(); reverse_heap.Clear(); - int distance = INVALID_EDGE_WEIGHT; - NodeID middle = SPECIAL_NODEID; - const EdgeWeight min_edge_offset = - std::min(-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), - -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); + int distance; + std::vector packed_leg; - // insert new starting nodes into forward heap, adjusted by previous distances. - if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID) + if (super::facade->GetCoreSize() > 0) { - forward_heap.Insert( - phantom_node_pair.source_phantom.forward_node_id, - -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), - phantom_node_pair.source_phantom.forward_node_id); + engine_working_data.InitializeOrClearSecondThreadLocalStorage( + super::facade->GetNumberOfNodes()); + QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2); + QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2); + forward_core_heap.Clear(); + reverse_core_heap.Clear(); + + + super::SearchWithCore(forward_heap, reverse_heap, forward_core_heap, reverse_core_heap, + phantom_node_pair.source_phantom, phantom_node_pair.target_phantom, + distance, packed_leg); } - if ( phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID) + else { - forward_heap.Insert( - phantom_node_pair.source_phantom.reverse_node_id, - -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), - phantom_node_pair.source_phantom.reverse_node_id); - } - - // insert new backward nodes into backward heap, unadjusted. - if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID) - { - reverse_heap.Insert(phantom_node_pair.target_phantom.forward_node_id, - phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), - phantom_node_pair.target_phantom.forward_node_id); - } - - if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID) - { - reverse_heap.Insert(phantom_node_pair.target_phantom.reverse_node_id, - phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), - phantom_node_pair.target_phantom.reverse_node_id); - } - - std::vector> forward_entry_points; - std::vector> reverse_entry_points; - - // run two-Target Dijkstra routing step. - while (0 < (forward_heap.Size() + reverse_heap.Size()) ) - { - if (!forward_heap.Empty()) - { - if (super::facade->IsCoreNode(forward_heap.Min())) - { - const NodeID node = forward_heap.DeleteMin(); - const int key = forward_heap.GetKey(node); - forward_entry_points.emplace_back(node, key); - } - else - { - super::RoutingStep(forward_heap, reverse_heap, &middle, &distance, - min_edge_offset, true); - } - } - if (!reverse_heap.Empty()) - { - if (super::facade->IsCoreNode(reverse_heap.Min())) - { - const NodeID node = reverse_heap.DeleteMin(); - const int key = reverse_heap.GetKey(node); - reverse_entry_points.emplace_back(node, key); - } - else - { - super::RoutingStep(reverse_heap, forward_heap, &middle, &distance, - min_edge_offset, false); - } - } - } - - // TODO check if unordered_set might be faster - // sort by id and increasing by distance - auto entry_point_comparator = [](const std::pair& lhs, const std::pair& rhs) - { - return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second); - }; - std::sort(forward_entry_points.begin(), forward_entry_points.end(), entry_point_comparator); - std::sort(reverse_entry_points.begin(), reverse_entry_points.end(), entry_point_comparator); - - NodeID last_id = SPECIAL_NODEID; - for (const auto p : forward_entry_points) - { - if (p.first == last_id) - { - continue; - } - forward_core_heap.Insert(p.first, p.second, p.first); - last_id = p.first; - } - last_id = SPECIAL_NODEID; - for (const auto p : reverse_entry_points) - { - if (p.first == last_id) - { - continue; - } - reverse_core_heap.Insert(p.first, p.second, p.first); - last_id = p.first; - } - - // run two-target Dijkstra routing step on core with termination criterion - while (0 < (forward_core_heap.Size() + reverse_core_heap.Size()) && - distance > (forward_core_heap.MinKey() + reverse_core_heap.MinKey())) - { - if (!forward_core_heap.Empty()) - { - super::RoutingStep(forward_core_heap, reverse_core_heap, &middle, &distance, - min_edge_offset, true, false); - } - if (!reverse_core_heap.Empty()) - { - super::RoutingStep(reverse_core_heap, forward_core_heap, &middle, &distance, - min_edge_offset, false, false); - } + super::Search(forward_heap, reverse_heap, phantom_node_pair.source_phantom, + phantom_node_pair.target_phantom, distance, packed_leg); } // No path found for both target nodes? @@ -211,30 +107,9 @@ class DirectShortestPathRouting final return; } - // Was a paths over one of the forward/reverse nodes not found? - BOOST_ASSERT_MSG((SPECIAL_NODEID == middle || INVALID_EDGE_WEIGHT != distance), - "no path found"); - - std::vector packed_leg; - // we need to unpack sub path from core heaps - if(super::facade->IsCoreNode(middle)) - { - std::vector packed_core_leg; - super::RetrievePackedPathFromHeap(forward_core_heap, reverse_core_heap, middle, packed_core_leg); - BOOST_ASSERT(packed_core_leg.size() > 0); - super::RetrievePackedPathFromSingleHeap(forward_heap, packed_core_leg.front(), packed_leg); - std::reverse(packed_leg.begin(), packed_leg.end()); - packed_leg.insert(packed_leg.end(), packed_core_leg.begin(), packed_core_leg.end()); - super::RetrievePackedPathFromSingleHeap(reverse_heap, packed_core_leg.back(), packed_leg); - } - else - { - super::RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); - } - - BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty"); + raw_route_data.shortest_path_length = distance; raw_route_data.unpacked_path_segments.resize(1); raw_route_data.source_traversed_in_reverse.push_back( (packed_leg.front() != phantom_node_pair.source_phantom.forward_node_id)); @@ -243,7 +118,6 @@ class DirectShortestPathRouting final super::UnpackPath(packed_leg, phantom_node_pair, raw_route_data.unpacked_path_segments.front()); - raw_route_data.shortest_path_length = distance; } }; diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index e43d6b725..360950d20 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_base.hpp @@ -416,6 +416,234 @@ template class BasicRoutingInterface } } + // assumes that heaps are already setup correctly. + void Search(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + int &distance, + std::vector &packed_leg) const + { + NodeID middle = SPECIAL_NODEID; + + const EdgeWeight min_edge_offset = std::min(-source_phantom.GetForwardWeightPlusOffset(), + -source_phantom.GetReverseWeightPlusOffset()); + + // insert new starting nodes into forward heap, adjusted by previous distances. + if (source_phantom.forward_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.forward_node_id, + -source_phantom.GetForwardWeightPlusOffset(), + source_phantom.forward_node_id); + } + if (source_phantom.reverse_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.reverse_node_id, + -source_phantom.GetReverseWeightPlusOffset(), + source_phantom.reverse_node_id); + } + + // insert new backward nodes into backward heap, unadjusted. + if (target_phantom.forward_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.forward_node_id, + target_phantom.GetForwardWeightPlusOffset(), + target_phantom.forward_node_id); + } + + if (target_phantom.reverse_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.reverse_node_id, + target_phantom.GetReverseWeightPlusOffset(), + target_phantom.reverse_node_id); + } + + std::vector> forward_entry_points; + std::vector> reverse_entry_points; + + // run two-Target Dijkstra routing step. + while (0 < (forward_heap.Size() + reverse_heap.Size())) + { + if (!forward_heap.Empty()) + { + RoutingStep(forward_heap, reverse_heap, &middle, &distance, min_edge_offset, + true); + } + if (!reverse_heap.Empty()) + { + RoutingStep(reverse_heap, forward_heap, &middle, &distance, min_edge_offset, + false); + } + } + + // No path found for both target nodes? + if (INVALID_EDGE_WEIGHT == distance) + { + return; + } + + // Was a paths over one of the forward/reverse nodes not found? + BOOST_ASSERT_MSG((SPECIAL_NODEID == middle || INVALID_EDGE_WEIGHT != distance), + "no path found"); + + RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); + } + + // assumes that heaps are already setup correctly. + void SearchWithCore(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + SearchEngineData::QueryHeap &forward_core_heap, + SearchEngineData::QueryHeap &reverse_core_heap, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + int &distance, + std::vector &packed_leg) const + { + NodeID middle = SPECIAL_NODEID; + + const EdgeWeight min_edge_offset = std::min(-source_phantom.GetForwardWeightPlusOffset(), + -source_phantom.GetReverseWeightPlusOffset()); + + // insert new starting nodes into forward heap, adjusted by previous distances. + if (source_phantom.forward_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.forward_node_id, + -source_phantom.GetForwardWeightPlusOffset(), + source_phantom.forward_node_id); + } + if (source_phantom.reverse_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.reverse_node_id, + -source_phantom.GetReverseWeightPlusOffset(), + source_phantom.reverse_node_id); + } + + // insert new backward nodes into backward heap, unadjusted. + if (target_phantom.forward_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.forward_node_id, + target_phantom.GetForwardWeightPlusOffset(), + target_phantom.forward_node_id); + } + + if (target_phantom.reverse_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.reverse_node_id, + target_phantom.GetReverseWeightPlusOffset(), + target_phantom.reverse_node_id); + } + + std::vector> forward_entry_points; + std::vector> reverse_entry_points; + + // run two-Target Dijkstra routing step. + while (0 < (forward_heap.Size() + reverse_heap.Size())) + { + if (!forward_heap.Empty()) + { + if (facade->IsCoreNode(forward_heap.Min())) + { + const NodeID node = forward_heap.DeleteMin(); + const int key = forward_heap.GetKey(node); + forward_entry_points.emplace_back(node, key); + } + else + { + RoutingStep(forward_heap, reverse_heap, &middle, &distance, min_edge_offset, + true); + } + } + if (!reverse_heap.Empty()) + { + if (facade->IsCoreNode(reverse_heap.Min())) + { + const NodeID node = reverse_heap.DeleteMin(); + const int key = reverse_heap.GetKey(node); + reverse_entry_points.emplace_back(node, key); + } + else + { + RoutingStep(reverse_heap, forward_heap, &middle, &distance, min_edge_offset, + false); + } + } + } + + // TODO check if unordered_set might be faster + // sort by id and increasing by distance + auto entry_point_comparator = [](const std::pair &lhs, + const std::pair &rhs) + { + return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second); + }; + std::sort(forward_entry_points.begin(), forward_entry_points.end(), entry_point_comparator); + std::sort(reverse_entry_points.begin(), reverse_entry_points.end(), entry_point_comparator); + + NodeID last_id = SPECIAL_NODEID; + for (const auto p : forward_entry_points) + { + if (p.first == last_id) + { + continue; + } + forward_core_heap.Insert(p.first, p.second, p.first); + last_id = p.first; + } + last_id = SPECIAL_NODEID; + for (const auto p : reverse_entry_points) + { + if (p.first == last_id) + { + continue; + } + reverse_core_heap.Insert(p.first, p.second, p.first); + last_id = p.first; + } + + // run two-target Dijkstra routing step on core with termination criterion + while (0 < (forward_core_heap.Size() + reverse_core_heap.Size()) && + distance > (forward_core_heap.MinKey() + reverse_core_heap.MinKey())) + { + if (!forward_core_heap.Empty()) + { + RoutingStep(forward_core_heap, reverse_core_heap, &middle, &distance, + min_edge_offset, true, false); + } + if (!reverse_core_heap.Empty()) + { + RoutingStep(reverse_core_heap, forward_core_heap, &middle, &distance, + min_edge_offset, false, false); + } + } + + // No path found for both target nodes? + if (INVALID_EDGE_WEIGHT == distance) + { + return; + } + + // Was a paths over one of the forward/reverse nodes not found? + BOOST_ASSERT_MSG((SPECIAL_NODEID == middle || INVALID_EDGE_WEIGHT != distance), + "no path found"); + + // we need to unpack sub path from core heaps + if (facade->IsCoreNode(middle)) + { + std::vector packed_core_leg; + RetrievePackedPathFromHeap(forward_core_heap, reverse_core_heap, middle, + packed_core_leg); + BOOST_ASSERT(packed_core_leg.size() > 0); + RetrievePackedPathFromSingleHeap(forward_heap, packed_core_leg.front(), packed_leg); + std::reverse(packed_leg.begin(), packed_leg.end()); + packed_leg.insert(packed_leg.end(), packed_core_leg.begin(), packed_core_leg.end()); + RetrievePackedPathFromSingleHeap(reverse_heap, packed_core_leg.back(), packed_leg); + } + else + { + RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); + } + } + double get_network_distance(SearchEngineData::QueryHeap &forward_heap, SearchEngineData::QueryHeap &reverse_heap, const PhantomNode &source_phantom, diff --git a/server/data_structures/datafacade_base.hpp b/server/data_structures/datafacade_base.hpp index 691c6f326..86155d8eb 100644 --- a/server/data_structures/datafacade_base.hpp +++ b/server/data_structures/datafacade_base.hpp @@ -118,6 +118,8 @@ template class BaseDataFacade virtual std::string get_name_for_id(const unsigned name_id) const = 0; + virtual std::size_t GetCoreSize() const = 0; + virtual std::string GetTimestamp() const = 0; }; diff --git a/server/data_structures/internal_datafacade.hpp b/server/data_structures/internal_datafacade.hpp index 7d279e8a2..b8c8e97e6 100644 --- a/server/data_structures/internal_datafacade.hpp +++ b/server/data_structures/internal_datafacade.hpp @@ -447,6 +447,11 @@ template class InternalDataFacade final : public BaseDataFacad return m_via_node_list.at(id); } + virtual std::size_t GetCoreSize() const override final + { + return m_is_core_node.size(); + } + virtual bool IsCoreNode(const NodeID id) const override final { if (m_is_core_node.size() > 0) diff --git a/server/data_structures/shared_datafacade.hpp b/server/data_structures/shared_datafacade.hpp index 1c929c33b..f3e02fc3f 100644 --- a/server/data_structures/shared_datafacade.hpp +++ b/server/data_structures/shared_datafacade.hpp @@ -473,6 +473,11 @@ template class SharedDataFacade final : public BaseDataFacade< return false; } + virtual std::size_t GetCoreSize() const override final + { + return m_is_core_node.size(); + } + std::string GetTimestamp() const override final { return m_timestamp; } };