diff --git a/include/engine/algorithm.hpp b/include/engine/algorithm.hpp index fa41129fe..43477f86a 100644 --- a/include/engine/algorithm.hpp +++ b/include/engine/algorithm.hpp @@ -11,29 +11,75 @@ namespace algorithm { // Contraction Hiearchy -struct CH final {}; +struct CH final +{ +}; // Contraction Hiearchy with core -struct CoreCH final {}; - +struct CoreCH final +{ +}; } namespace algorithm_trais { -template struct HasAlternativePathSearch final : std::false_type {}; -template struct HasShortestPathSearch final : std::false_type {}; -template struct HasDirectShortestPathSearch final : std::false_type {}; -template struct HasMapMatching final : std::false_type {}; -template struct HasManyToManySearch final : std::false_type {}; -template struct HasGetTileTurns final : std::false_type {}; +template struct HasAlternativePathSearch final : std::false_type +{ +}; +template struct HasShortestPathSearch final : std::false_type +{ +}; +template struct HasDirectShortestPathSearch final : std::false_type +{ +}; +template struct HasMapMatching final : std::false_type +{ +}; +template struct HasManyToManySearch final : std::false_type +{ +}; +template struct HasGetTileTurns final : std::false_type +{ +}; -template <> struct HasAlternativePathSearch final : std::true_type {}; -template <> struct HasShortestPathSearch final : std::true_type {}; -template <> struct HasDirectShortestPathSearch final : std::true_type {}; -template <> struct HasMapMatching final : std::true_type {}; -template <> struct HasManyToManySearch final : std::true_type {}; -template <> struct HasGetTileTurns final : std::true_type {}; +template <> struct HasAlternativePathSearch final : std::true_type +{ +}; +template <> struct HasShortestPathSearch final : std::true_type +{ +}; +template <> struct HasDirectShortestPathSearch final : std::true_type +{ +}; +template <> struct HasMapMatching final : std::true_type +{ +}; +template <> struct HasManyToManySearch final : std::true_type +{ +}; +template <> struct HasGetTileTurns final : std::true_type +{ +}; +// disbaled because of perfomance reasons +template <> struct HasAlternativePathSearch final : std::false_type +{ +}; +template <> struct HasManyToManySearch final : std::false_type +{ +}; +template <> struct HasShortestPathSearch final : std::true_type +{ +}; +template <> struct HasDirectShortestPathSearch final : std::true_type +{ +}; +template <> struct HasMapMatching final : std::true_type +{ +}; +template <> struct HasGetTileTurns final : std::true_type +{ +}; } } } diff --git a/include/engine/datafacade/algorithm_datafacade.hpp b/include/engine/datafacade/algorithm_datafacade.hpp index 8438149b8..004f33341 100644 --- a/include/engine/datafacade/algorithm_datafacade.hpp +++ b/include/engine/datafacade/algorithm_datafacade.hpp @@ -49,6 +49,12 @@ template <> class AlgorithmDataFacade virtual EdgeID FindSmallestEdge(const NodeID from, const NodeID to, const std::function filter) const = 0; +}; + +template <> class AlgorithmDataFacade +{ + public: + using EdgeData = contractor::QueryEdge::EdgeData; virtual bool IsCoreNode(const NodeID id) const = 0; diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 768c0586c..34f22490b 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -58,7 +58,6 @@ class ContiguousInternalMemoryAlgorithmDataFacade using GraphEdge = QueryGraph::EdgeArrayEntry; std::unique_ptr m_query_graph; - util::ShM::vector m_is_core_node; // allocator that keeps the allocation data std::shared_ptr allocator; @@ -78,15 +77,6 @@ class ContiguousInternalMemoryAlgorithmDataFacade m_query_graph.reset(new QueryGraph(node_list, edge_list)); } - void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block) - { - auto core_marker_ptr = - data_layout.GetBlockPtr(memory_block, storage::DataLayout::CH_CORE_MARKER); - util::ShM::vector is_core_node( - core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]); - m_is_core_node = std::move(is_core_node); - } - public: ContiguousInternalMemoryAlgorithmDataFacade( std::shared_ptr allocator_) @@ -98,21 +88,8 @@ class ContiguousInternalMemoryAlgorithmDataFacade void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block) { InitializeGraphPointer(data_layout, memory_block); - InitializeCoreInformationPointer(data_layout, memory_block); } - bool IsCoreNode(const NodeID id) const override final - { - if (m_is_core_node.size() > 0) - { - return m_is_core_node.at(id); - } - - return false; - } - - std::size_t GetCoreSize() const override final { return m_is_core_node.size(); } - // search graph access unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } @@ -164,6 +141,51 @@ class ContiguousInternalMemoryAlgorithmDataFacade } }; +template <> +class ContiguousInternalMemoryAlgorithmDataFacade + : public datafacade::AlgorithmDataFacade +{ + private: + util::ShM::vector m_is_core_node; + + // allocator that keeps the allocation data + std::shared_ptr allocator; + + void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block) + { + auto core_marker_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::CH_CORE_MARKER); + util::ShM::vector is_core_node( + core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]); + m_is_core_node = std::move(is_core_node); + } + + public: + ContiguousInternalMemoryAlgorithmDataFacade( + std::shared_ptr allocator_) + : allocator(std::move(allocator_)) + { + InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory()); + } + + void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block) + { + InitializeCoreInformationPointer(data_layout, memory_block); + } + + bool IsCoreNode(const NodeID id) const override final + { + if (m_is_core_node.size() > 0) + { + return m_is_core_node.at(id); + } + + return false; + } + + std::size_t GetCoreSize() const override final { return m_is_core_node.size(); } +}; + /** * This base class implements the Datafacade interface for accessing * data that's stored in a single large block of memory (RAM). @@ -1050,6 +1072,20 @@ class ContiguousInternalMemoryDataFacade { } }; + +template <> +class ContiguousInternalMemoryDataFacade final + : public ContiguousInternalMemoryDataFacade, + public ContiguousInternalMemoryAlgorithmDataFacade +{ + public: + ContiguousInternalMemoryDataFacade(std::shared_ptr allocator) + : ContiguousInternalMemoryDataFacade(allocator), + ContiguousInternalMemoryAlgorithmDataFacade(allocator) + + { + } +}; } } } diff --git a/include/engine/engine.hpp b/include/engine/engine.hpp index 87c5ab164..222000655 100644 --- a/include/engine/engine.hpp +++ b/include/engine/engine.hpp @@ -125,6 +125,8 @@ template class Engine final : public EngineInterface return tile_plugin.HandleRequest(*facade, algorithms, params, result); } + static bool CheckCompability(const EngineConfig &config); + private: std::unique_ptr> facade_provider; mutable SearchEngineData heaps; @@ -136,6 +138,54 @@ template class Engine final : public EngineInterface const plugins::MatchPlugin match_plugin; const plugins::TilePlugin tile_plugin; }; + +template <> bool Engine::CheckCompability(const EngineConfig &config) +{ + if (config.use_shared_memory) + { + storage::SharedMonitor barrier; + using mutex_type = typename decltype(barrier)::mutex_type; + boost::interprocess::scoped_lock current_region_lock(barrier.get_mutex()); + + auto mem = storage::makeSharedMemory(barrier.data().region); + auto layout = reinterpret_cast(mem->Ptr()); + return layout->GetBlockSize(storage::DataLayout::CH_GRAPH_NODE_LIST) > 0 && + layout->GetBlockSize(storage::DataLayout::CH_GRAPH_EDGE_LIST) > 0; + } + else + { + std::ifstream in(config.storage_config.hsgr_data_path.string().c_str()); + in.seekg(std::ios::end); + auto size = in.tellg(); + return size > 0; + } +} + +template <> bool Engine::CheckCompability(const EngineConfig &config) +{ + if (!Engine::CheckCompability(config)) + { + return false; + } + + if (config.use_shared_memory) + { + storage::SharedMonitor barrier; + using mutex_type = typename decltype(barrier)::mutex_type; + boost::interprocess::scoped_lock current_region_lock(barrier.get_mutex()); + + auto mem = storage::makeSharedMemory(barrier.data().region); + auto layout = reinterpret_cast(mem->Ptr()); + return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER) > 0; + } + else + { + std::ifstream in(config.storage_config.core_data_path.string().c_str()); + in.seekg(std::ios::end); + auto size = in.tellg(); + return size > 0; + } +} } } diff --git a/include/engine/routing_algorithms.hpp b/include/engine/routing_algorithms.hpp index ebff8b62c..b845f5397 100644 --- a/include/engine/routing_algorithms.hpp +++ b/include/engine/routing_algorithms.hpp @@ -19,19 +19,20 @@ namespace engine class RoutingAlgorithmsInterface { public: - virtual InternalRouteResult AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0; + virtual InternalRouteResult + AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0; virtual InternalRouteResult ShortestPathSearch(const std::vector &phantom_node_pair, - const boost::optional continue_straight_at_waypoint) const = 0; + const boost::optional continue_straight_at_waypoint) const = 0; virtual InternalRouteResult - DirectShortestPathSearch(const std::vector &phantom_node_pair) const = 0; + DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0; virtual std::vector ManyToManySearch(const std::vector &phantom_nodes, - const std::vector &source_indices, - const std::vector &target_indices) const = 0; + const std::vector &source_indices, + const std::vector &target_indices) const = 0; virtual routing_algorithms::SubMatchingList MapMatching(const routing_algorithms::CandidateLists &candidates_list, @@ -41,7 +42,7 @@ class RoutingAlgorithmsInterface virtual std::vector GetTileTurns(const std::vector &edges, - const std::vector &sorted_edge_indexes) const = 0; + const std::vector &sorted_edge_indexes) const = 0; virtual bool HasAlternativePathSearch() const = 0; virtual bool HasShortestPathSearch() const = 0; @@ -54,8 +55,9 @@ class RoutingAlgorithmsInterface namespace detail { -struct NotImplementedException : public std::runtime_error {}; - +struct NotImplementedException : public std::runtime_error +{ +}; } // Short-lived object passed to each plugin in request to wrap routing algorithms @@ -74,24 +76,24 @@ template class RoutingAlgorithms final : public RoutingAlg return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair); } - InternalRouteResult - ShortestPathSearch(const std::vector &phantom_node_pair, - const boost::optional continue_straight_at_waypoint) const final override + InternalRouteResult ShortestPathSearch( + const std::vector &phantom_node_pair, + const boost::optional continue_straight_at_waypoint) const final override { return routing_algorithms::shortestPathSearch( heaps, facade, phantom_node_pair, continue_straight_at_waypoint); } - InternalRouteResult DirectShortestPathSearch( - const std::vector &phantom_node_pair) const final override + InternalRouteResult + DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override { - return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_node_pair); + return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes); } std::vector ManyToManySearch(const std::vector &phantom_nodes, - const std::vector &source_indices, - const std::vector &target_indices) const final override + const std::vector &source_indices, + const std::vector &target_indices) const final override { return routing_algorithms::manyToManySearch( heaps, facade, phantom_nodes, source_indices, target_indices); @@ -113,7 +115,7 @@ template class RoutingAlgorithms final : public RoutingAlg std::vector GetTileTurns(const std::vector &edges, - const std::vector &sorted_edge_indexes) const final override + const std::vector &sorted_edge_indexes) const final override { return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes); } diff --git a/include/engine/routing_algorithms/direct_shortest_path.hpp b/include/engine/routing_algorithms/direct_shortest_path.hpp index 53e6c5e51..391a451a7 100644 --- a/include/engine/routing_algorithms/direct_shortest_path.hpp +++ b/include/engine/routing_algorithms/direct_shortest_path.hpp @@ -34,7 +34,12 @@ directShortestPathSearch(SearchEngineData &, InternalRouteResult directShortestPathSearch( SearchEngineData &engine_working_data, const datafacade::ContiguousInternalMemoryDataFacade &facade, - const std::vector &phantom_nodes_vector); + const PhantomNodes &phantom_nodes); + +InternalRouteResult directShortestPathSearch( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const PhantomNodes &phantom_nodes); } // namespace routing_algorithms } // namespace engine diff --git a/include/engine/routing_algorithms/map_matching.hpp b/include/engine/routing_algorithms/map_matching.hpp index 55d5712f2..61add6525 100644 --- a/include/engine/routing_algorithms/map_matching.hpp +++ b/include/engine/routing_algorithms/map_matching.hpp @@ -39,6 +39,14 @@ mapMatching(SearchEngineData &engine_working_data, const std::vector &trace_coordinates, const std::vector &trace_timestamps, const std::vector> &trace_gps_precision); + +SubMatchingList +mapMatching(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const CandidateLists &candidates_list, + const std::vector &trace_coordinates, + const std::vector &trace_timestamps, + const std::vector> &trace_gps_precision); } } } diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index f3dfa4452..77f16fed6 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -452,6 +452,28 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade const bool force_loop_reverse, const int duration_upper_bound = INVALID_EDGE_WEIGHT); +// Alias to be compatible with the overload for CoreCH that needs 4 heaps +inline void search(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + SearchEngineData::QueryHeap &, + SearchEngineData::QueryHeap &, + std::int32_t &weight, + std::vector &packed_leg, + const bool force_loop_forward, + const bool force_loop_reverse, + const int duration_upper_bound = INVALID_EDGE_WEIGHT) +{ + search(facade, + forward_heap, + reverse_heap, + weight, + packed_leg, + force_loop_forward, + force_loop_reverse, + duration_upper_bound); +} + // assumes that heaps are already setup correctly. // A forced loop might be necessary, if source and target are on the same segment. // If this is the case and the offsets of the respective direction are larger for the source @@ -461,16 +483,16 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade // && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) // requires // a force loop, if the heaps have been initialized with positive offsets. -void searchWithCore(const datafacade::ContiguousInternalMemoryDataFacade &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - SearchEngineData::QueryHeap &forward_core_heap, - SearchEngineData::QueryHeap &reverse_core_heap, - int &weight, - std::vector &packed_leg, - const bool force_loop_forward, - const bool force_loop_reverse, - int duration_upper_bound = INVALID_EDGE_WEIGHT); +void search(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + SearchEngineData::QueryHeap &forward_core_heap, + SearchEngineData::QueryHeap &reverse_core_heap, + int &weight, + std::vector &packed_leg, + const bool force_loop_forward, + const bool force_loop_reverse, + int duration_upper_bound = INVALID_EDGE_WEIGHT); bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom); @@ -484,15 +506,15 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, - 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 duration_upper_bound = INVALID_EDGE_WEIGHT); +double +getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + 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 duration_upper_bound = INVALID_EDGE_WEIGHT); // Requires the heaps for be empty // If heaps should be adjusted to be initialized outside of this function, @@ -505,6 +527,21 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + SearchEngineData::QueryHeap &, + SearchEngineData::QueryHeap &, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + int duration_upper_bound = INVALID_EDGE_WEIGHT) +{ + return getNetworkDistance( + facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound); +} + } // namespace routing_algorithms } // namespace engine } // namespace osrm diff --git a/include/engine/routing_algorithms/shortest_path.hpp b/include/engine/routing_algorithms/shortest_path.hpp index 2fbd5803d..bb6b67914 100644 --- a/include/engine/routing_algorithms/shortest_path.hpp +++ b/include/engine/routing_algorithms/shortest_path.hpp @@ -30,6 +30,12 @@ shortestPathSearch(SearchEngineData &engine_working_data, const std::vector &phantom_nodes_vector, const boost::optional continue_straight_at_waypoint); +InternalRouteResult +shortestPathSearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector, + const boost::optional continue_straight_at_waypoint); + } // namespace routing_algorithms } // namespace engine } // namespace osrm diff --git a/src/engine/plugins/match.cpp b/src/engine/plugins/match.cpp index a92948769..e4a32df2c 100644 --- a/src/engine/plugins/match.cpp +++ b/src/engine/plugins/match.cpp @@ -115,7 +115,9 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData { if (!algorithms.HasMapMatching()) { - return Error("NotImplemented", "Map matching is not implemented for the chosen search algorithm.", json_result); + return Error("NotImplemented", + "Map matching is not implemented for the chosen search algorithm.", + json_result); } BOOST_ASSERT(parameters.IsValid()); diff --git a/src/engine/plugins/table.cpp b/src/engine/plugins/table.cpp index fc5e5404d..b5d391276 100644 --- a/src/engine/plugins/table.cpp +++ b/src/engine/plugins/table.cpp @@ -35,7 +35,9 @@ Status TablePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData { if (!algorithms.HasManyToManySearch()) { - return Error("NotImplemented", "Many to many search is not implemented for the chosen search algorithm.", result); + return Error("NotImplemented", + "Many to many search is not implemented for the chosen search algorithm.", + result); } BOOST_ASSERT(params.IsValid()); diff --git a/src/engine/plugins/trip.cpp b/src/engine/plugins/trip.cpp index 5c5514d04..ce85c70ea 100644 --- a/src/engine/plugins/trip.cpp +++ b/src/engine/plugins/trip.cpp @@ -149,11 +149,15 @@ Status TripPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataF { if (!algorithms.HasShortestPathSearch()) { - return Error("NotImplemented", "Shortest path search is not implemented for the chosen search algorithm.", json_result); + return Error("NotImplemented", + "Shortest path search is not implemented for the chosen search algorithm.", + json_result); } if (!algorithms.HasManyToManySearch()) { - return Error("NotImplemented", "Many to many search is not implemented for the chosen search algorithm.", json_result); + return Error("NotImplemented", + "Many to many search is not implemented for the chosen search algorithm.", + json_result); } BOOST_ASSERT(parameters.IsValid()); diff --git a/src/engine/plugins/viaroute.cpp b/src/engine/plugins/viaroute.cpp index d2c727857..a97e199a6 100644 --- a/src/engine/plugins/viaroute.cpp +++ b/src/engine/plugins/viaroute.cpp @@ -36,12 +36,18 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca if (!algorithms.HasShortestPathSearch() && route_parameters.coordinates.size() > 2) { - return Error("NotImplemented", "Shortest path search is not implemented for the chosen search algorithm. Only two coordinates supported.", json_result); + return Error("NotImplemented", + "Shortest path search is not implemented for the chosen search algorithm. " + "Only two coordinates supported.", + json_result); } if (!algorithms.HasDirectShortestPathSearch() && !algorithms.HasShortestPathSearch()) { - return Error("NotImplemented", "Direct shortest path search is not implemented for the chosen search algorithm.", json_result); + return Error( + "NotImplemented", + "Direct shortest path search is not implemented for the chosen search algorithm.", + json_result); } if (max_locations_viaroute > 0 && @@ -95,18 +101,20 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca }; util::for_each_pair(snapped_phantoms, build_phantom_pairs); - if (1 == raw_route.segment_end_coordinates.size() && algorithms.HasAlternativePathSearch() && route_parameters.alternatives) + if (1 == raw_route.segment_end_coordinates.size() && algorithms.HasAlternativePathSearch() && + route_parameters.alternatives) { raw_route = algorithms.AlternativePathSearch(raw_route.segment_end_coordinates.front()); } - else if (1 == raw_route.segment_end_coordinates.size() && algorithms.HasDirectShortestPathSearch()) + else if (1 == raw_route.segment_end_coordinates.size() && + algorithms.HasDirectShortestPathSearch()) { - raw_route = algorithms.DirectShortestPathSearch(raw_route.segment_end_coordinates); + raw_route = algorithms.DirectShortestPathSearch(raw_route.segment_end_coordinates.front()); } else { raw_route = algorithms.ShortestPathSearch(raw_route.segment_end_coordinates, - route_parameters.continue_straight); + route_parameters.continue_straight); } // we can only know this after the fact, different SCC ids still diff --git a/src/engine/routing_algorithms/direct_shortest_path.cpp b/src/engine/routing_algorithms/direct_shortest_path.cpp index 5d0bfd072..ab7becf1a 100644 --- a/src/engine/routing_algorithms/direct_shortest_path.cpp +++ b/src/engine/routing_algorithms/direct_shortest_path.cpp @@ -9,32 +9,14 @@ namespace engine namespace routing_algorithms { -/// This is a striped down version of the general shortest path algorithm. -/// The general algorithm always computes two queries for each leg. This is only -/// necessary in case of vias, where the directions of the start node is constrainted -/// by the previous route. -/// This variation is only an optimazation for graphs with slow queries, for example -/// not fully contracted graphs. -InternalRouteResult directShortestPathSearch( - SearchEngineData &engine_working_data, - const datafacade::ContiguousInternalMemoryDataFacade &facade, - const std::vector &phantom_nodes_vector) +namespace { - InternalRouteResult raw_route_data; - // Get weight 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(); - const auto &source_phantom = phantom_node_pair.source_phantom; - const auto &target_phantom = phantom_node_pair.target_phantom; - - engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); - auto &forward_heap = *(engine_working_data.forward_heap_1); - auto &reverse_heap = *(engine_working_data.reverse_heap_1); - forward_heap.Clear(); - reverse_heap.Clear(); - +void insertInHeaps(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + const PhantomNodes &nodes) +{ + const auto &source_phantom = nodes.source_phantom; + const auto &target_phantom = nodes.target_phantom; BOOST_ASSERT(source_phantom.IsValid()); BOOST_ASSERT(target_phantom.IsValid()); @@ -64,42 +46,16 @@ InternalRouteResult directShortestPathSearch( target_phantom.GetReverseWeightPlusOffset(), target_phantom.reverse_segment_id.id); } +} - int weight = INVALID_EDGE_WEIGHT; - std::vector packed_leg; - - const bool constexpr DO_NOT_FORCE_LOOPS = - false; // prevents forcing of loops, since offsets are set correctly - - if (facade.GetCoreSize() > 0) - { - engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes()); - auto &forward_core_heap = *(engine_working_data.forward_heap_2); - auto &reverse_core_heap = *(engine_working_data.reverse_heap_2); - forward_core_heap.Clear(); - reverse_core_heap.Clear(); - - searchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - weight, - packed_leg, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); - } - else - { - search(facade, - forward_heap, - reverse_heap, - weight, - packed_leg, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); - } - +template +InternalRouteResult +extractRoute(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const EdgeWeight weight, + const std::vector &packed_leg, + const PhantomNodes &nodes) +{ + InternalRouteResult raw_route_data; // No path found for both target nodes? if (INVALID_EDGE_WEIGHT == weight) { @@ -113,18 +69,79 @@ InternalRouteResult directShortestPathSearch( raw_route_data.shortest_path_length = weight; 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_segment_id.id)); + (packed_leg.front() != nodes.source_phantom.forward_segment_id.id)); raw_route_data.target_traversed_in_reverse.push_back( - (packed_leg.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); + (packed_leg.back() != nodes.target_phantom.forward_segment_id.id)); unpackPath(facade, packed_leg.begin(), packed_leg.end(), - phantom_node_pair, + nodes, raw_route_data.unpacked_path_segments.front()); 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. +/// The general algorithm always computes two queries for each leg. This is only +/// necessary in case of vias, where the directions of the start node is constrainted +/// by the previous route. +/// This variation is only an optimazation for graphs with slow queries, for example +/// not fully contracted graphs. +template +InternalRouteResult directShortestPathSearchImpl( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const PhantomNodes &phantom_nodes) +{ + engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); + engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes()); + auto &forward_heap = *(engine_working_data.forward_heap_1); + auto &reverse_heap = *(engine_working_data.reverse_heap_1); + auto &forward_core_heap = *(engine_working_data.forward_heap_2); + auto &reverse_core_heap = *(engine_working_data.reverse_heap_2); + forward_heap.Clear(); + reverse_heap.Clear(); + forward_core_heap.Clear(); + reverse_core_heap.Clear(); + + int weight = INVALID_EDGE_WEIGHT; + std::vector packed_leg; + insertInHeaps(forward_heap, reverse_heap, phantom_nodes); + + search(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + weight, + packed_leg, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); + + return extractRoute(facade, weight, packed_leg, phantom_nodes); +} + +InternalRouteResult directShortestPathSearch( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const PhantomNodes &phantom_nodes) +{ + return directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes); +} + +InternalRouteResult directShortestPathSearch( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const PhantomNodes &phantom_nodes) +{ + return directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes); +} + } // namespace routing_algorithms } // namespace engine } // namespace osrm diff --git a/src/engine/routing_algorithms/map_matching.cpp b/src/engine/routing_algorithms/map_matching.cpp index 4fde68304..3975322cc 100644 --- a/src/engine/routing_algorithms/map_matching.cpp +++ b/src/engine/routing_algorithms/map_matching.cpp @@ -47,13 +47,14 @@ unsigned getMedianSampleTime(const std::vector ×tamps) } } +template SubMatchingList -mapMatching(SearchEngineData &engine_working_data, - const datafacade::ContiguousInternalMemoryDataFacade &facade, - const CandidateLists &candidates_list, - const std::vector &trace_coordinates, - const std::vector &trace_timestamps, - const std::vector> &trace_gps_precision) +mapMatchingImpl(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const CandidateLists &candidates_list, + const std::vector &trace_coordinates, + const std::vector &trace_timestamps, + const std::vector> &trace_gps_precision) { map_matching::MatchingConfidence confidence; map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION); @@ -208,33 +209,15 @@ mapMatching(SearchEngineData &engine_working_data, continue; } - forward_heap.Clear(); - reverse_heap.Clear(); - - double network_distance; - if (facade.GetCoreSize() > 0) - { - forward_core_heap.Clear(); - reverse_core_heap.Clear(); - network_distance = getNetworkDistanceWithCore( - facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - prev_unbroken_timestamps_list[s].phantom_node, - current_timestamps_list[s_prime].phantom_node, - duration_upper_bound); - } - else - { - network_distance = - getNetworkDistance(facade, - forward_heap, - reverse_heap, - prev_unbroken_timestamps_list[s].phantom_node, - current_timestamps_list[s_prime].phantom_node); - } + double network_distance = + getNetworkDistance(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + prev_unbroken_timestamps_list[s].phantom_node, + current_timestamps_list[s_prime].phantom_node, + duration_upper_bound); // get distance diff between loc1/2 and locs/s_prime const auto d_t = std::abs(network_distance - haversine_distance); @@ -427,6 +410,39 @@ mapMatching(SearchEngineData &engine_working_data, return sub_matchings; } +SubMatchingList +mapMatching(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const CandidateLists &candidates_list, + const std::vector &trace_coordinates, + const std::vector &trace_timestamps, + const std::vector> &trace_gps_precision) +{ + return mapMatchingImpl(engine_working_data, + facade, + candidates_list, + trace_coordinates, + trace_timestamps, + trace_gps_precision); +} + +SubMatchingList +mapMatching(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const CandidateLists &candidates_list, + const std::vector &trace_coordinates, + const std::vector &trace_timestamps, + const std::vector> &trace_gps_precision) +{ + + return mapMatchingImpl(engine_working_data, + facade, + candidates_list, + trace_coordinates, + trace_timestamps, + trace_gps_precision); +} + } // namespace routing_algorithms } // namespace engine } // namespace osrm diff --git a/src/engine/routing_algorithms/routing_base.cpp b/src/engine/routing_algorithms/routing_base.cpp index 7cff2f8aa..a73ff55ad 100644 --- a/src/engine/routing_algorithms/routing_base.cpp +++ b/src/engine/routing_algorithms/routing_base.cpp @@ -270,16 +270,16 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade // && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) // requires // a force loop, if the heaps have been initialized with positive offsets. -void searchWithCore(const datafacade::ContiguousInternalMemoryDataFacade &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - SearchEngineData::QueryHeap &forward_core_heap, - SearchEngineData::QueryHeap &reverse_core_heap, - EdgeWeight &weight, - std::vector &packed_leg, - const bool force_loop_forward, - const bool force_loop_reverse, - EdgeWeight weight_upper_bound) +void search(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + SearchEngineData::QueryHeap &forward_core_heap, + SearchEngineData::QueryHeap &reverse_core_heap, + EdgeWeight &weight, + std::vector &packed_leg, + const bool force_loop_forward, + const bool force_loop_reverse, + EdgeWeight weight_upper_bound) { NodeID middle = SPECIAL_NODEID; weight = weight_upper_bound; @@ -530,18 +530,20 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, - 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, - EdgeWeight weight_upper_bound) +double +getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + 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, + EdgeWeight weight_upper_bound) { - BOOST_ASSERT(forward_heap.Empty()); - BOOST_ASSERT(reverse_heap.Empty()); + forward_heap.Clear(); + reverse_heap.Clear(); + forward_core_heap.Clear(); + reverse_core_heap.Clear(); if (source_phantom.forward_segment_id.enabled) { @@ -574,16 +576,16 @@ double getNetworkDistanceWithCore( EdgeWeight weight = INVALID_EDGE_WEIGHT; std::vector packed_path; - searchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - weight, - packed_path, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS, - weight_upper_bound); + search(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + weight, + packed_path, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS, + weight_upper_bound); double distance = std::numeric_limits::max(); if (weight != INVALID_EDGE_WEIGHT) @@ -604,8 +606,8 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade target forward/reverse -void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade &facade, +template +void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade &facade, QueryHeap &forward_heap, QueryHeap &reverse_heap, QueryHeap &forward_core_heap, @@ -70,32 +74,21 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade 0) - { - forward_core_heap.Clear(); - reverse_core_heap.Clear(); - BOOST_ASSERT(forward_core_heap.Size() == 0); - BOOST_ASSERT(reverse_core_heap.Size() == 0); - searchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - new_total_weight, - leg_packed_path, - needs_loop_forwad, - needs_loop_backwards); - } - else - { - search(facade, - forward_heap, - reverse_heap, - new_total_weight, - leg_packed_path, - needs_loop_forwad, - needs_loop_backwards); - } + + forward_core_heap.Clear(); + reverse_core_heap.Clear(); + BOOST_ASSERT(forward_core_heap.Size() == 0); + BOOST_ASSERT(reverse_core_heap.Size() == 0); + routing_algorithms::search(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + new_total_weight, + leg_packed_path, + needs_loop_forwad, + needs_loop_backwards); + // if no route is found between two parts of the via-route, the entire route becomes // invalid. Adding to invalid edge weight sadly doesn't return an invalid edge weight. Here // we prevent the possible overflow, faking the addition of infinity + x == infinity @@ -106,7 +99,8 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade target forward // source forward/reverse -> target reverse -void Search(const datafacade::ContiguousInternalMemoryDataFacade &facade, +template +void search(const datafacade::ContiguousInternalMemoryDataFacade &facade, QueryHeap &forward_heap, QueryHeap &reverse_heap, QueryHeap &forward_core_heap, @@ -149,32 +143,19 @@ void Search(const datafacade::ContiguousInternalMemoryDataFacade BOOST_ASSERT(forward_heap.Size() > 0); BOOST_ASSERT(reverse_heap.Size() > 0); - if (facade.GetCoreSize() > 0) - { - forward_core_heap.Clear(); - reverse_core_heap.Clear(); - BOOST_ASSERT(forward_core_heap.Size() == 0); - BOOST_ASSERT(reverse_core_heap.Size() == 0); - searchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - new_total_weight_to_forward, - leg_packed_path_forward, - needsLoopForward(source_phantom, target_phantom), - DO_NOT_FORCE_LOOP); - } - else - { - search(facade, - forward_heap, - reverse_heap, - new_total_weight_to_forward, - leg_packed_path_forward, - needsLoopForward(source_phantom, target_phantom), - DO_NOT_FORCE_LOOP); - } + forward_core_heap.Clear(); + reverse_core_heap.Clear(); + BOOST_ASSERT(forward_core_heap.Size() == 0); + BOOST_ASSERT(reverse_core_heap.Size() == 0); + routing_algorithms::search(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + new_total_weight_to_forward, + leg_packed_path_forward, + needsLoopForward(source_phantom, target_phantom), + DO_NOT_FORCE_LOOP); } if (search_to_reverse_node) @@ -200,32 +181,19 @@ void Search(const datafacade::ContiguousInternalMemoryDataFacade } BOOST_ASSERT(forward_heap.Size() > 0); BOOST_ASSERT(reverse_heap.Size() > 0); - if (facade.GetCoreSize() > 0) - { - forward_core_heap.Clear(); - reverse_core_heap.Clear(); - BOOST_ASSERT(forward_core_heap.Size() == 0); - BOOST_ASSERT(reverse_core_heap.Size() == 0); - searchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - new_total_weight_to_reverse, - leg_packed_path_reverse, - DO_NOT_FORCE_LOOP, - needsLoopBackwards(source_phantom, target_phantom)); - } - else - { - search(facade, - forward_heap, - reverse_heap, - new_total_weight_to_reverse, - leg_packed_path_reverse, - DO_NOT_FORCE_LOOP, - needsLoopBackwards(source_phantom, target_phantom)); - } + forward_core_heap.Clear(); + reverse_core_heap.Clear(); + BOOST_ASSERT(forward_core_heap.Size() == 0); + BOOST_ASSERT(reverse_core_heap.Size() == 0); + routing_algorithms::search(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + new_total_weight_to_reverse, + leg_packed_path_reverse, + DO_NOT_FORCE_LOOP, + needsLoopBackwards(source_phantom, target_phantom)); } } @@ -259,11 +227,12 @@ void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade InternalRouteResult -shortestPathSearch(SearchEngineData &engine_working_data, - const datafacade::ContiguousInternalMemoryDataFacade &facade, - const std::vector &phantom_nodes_vector, - const boost::optional continue_straight_at_waypoint) +shortestPathSearchImpl(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector, + const boost::optional continue_straight_at_waypoint) { InternalRouteResult raw_route_data; const bool allow_uturn_at_waypoint = @@ -351,7 +320,7 @@ shortestPathSearch(SearchEngineData &engine_working_data, } else { - Search(facade, + search(facade, forward_heap, reverse_heap, forward_core_heap, @@ -503,6 +472,27 @@ shortestPathSearch(SearchEngineData &engine_working_data, return raw_route_data; } +} + +InternalRouteResult +shortestPathSearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector, + const boost::optional continue_straight_at_waypoint) +{ + return shortestPathSearchImpl( + engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint); +} + +InternalRouteResult +shortestPathSearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector, + const boost::optional continue_straight_at_waypoint) +{ + return shortestPathSearchImpl( + engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint); +} } // namespace routing_algorithms } // namespace engine diff --git a/src/osrm/osrm.cpp b/src/osrm/osrm.cpp index 0af42360f..b94c9931f 100644 --- a/src/osrm/osrm.cpp +++ b/src/osrm/osrm.cpp @@ -17,8 +17,15 @@ namespace osrm // Pimpl idiom OSRM::OSRM(engine::EngineConfig &config) - : engine_(std::make_unique>(config)) { + if (engine::Engine::CheckCompability(config)) + { + engine_ = std::make_unique>(config); + } + else + { + engine_ = std::make_unique>(config); + } } OSRM::~OSRM() = default; OSRM::OSRM(OSRM &&) noexcept = default; diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 50e46a4f9..0ef54270f 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -278,6 +278,16 @@ class MockAlgorithmDataFacade { return SPECIAL_EDGEID; } +}; + +template <> +class MockAlgorithmDataFacade + : public engine::datafacade::AlgorithmDataFacade +{ + private: + EdgeData foo; + + public: bool IsCoreNode(const NodeID /* id */) const override { return false; } std::size_t GetCoreSize() const override { return 0; } }; @@ -287,6 +297,14 @@ class MockDataFacade final : public MockBaseDataFacade, public MockAlgorithmData { }; +template <> +class MockDataFacade final + : public MockBaseDataFacade, + public MockAlgorithmDataFacade, + public MockAlgorithmDataFacade +{ +}; + } // ns test } // ns osrm