From 436b34ffeab641122f212f43904872becf7b87be Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 25 Feb 2017 01:24:21 +0000 Subject: [PATCH] Refactor routing_algorithms to only contain free functions --- include/engine/edge_unpacker.hpp | 107 --- include/engine/routing_algorithms.hpp | 61 +- .../routing_algorithms/alternative_path.hpp | 193 +--- .../direct_shortest_path.hpp | 31 +- .../routing_algorithms/many_to_many.hpp | 128 +-- .../routing_algorithms/map_matching.hpp | 61 +- .../routing_algorithms/routing_base.hpp | 793 +++++++++------- .../routing_algorithms/shortest_path.hpp | 78 +- .../engine/routing_algorithms/tile_turns.hpp | 27 +- src/engine/plugins/match.cpp | 4 +- src/engine/plugins/tile.cpp | 1 - src/engine/plugins/trip.cpp | 2 +- src/engine/plugins/viaroute.cpp | 8 +- .../routing_algorithms/alternative_path.cpp | 884 ++++++++++-------- .../direct_shortest_path.cpp | 65 +- .../routing_algorithms/many_to_many.cpp | 261 ++++-- .../routing_algorithms/map_matching.cpp | 73 +- .../routing_algorithms/routing_base.cpp | 168 ++-- .../routing_algorithms/shortest_path.cpp | 217 ++--- src/engine/routing_algorithms/tile_turns.cpp | 8 +- 20 files changed, 1481 insertions(+), 1689 deletions(-) delete mode 100644 include/engine/edge_unpacker.hpp diff --git a/include/engine/edge_unpacker.hpp b/include/engine/edge_unpacker.hpp deleted file mode 100644 index ed52a0f5b..000000000 --- a/include/engine/edge_unpacker.hpp +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef EDGE_UNPACKER_H -#define EDGE_UNPACKER_H - -#include "extractor/guidance/turn_instruction.hpp" -#include "extractor/travel_mode.hpp" -#include "engine/phantom_node.hpp" -#include "osrm/coordinate.hpp" -#include "util/guidance/turn_lanes.hpp" -#include "util/typedefs.hpp" - -#include -#include - -namespace osrm -{ -namespace engine -{ - -/** - * Given a sequence of connected `NodeID`s in the CH graph, performs a depth-first unpacking of - * the shortcut - * edges. For every "original" edge found, it calls the `callback` with the two NodeIDs for the - * edge, and the EdgeData - * for that edge. - * - * The primary purpose of this unpacking is to expand a path through the CH into the original - * route through the - * pre-contracted graph. - * - * Because of the depth-first-search, the `callback` will effectively be called in sequence for - * the original route - * from beginning to end. - * - * @param packed_path_begin iterator pointing to the start of the NodeID list - * @param packed_path_end iterator pointing to the end of the NodeID list - * @param callback void(const std::pair, const EdgeData &) called for each - * original edge found. - */ - -template -inline void UnpackCHPath(const DataFacadeT &facade, - BidirectionalIterator packed_path_begin, - BidirectionalIterator packed_path_end, - Callback &&callback) -{ - // make sure we have at least something to unpack - if (packed_path_begin == packed_path_end) - return; - - using EdgeData = typename DataFacadeT::EdgeData; - - std::stack> recursion_stack; - - // We have to push the path in reverse order onto the stack because it's LIFO. - for (auto current = std::prev(packed_path_end); current != packed_path_begin; - current = std::prev(current)) - { - recursion_stack.emplace(*std::prev(current), *current); - } - - std::pair edge; - while (!recursion_stack.empty()) - { - edge = recursion_stack.top(); - recursion_stack.pop(); - - // Look for an edge on the forward CH graph (.forward) - EdgeID smaller_edge_id = facade.FindSmallestEdge( - edge.first, edge.second, [](const EdgeData &data) { return data.forward; }); - - // If we didn't find one there, the we might be looking at a part of the path that - // was found using the backward search. Here, we flip the node order (.second, .first) - // and only consider edges with the `.backward` flag. - if (SPECIAL_EDGEID == smaller_edge_id) - { - smaller_edge_id = facade.FindSmallestEdge( - edge.second, edge.first, [](const EdgeData &data) { return data.backward; }); - } - - // If we didn't find anything *still*, then something is broken and someone has - // called this function with bad values. - BOOST_ASSERT_MSG(smaller_edge_id != SPECIAL_EDGEID, "Invalid smaller edge ID"); - - const auto &data = facade.GetEdgeData(smaller_edge_id); - BOOST_ASSERT_MSG(data.weight != std::numeric_limits::max(), - "edge weight invalid"); - - // If the edge is a shortcut, we need to add the two halfs to the stack. - if (data.shortcut) - { // unpack - const NodeID middle_node_id = data.id; - // Note the order here - we're adding these to a stack, so we - // want the first->middle to get visited before middle->second - recursion_stack.emplace(middle_node_id, edge.second); - recursion_stack.emplace(edge.first, middle_node_id); - } - else - { - // We found an original edge, call our callback. - std::forward(callback)(edge, data); - } - } -} -} -} - -#endif // EDGE_UNPACKER_H diff --git a/include/engine/routing_algorithms.hpp b/include/engine/routing_algorithms.hpp index b9d514f14..9b2e866ba 100644 --- a/include/engine/routing_algorithms.hpp +++ b/include/engine/routing_algorithms.hpp @@ -19,15 +19,14 @@ namespace engine class RoutingAlgorithmsInterface { public: - virtual void AlternativeRouting(const PhantomNodes &phantom_node_pair, - InternalRouteResult &raw_route_data) const = 0; + virtual InternalRouteResult AlternativeRouting(const PhantomNodes &phantom_node_pair) const = 0; - virtual void ShortestRouting(const std::vector &phantom_node_pair, - const boost::optional continue_straight_at_waypoint, - InternalRouteResult &raw_route_data) const = 0; + virtual InternalRouteResult + ShortestRouting(const std::vector &phantom_node_pair, + const boost::optional continue_straight_at_waypoint) const = 0; - virtual void DirectShortestPathRouting(const std::vector &phantom_node_pair, - InternalRouteResult &raw_route_data) const = 0; + virtual InternalRouteResult + DirectShortestPathRouting(const std::vector &phantom_node_pair) const = 0; virtual std::vector ManyToManyRouting(const std::vector &phantom_nodes, @@ -53,29 +52,28 @@ template class RoutingAlgorithms final : public RoutingAlg public: RoutingAlgorithms(SearchEngineData &heaps, const datafacade::ContiguousInternalMemoryDataFacade &facade) - : facade(facade), alternative_routing(heaps), shortest_path_routing(heaps), - direct_shortest_path_routing(heaps), many_to_many_routing(heaps), map_matching(heaps) + : heaps(heaps), facade(facade) { } - void AlternativeRouting(const PhantomNodes &phantom_node_pair, - InternalRouteResult &raw_route_data) const final override + InternalRouteResult + AlternativeRouting(const PhantomNodes &phantom_node_pair) const final override { - alternative_routing(facade, phantom_node_pair, raw_route_data); + return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair); } - void ShortestRouting(const std::vector &phantom_node_pair, - const boost::optional continue_straight_at_waypoint, - InternalRouteResult &raw_route_data) const final override + InternalRouteResult + ShortestRouting(const std::vector &phantom_node_pair, + const boost::optional continue_straight_at_waypoint) const final override { - shortest_path_routing( - facade, phantom_node_pair, continue_straight_at_waypoint, raw_route_data); + return routing_algorithms::shortestPathSearch( + heaps, facade, phantom_node_pair, continue_straight_at_waypoint); } - void DirectShortestPathRouting(const std::vector &phantom_node_pair, - InternalRouteResult &raw_route_data) const final override + InternalRouteResult DirectShortestPathRouting( + const std::vector &phantom_node_pair) const final override { - direct_shortest_path_routing(facade, phantom_node_pair, raw_route_data); + return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_node_pair); } std::vector @@ -83,7 +81,8 @@ template class RoutingAlgorithms final : public RoutingAlg const std::vector &source_indices, const std::vector &target_indices) const final override { - return many_to_many_routing(facade, phantom_nodes, source_indices, target_indices); + return routing_algorithms::manyToManySearch( + heaps, facade, phantom_nodes, source_indices, target_indices); } routing_algorithms::SubMatchingList MapMatching( @@ -92,32 +91,30 @@ template class RoutingAlgorithms final : public RoutingAlg const std::vector &trace_timestamps, const std::vector> &trace_gps_precision) const final override { - return map_matching( - facade, candidates_list, trace_coordinates, trace_timestamps, trace_gps_precision); + return routing_algorithms::mapMatching(heaps, + facade, + candidates_list, + trace_coordinates, + trace_timestamps, + trace_gps_precision); } std::vector TileTurns(const std::vector &edges, const std::vector &sorted_edge_indexes) const final override { - return tile_turns(facade, edges, sorted_edge_indexes); + return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes); } bool HasAlternativeRouting() const final override { return algorithm_trais::HasAlternativeRouting()(facade); - }; + } private: + SearchEngineData &heaps; // Owned by shared-ptr passed to the query const datafacade::ContiguousInternalMemoryDataFacade &facade; - - mutable routing_algorithms::AlternativeRouting alternative_routing; - mutable routing_algorithms::ShortestPathRouting shortest_path_routing; - mutable routing_algorithms::DirectShortestPathRouting direct_shortest_path_routing; - mutable routing_algorithms::ManyToManyRouting many_to_many_routing; - mutable routing_algorithms::MapMatching map_matching; - routing_algorithms::TileTurns tile_turns; }; } } diff --git a/include/engine/routing_algorithms/alternative_path.hpp b/include/engine/routing_algorithms/alternative_path.hpp index d93f3f807..30a842d77 100644 --- a/include/engine/routing_algorithms/alternative_path.hpp +++ b/include/engine/routing_algorithms/alternative_path.hpp @@ -1,22 +1,11 @@ #ifndef ALTERNATIVE_PATH_ROUTING_HPP #define ALTERNATIVE_PATH_ROUTING_HPP -#include "engine/datafacade/datafacade_base.hpp" -#include "engine/routing_algorithms/routing_base.hpp" +#include "engine/datafacade/contiguous_internalmem_datafacade.hpp" +#include "engine/internal_route_result.hpp" #include "engine/algorithm.hpp" #include "engine/search_engine_data.hpp" -#include "util/integer_range.hpp" - -#include - -#include -#include -#include -#include -#include - -#include namespace osrm { @@ -25,181 +14,13 @@ namespace engine namespace routing_algorithms { -const double constexpr VIAPATH_ALPHA = 0.10; -const double constexpr VIAPATH_EPSILON = 0.15; // alternative at most 15% longer -const double constexpr VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest. - -template class AlternativeRouting; - -template <> class AlternativeRouting final : private BasicRouting -{ - using super = BasicRouting; - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; - using QueryHeap = SearchEngineData::QueryHeap; - using SearchSpaceEdge = std::pair; - - struct RankedCandidateNode - { - RankedCandidateNode(const NodeID node, const int length, const int sharing) - : node(node), length(length), sharing(sharing) - { - } - - NodeID node; - int length; - int sharing; - - bool operator<(const RankedCandidateNode &other) const - { - return (2 * length + sharing) < (2 * other.length + other.sharing); - } - }; - SearchEngineData &engine_working_data; - - public: - AlternativeRouting(SearchEngineData &engine_working_data) - : engine_working_data(engine_working_data) - { - } - - virtual ~AlternativeRouting() {} - - void operator()(const FacadeT &facade, - const PhantomNodes &phantom_node_pair, - InternalRouteResult &raw_route_data); - - private: - // unpack alternate by exploring search spaces from v - void RetrievePackedAlternatePath(const QueryHeap &forward_heap1, - const QueryHeap &reverse_heap1, - const QueryHeap &forward_heap2, - const QueryHeap &reverse_heap2, - const NodeID s_v_middle, - const NodeID v_t_middle, - std::vector &packed_path) const; - - // TODO: reorder parameters - // compute and unpack and by exploring search spaces - // from v and intersecting against queues. only half-searches have to be - // done at this stage - void ComputeLengthAndSharingOfViaPath(const FacadeT &facade, - const NodeID via_node, - int *real_length_of_via_path, - int *sharing_of_via_path, - const std::vector &packed_shortest_path, - const EdgeWeight min_edge_offset); - - // todo: reorder parameters - template - void AlternativeRoutingStep(const FacadeT &facade, - QueryHeap &heap1, - QueryHeap &heap2, - NodeID *middle_node, - EdgeWeight *upper_bound_to_shortest_path_weight, - std::vector &search_space_intersection, - std::vector &search_space, - const EdgeWeight min_edge_offset) const - { - QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2); - QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1); - - const NodeID node = forward_heap.DeleteMin(); - const EdgeWeight weight = forward_heap.GetKey(node); - // const NodeID parentnode = forward_heap.GetData(node).parent; - // util::Log() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled - // edge (" - // << parentnode << "," << node << "), dist: " << weight; - - const auto scaled_weight = - static_cast((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)) - { - forward_heap.DeleteAll(); - return; - } - - search_space.emplace_back(forward_heap.GetData(node).parent, node); - - if (reverse_heap.WasInserted(node)) - { - search_space_intersection.emplace_back(node); - const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight; - if (new_weight < *upper_bound_to_shortest_path_weight) - { - if (new_weight >= 0) - { - *middle_node = node; - *upper_bound_to_shortest_path_weight = new_weight; - // util::Log() << "accepted middle_node " << *middle_node - // << " at - // weight " << new_weight; - // } else { - // util::Log() << "discarded middle_node " << *middle_node - // << " - // at weight " << new_weight; - } - else - { - // check whether there is a loop present at the node - const auto loop_weight = super::GetLoopWeight(facade, 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; - *upper_bound_to_shortest_path_weight = loop_weight; - } - } - } - } - - for (auto edge : facade.GetAdjacentEdgeRange(node)) - { - const auto &data = facade.GetEdgeData(edge); - const bool edge_is_forward_directed = - (is_forward_directed ? data.forward : data.backward); - if (edge_is_forward_directed) - { - const NodeID to = facade.GetTarget(edge); - const EdgeWeight edge_weight = data.weight; - - BOOST_ASSERT(edge_weight > 0); - const EdgeWeight to_weight = weight + edge_weight; - - // New Node discovered -> Add to Heap + Node Info Storage - if (!forward_heap.WasInserted(to)) - { - forward_heap.Insert(to, to_weight, node); - } - // Found a shorter Path -> Update weight - else if (to_weight < forward_heap.GetKey(to)) - { - // new parent - forward_heap.GetData(to).parent = node; - // decreased weight - forward_heap.DecreaseKey(to, to_weight); - } - } - } - } - - // conduct T-Test - bool ViaNodeCandidatePassesTTest(const FacadeT &facade, - QueryHeap &existing_forward_heap, - QueryHeap &existing_reverse_heap, - QueryHeap &new_forward_heap, - QueryHeap &new_reverse_heap, - const RankedCandidateNode &candidate, - const int length_of_shortest_path, - int *length_of_via_path, - NodeID *s_v_middle, - NodeID *v_t_middle, - const EdgeWeight min_edge_offset) const; -}; +InternalRouteResult +alternativePathSearch(SearchEngineData &search_engine_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const PhantomNodes &phantom_node_pair); } // namespace routing_algorithms } // namespace engine } // namespace osrm -#endif /* ALTERNATIVE_PATH_ROUTING_HPP */ +#endif diff --git a/include/engine/routing_algorithms/direct_shortest_path.hpp b/include/engine/routing_algorithms/direct_shortest_path.hpp index dcdcfc6a6..ced2f3f2a 100644 --- a/include/engine/routing_algorithms/direct_shortest_path.hpp +++ b/include/engine/routing_algorithms/direct_shortest_path.hpp @@ -1,10 +1,11 @@ #ifndef DIRECT_SHORTEST_PATH_HPP #define DIRECT_SHORTEST_PATH_HPP -#include "engine/routing_algorithms/routing_base.hpp" - #include "engine/algorithm.hpp" +#include "engine/datafacade/contiguous_internalmem_datafacade.hpp" +#include "engine/internal_route_result.hpp" #include "engine/search_engine_data.hpp" + #include "util/typedefs.hpp" namespace osrm @@ -14,34 +15,16 @@ namespace engine namespace routing_algorithms { -template class DirectShortestPathRouting; - /// 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 <> -class DirectShortestPathRouting final : public BasicRouting -{ - using super = BasicRouting; - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; - using QueryHeap = SearchEngineData::QueryHeap; - SearchEngineData &engine_working_data; - - public: - DirectShortestPathRouting(SearchEngineData &engine_working_data) - : engine_working_data(engine_working_data) - { - } - - ~DirectShortestPathRouting() {} - - void operator()(const FacadeT &facade, - const std::vector &phantom_nodes_vector, - InternalRouteResult &raw_route_data) const; -}; +InternalRouteResult directShortestPathSearch( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector); } // namespace routing_algorithms } // namespace engine diff --git a/include/engine/routing_algorithms/many_to_many.hpp b/include/engine/routing_algorithms/many_to_many.hpp index ada124199..c6c1dbced 100644 --- a/include/engine/routing_algorithms/many_to_many.hpp +++ b/include/engine/routing_algorithms/many_to_many.hpp @@ -1,138 +1,28 @@ #ifndef MANY_TO_MANY_ROUTING_HPP #define MANY_TO_MANY_ROUTING_HPP -#include "engine/routing_algorithms/routing_base.hpp" - #include "engine/algorithm.hpp" +#include "engine/datafacade/contiguous_internalmem_datafacade.hpp" #include "engine/search_engine_data.hpp" + #include "util/typedefs.hpp" -#include - -#include -#include -#include #include namespace osrm { namespace engine { + namespace routing_algorithms { -template class ManyToManyRouting; - -template <> class ManyToManyRouting final : public BasicRouting -{ - using super = BasicRouting; - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; - using QueryHeap = SearchEngineData::ManyToManyQueryHeap; - SearchEngineData &engine_working_data; - - struct NodeBucket - { - unsigned target_id; // essentially a row in the weight matrix - EdgeWeight weight; - EdgeWeight duration; - NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration) - : target_id(target_id), weight(weight), duration(duration) - { - } - }; - - // FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking - using SearchSpaceWithBuckets = std::unordered_map>; - - public: - ManyToManyRouting(SearchEngineData &engine_working_data) - : engine_working_data(engine_working_data) - { - } - - std::vector operator()(const FacadeT &facade, - const std::vector &phantom_nodes, - const std::vector &source_indices, - const std::vector &target_indices) const; - - void ForwardRoutingStep(const FacadeT &facade, - const unsigned row_idx, - const unsigned number_of_targets, - QueryHeap &query_heap, - const SearchSpaceWithBuckets &search_space_with_buckets, - std::vector &weights_table, - std::vector &durations_table) const; - - void BackwardRoutingStep(const FacadeT &facade, - const unsigned column_idx, - QueryHeap &query_heap, - SearchSpaceWithBuckets &search_space_with_buckets) const; - - template - inline void RelaxOutgoingEdges(const FacadeT &facade, - const NodeID node, - const EdgeWeight weight, - const EdgeWeight duration, - QueryHeap &query_heap) const - { - for (auto edge : facade.GetAdjacentEdgeRange(node)) - { - const auto &data = facade.GetEdgeData(edge); - const bool direction_flag = (forward_direction ? data.forward : data.backward); - if (direction_flag) - { - const NodeID to = facade.GetTarget(edge); - const EdgeWeight edge_weight = data.weight; - const EdgeWeight edge_duration = data.duration; - - BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); - const EdgeWeight to_weight = weight + edge_weight; - const EdgeWeight to_duration = duration + edge_duration; - - // New Node discovered -> Add to Heap + Node Info Storage - if (!query_heap.WasInserted(to)) - { - query_heap.Insert(to, to_weight, {node, to_duration}); - } - // Found a shorter Path -> Update weight - else if (to_weight < query_heap.GetKey(to)) - { - // new parent - query_heap.GetData(to) = {node, to_duration}; - query_heap.DecreaseKey(to, to_weight); - } - } - } - } - - // Stalling - template - inline bool StallAtNode(const FacadeT &facade, - const NodeID node, - const EdgeWeight weight, - QueryHeap &query_heap) const - { - for (auto edge : facade.GetAdjacentEdgeRange(node)) - { - const auto &data = facade.GetEdgeData(edge); - const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward); - if (reverse_flag) - { - const NodeID to = facade.GetTarget(edge); - const EdgeWeight edge_weight = data.weight; - BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); - if (query_heap.WasInserted(to)) - { - if (query_heap.GetKey(to) + edge_weight < weight) - { - return true; - } - } - } - } - return false; - } -}; +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 diff --git a/include/engine/routing_algorithms/map_matching.hpp b/include/engine/routing_algorithms/map_matching.hpp index c8f1e3c78..34a238fb9 100644 --- a/include/engine/routing_algorithms/map_matching.hpp +++ b/include/engine/routing_algorithms/map_matching.hpp @@ -1,25 +1,11 @@ #ifndef MAP_MATCHING_HPP #define MAP_MATCHING_HPP -#include "engine/routing_algorithms/routing_base.hpp" - #include "engine/algorithm.hpp" -#include "engine/map_matching/hidden_markov_model.hpp" -#include "engine/map_matching/matching_confidence.hpp" +#include "engine/datafacade/contiguous_internalmem_datafacade.hpp" #include "engine/map_matching/sub_matching.hpp" +#include "engine/search_engine_data.hpp" -#include "extractor/profile_properties.hpp" -#include "util/coordinate_calculation.hpp" -#include "util/for_each_pair.hpp" - -#include - -#include -#include -#include -#include -#include -#include #include namespace osrm @@ -31,45 +17,16 @@ namespace routing_algorithms using CandidateList = std::vector; using CandidateLists = std::vector; -using HMM = map_matching::HiddenMarkovModel; using SubMatchingList = std::vector; - -constexpr static const unsigned MAX_BROKEN_STATES = 10; -static const constexpr double MATCHING_BETA = 10; -constexpr static const double MAX_DISTANCE_DELTA = 2000.; static const constexpr double DEFAULT_GPS_PRECISION = 5; -template class MapMatching; - -// implements a hidden markov model map matching algorithm -template <> class MapMatching final : public BasicRouting -{ - using super = BasicRouting; - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; - using QueryHeap = SearchEngineData::QueryHeap; - SearchEngineData &engine_working_data; - map_matching::EmissionLogProbability default_emission_log_probability; - map_matching::TransitionLogProbability transition_log_probability; - map_matching::MatchingConfidence confidence; - extractor::ProfileProperties m_profile_properties; - - unsigned GetMedianSampleTime(const std::vector ×tamps) const; - - public: - MapMatching(SearchEngineData &engine_working_data) - : engine_working_data(engine_working_data), - default_emission_log_probability(DEFAULT_GPS_PRECISION), - transition_log_probability(MATCHING_BETA) - { - } - - SubMatchingList - operator()(const FacadeT &facade, - const CandidateLists &candidates_list, - const std::vector &trace_coordinates, - const std::vector &trace_timestamps, - const std::vector> &trace_gps_precision) const; -}; +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 48c2460d1..f3dfa4452 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -5,7 +5,6 @@ #include "engine/algorithm.hpp" #include "engine/datafacade/contiguous_internalmem_datafacade.hpp" -#include "engine/edge_unpacker.hpp" #include "engine/internal_route_result.hpp" #include "engine/search_engine_data.hpp" @@ -35,402 +34,476 @@ namespace engine namespace routing_algorithms { -template class BasicRouting; +/* +min_edge_offset is needed in case we use multiple +nodes as start/target nodes with different (even negative) offsets. +In that case the termination criterion is not correct +anymore. -// TODO: There is no reason these functions are contained in a class other then for namespace -// purposes. This should be a namespace with free functions. -template <> class BasicRouting -{ - protected: - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; - using EdgeData = typename FacadeT::EdgeData; +Example: +forward heap: a(-100), b(0), +reverse heap: c(0), d(100) - public: - /* - min_edge_offset is needed in case we use multiple - nodes as start/target nodes with different (even negative) offsets. - In that case the termination criterion is not correct - anymore. +a --- d + \ / + / \ +b --- c - Example: - forward heap: a(-100), b(0), - reverse heap: c(0), d(100) +This is equivalent to running a bi-directional Dijkstra on the following graph: a --- d - \ / - / \ + / \ / \ + y x z + \ / \ / b --- c - This is equivalent to running a bi-directional Dijkstra on the following graph: +The graph is constructed by inserting nodes y and z that are connected to the initial nodes +using edges (y, a) with weight -100, (y, b) with weight 0 and, +(d, z) with weight 100, (c, z) with weight 0 corresponding. +Since we are dealing with a graph that contains _negative_ edges, +we need to add an offset to the termination criterion. +*/ +void routingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + NodeID &middle_node_id, + std::int32_t &upper_bound, + std::int32_t min_edge_offset, + const bool forward_direction, + const bool stalling, + const bool force_loop_forward, + const bool force_loop_reverse); - a --- d - / \ / \ - y x z - \ / \ / - b --- c - - The graph is constructed by inserting nodes y and z that are connected to the initial nodes - using edges (y, a) with weight -100, (y, b) with weight 0 and, - (d, z) with weight 100, (c, z) with weight 0 corresponding. - Since we are dealing with a graph that contains _negative_ edges, - we need to add an offset to the termination criterion. - */ - void RoutingStep(const FacadeT &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - NodeID &middle_node_id, - std::int32_t &upper_bound, - std::int32_t min_edge_offset, - const bool forward_direction, - const bool stalling, - const bool force_loop_forward, - const bool force_loop_reverse) const; - - template EdgeWeight GetLoopWeight(const FacadeT &facade, NodeID node) const +template +EdgeWeight +getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade &facade, + NodeID node) +{ + EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT; + for (auto edge : facade.GetAdjacentEdgeRange(node)) { - EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT; - for (auto edge : facade.GetAdjacentEdgeRange(node)) + const auto &data = facade.GetEdgeData(edge); + if (data.forward) { - const auto &data = facade.GetEdgeData(edge); - if (data.forward) + const NodeID to = facade.GetTarget(edge); + if (to == node) { - const NodeID to = facade.GetTarget(edge); - if (to == node) - { - const auto value = UseDuration ? data.duration : data.weight; - loop_weight = std::min(loop_weight, value); - } + const auto value = UseDuration ? data.duration : data.weight; + loop_weight = std::min(loop_weight, value); } } - return loop_weight; + } + return loop_weight; +} + +/** + * Given a sequence of connected `NodeID`s in the CH graph, performs a depth-first unpacking of + * the shortcut + * edges. For every "original" edge found, it calls the `callback` with the two NodeIDs for the + * edge, and the EdgeData + * for that edge. + * + * The primary purpose of this unpacking is to expand a path through the CH into the original + * route through the + * pre-contracted graph. + * + * Because of the depth-first-search, the `callback` will effectively be called in sequence for + * the original route + * from beginning to end. + * + * @param packed_path_begin iterator pointing to the start of the NodeID list + * @param packed_path_end iterator pointing to the end of the NodeID list + * @param callback void(const std::pair, const EdgeData &) called for each + * original edge found. + */ +template +void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade &facade, + BidirectionalIterator packed_path_begin, + BidirectionalIterator packed_path_end, + Callback &&callback) +{ + // make sure we have at least something to unpack + if (packed_path_begin == packed_path_end) + return; + + std::stack> recursion_stack; + + // We have to push the path in reverse order onto the stack because it's LIFO. + for (auto current = std::prev(packed_path_end); current != packed_path_begin; + current = std::prev(current)) + { + recursion_stack.emplace(*std::prev(current), *current); } - template - void UnpackPath(const FacadeT &facade, - RandomIter packed_path_begin, - RandomIter packed_path_end, - const PhantomNodes &phantom_node_pair, - std::vector &unpacked_path) const + std::pair edge; + while (!recursion_stack.empty()) { - BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0); + edge = recursion_stack.top(); + recursion_stack.pop(); - const bool start_traversed_in_reverse = - (*packed_path_begin != phantom_node_pair.source_phantom.forward_segment_id.id); - const bool target_traversed_in_reverse = - (*std::prev(packed_path_end) != phantom_node_pair.target_phantom.forward_segment_id.id); + // Look for an edge on the forward CH graph (.forward) + EdgeID smaller_edge_id = facade.FindSmallestEdge( + edge.first, edge.second, [](const auto &data) { return data.forward; }); - BOOST_ASSERT(*packed_path_begin == phantom_node_pair.source_phantom.forward_segment_id.id || - *packed_path_begin == phantom_node_pair.source_phantom.reverse_segment_id.id); - BOOST_ASSERT( - *std::prev(packed_path_end) == phantom_node_pair.target_phantom.forward_segment_id.id || - *std::prev(packed_path_end) == phantom_node_pair.target_phantom.reverse_segment_id.id); - - UnpackCHPath( - facade, - packed_path_begin, - packed_path_end, - [this, - &facade, - &unpacked_path, - &phantom_node_pair, - &start_traversed_in_reverse, - &target_traversed_in_reverse](std::pair & /* edge */, - const EdgeData &edge_data) { - - BOOST_ASSERT_MSG(!edge_data.shortcut, "original edge flagged as shortcut"); - const auto name_index = facade.GetNameIndexFromEdgeID(edge_data.id); - const auto turn_instruction = facade.GetTurnInstructionForEdgeID(edge_data.id); - const extractor::TravelMode travel_mode = - (unpacked_path.empty() && start_traversed_in_reverse) - ? phantom_node_pair.source_phantom.backward_travel_mode - : facade.GetTravelModeForEdgeID(edge_data.id); - - const auto geometry_index = facade.GetGeometryIndexForEdgeID(edge_data.id); - std::vector id_vector; - - std::vector weight_vector; - std::vector duration_vector; - std::vector datasource_vector; - if (geometry_index.forward) - { - id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id); - weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id); - duration_vector = facade.GetUncompressedForwardDurations(geometry_index.id); - datasource_vector = facade.GetUncompressedForwardDatasources(geometry_index.id); - } - else - { - id_vector = facade.GetUncompressedReverseGeometry(geometry_index.id); - weight_vector = facade.GetUncompressedReverseWeights(geometry_index.id); - duration_vector = facade.GetUncompressedReverseDurations(geometry_index.id); - datasource_vector = facade.GetUncompressedReverseDatasources(geometry_index.id); - } - BOOST_ASSERT(id_vector.size() > 0); - BOOST_ASSERT(datasource_vector.size() > 0); - BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1); - BOOST_ASSERT(duration_vector.size() == id_vector.size() - 1); - const bool is_first_segment = unpacked_path.empty(); - - const std::size_t start_index = - (is_first_segment - ? ((start_traversed_in_reverse) - ? weight_vector.size() - - phantom_node_pair.source_phantom.fwd_segment_position - 1 - : phantom_node_pair.source_phantom.fwd_segment_position) - : 0); - const std::size_t end_index = weight_vector.size(); - - BOOST_ASSERT(start_index >= 0); - BOOST_ASSERT(start_index < end_index); - for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx) - { - unpacked_path.push_back( - PathData{id_vector[segment_idx + 1], - name_index, - weight_vector[segment_idx], - duration_vector[segment_idx], - extractor::guidance::TurnInstruction::NO_TURN(), - {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, - travel_mode, - INVALID_ENTRY_CLASSID, - datasource_vector[segment_idx], - util::guidance::TurnBearing(0), - util::guidance::TurnBearing(0)}); - } - BOOST_ASSERT(unpacked_path.size() > 0); - if (facade.hasLaneData(edge_data.id)) - unpacked_path.back().lane_data = facade.GetLaneData(edge_data.id); - - unpacked_path.back().entry_classid = facade.GetEntryClassID(edge_data.id); - unpacked_path.back().turn_instruction = turn_instruction; - unpacked_path.back().duration_until_turn += - facade.GetDurationPenaltyForEdgeID(edge_data.id); - unpacked_path.back().weight_until_turn += - facade.GetWeightPenaltyForEdgeID(edge_data.id); - unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(edge_data.id); - unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(edge_data.id); - }); - - std::size_t start_index = 0, end_index = 0; - std::vector id_vector; - std::vector weight_vector; - std::vector duration_vector; - std::vector datasource_vector; - const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == - phantom_node_pair.target_phantom.packed_geometry_id) && - unpacked_path.empty(); - - if (target_traversed_in_reverse) + // If we didn't find one there, the we might be looking at a part of the path that + // was found using the backward search. Here, we flip the node order (.second, .first) + // and only consider edges with the `.backward` flag. + if (SPECIAL_EDGEID == smaller_edge_id) { - id_vector = facade.GetUncompressedReverseGeometry( - phantom_node_pair.target_phantom.packed_geometry_id); + smaller_edge_id = facade.FindSmallestEdge( + edge.second, edge.first, [](const auto &data) { return data.backward; }); + } - weight_vector = facade.GetUncompressedReverseWeights( - phantom_node_pair.target_phantom.packed_geometry_id); + // If we didn't find anything *still*, then something is broken and someone has + // called this function with bad values. + BOOST_ASSERT_MSG(smaller_edge_id != SPECIAL_EDGEID, "Invalid smaller edge ID"); - duration_vector = facade.GetUncompressedReverseDurations( - phantom_node_pair.target_phantom.packed_geometry_id); + const auto &data = facade.GetEdgeData(smaller_edge_id); + BOOST_ASSERT_MSG(data.weight != std::numeric_limits::max(), + "edge weight invalid"); - datasource_vector = facade.GetUncompressedReverseDatasources( - phantom_node_pair.target_phantom.packed_geometry_id); - - if (is_local_path) - { - start_index = weight_vector.size() - - phantom_node_pair.source_phantom.fwd_segment_position - 1; - } - end_index = - weight_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1; + // If the edge is a shortcut, we need to add the two halfs to the stack. + if (data.shortcut) + { // unpack + const NodeID middle_node_id = data.id; + // Note the order here - we're adding these to a stack, so we + // want the first->middle to get visited before middle->second + recursion_stack.emplace(middle_node_id, edge.second); + recursion_stack.emplace(edge.first, middle_node_id); } else { - if (is_local_path) - { - start_index = phantom_node_pair.source_phantom.fwd_segment_position; - } - end_index = phantom_node_pair.target_phantom.fwd_segment_position; - - id_vector = facade.GetUncompressedForwardGeometry( - phantom_node_pair.target_phantom.packed_geometry_id); - - weight_vector = facade.GetUncompressedForwardWeights( - phantom_node_pair.target_phantom.packed_geometry_id); - - duration_vector = facade.GetUncompressedForwardDurations( - phantom_node_pair.target_phantom.packed_geometry_id); - - datasource_vector = facade.GetUncompressedForwardDatasources( - phantom_node_pair.target_phantom.packed_geometry_id); - } - - // Given the following compressed geometry: - // U---v---w---x---y---Z - // s t - // s: fwd_segment 0 - // t: fwd_segment 3 - // -> (U, v), (v, w), (w, x) - // note that (x, t) is _not_ included but needs to be added later. - for (std::size_t segment_idx = start_index; segment_idx != end_index; - (start_index < end_index ? ++segment_idx : --segment_idx)) - { - BOOST_ASSERT(segment_idx < id_vector.size() - 1); - BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0); - unpacked_path.push_back(PathData{ - id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], - phantom_node_pair.target_phantom.name_id, - weight_vector[segment_idx], - duration_vector[segment_idx], - extractor::guidance::TurnInstruction::NO_TURN(), - {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, - target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode - : phantom_node_pair.target_phantom.forward_travel_mode, - INVALID_ENTRY_CLASSID, - datasource_vector[segment_idx], - util::guidance::TurnBearing(0), - util::guidance::TurnBearing(0)}); - } - - if (unpacked_path.size() > 0) - { - const auto source_weight = start_traversed_in_reverse - ? phantom_node_pair.source_phantom.reverse_weight - : phantom_node_pair.source_phantom.forward_weight; - const auto source_duration = start_traversed_in_reverse - ? phantom_node_pair.source_phantom.reverse_duration - : phantom_node_pair.source_phantom.forward_duration; - // The above code will create segments for (v, w), (w,x), (x, y) and (y, Z). - // However the first segment duration needs to be adjusted to the fact that the source - // phantom is in the middle of the segment. We do this by subtracting v--s from the - // duration. - - // Since it's possible duration_until_turn can be less than source_weight here if - // a negative enough turn penalty is used to modify this edge weight during - // osrm-contract, we clamp to 0 here so as not to return a negative duration - // for this segment. - - // TODO this creates a scenario where it's possible the duration from a phantom - // node to the first turn would be the same as from end to end of a segment, - // which is obviously incorrect and not ideal... - unpacked_path.front().weight_until_turn = - std::max(unpacked_path.front().weight_until_turn - source_weight, 0); - unpacked_path.front().duration_until_turn = - std::max(unpacked_path.front().duration_until_turn - source_duration, 0); - } - - // there is no equivalent to a node-based node in an edge-expanded graph. - // two equivalent routes may start (or end) at different node-based edges - // as they are added with the offset how much "weight" on the edge - // has already been traversed. Depending on offset one needs to remove - // the last node. - if (unpacked_path.size() > 1) - { - const std::size_t last_index = unpacked_path.size() - 1; - const std::size_t second_to_last_index = last_index - 1; - - if (unpacked_path[last_index].turn_via_node == - unpacked_path[second_to_last_index].turn_via_node) - { - unpacked_path.pop_back(); - } - BOOST_ASSERT(!unpacked_path.empty()); + // We found an original edge, call our callback. + std::forward(callback)(edge, data); } } +} - /** - * Unpacks a single edge (NodeID->NodeID) from the CH graph down to it's original non-shortcut - * route. - * @param from the node the CH edge starts at - * @param to the node the CH edge finishes at - * @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge - */ - void UnpackEdge(const FacadeT &facade, - const NodeID from, - const NodeID to, - std::vector &unpacked_path) const; +// Should work both for CH and not CH if the unpackPath function above is implemented a proper +// implementation. +template +void unpackPath(const FacadeT &facade, + RandomIter packed_path_begin, + RandomIter packed_path_end, + const PhantomNodes &phantom_node_pair, + std::vector &unpacked_path) +{ + BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0); - void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, - const SearchEngineData::QueryHeap &reverse_heap, - const NodeID middle_node_id, - std::vector &packed_path) const; + const bool start_traversed_in_reverse = + (*packed_path_begin != phantom_node_pair.source_phantom.forward_segment_id.id); + const bool target_traversed_in_reverse = + (*std::prev(packed_path_end) != phantom_node_pair.target_phantom.forward_segment_id.id); - void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, - const NodeID middle_node_id, - std::vector &packed_path) const; + BOOST_ASSERT(*packed_path_begin == phantom_node_pair.source_phantom.forward_segment_id.id || + *packed_path_begin == phantom_node_pair.source_phantom.reverse_segment_id.id); + BOOST_ASSERT( + *std::prev(packed_path_end) == phantom_node_pair.target_phantom.forward_segment_id.id || + *std::prev(packed_path_end) == phantom_node_pair.target_phantom.reverse_segment_id.id); - // assumes that heaps are already setup correctly. - // ATTENTION: This only works if no additional offset is supplied next to the Phantom Node - // Offsets. - // In case additional offsets are supplied, you might have to force a loop first. - // 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 - // than the target - // then a force loop is required (e.g. source_phantom.forward_segment_id == - // target_phantom.forward_segment_id - // && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) - // requires - // a force loop, if the heaps have been initialized with positive offsets. - void Search(const FacadeT &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - 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) const; + unpackPath( + facade, + packed_path_begin, + packed_path_end, + [&facade, + &unpacked_path, + &phantom_node_pair, + &start_traversed_in_reverse, + &target_traversed_in_reverse](std::pair & /* edge */, + const auto &edge_data) { - // 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 - // than the target - // then a force loop is required (e.g. source_phantom.forward_segment_id == - // target_phantom.forward_segment_id - // && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) - // requires - // a force loop, if the heaps have been initialized with positive offsets. - void SearchWithCore(const FacadeT &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) const; + BOOST_ASSERT_MSG(!edge_data.shortcut, "original edge flagged as shortcut"); + const auto name_index = facade.GetNameIndexFromEdgeID(edge_data.id); + const auto turn_instruction = facade.GetTurnInstructionForEdgeID(edge_data.id); + const extractor::TravelMode travel_mode = + (unpacked_path.empty() && start_traversed_in_reverse) + ? phantom_node_pair.source_phantom.backward_travel_mode + : facade.GetTravelModeForEdgeID(edge_data.id); - bool NeedsLoopForward(const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const; + const auto geometry_index = facade.GetGeometryIndexForEdgeID(edge_data.id); + std::vector id_vector; - bool NeedsLoopBackwards(const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const; + std::vector weight_vector; + std::vector duration_vector; + std::vector datasource_vector; + if (geometry_index.forward) + { + id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id); + weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id); + duration_vector = facade.GetUncompressedForwardDurations(geometry_index.id); + datasource_vector = facade.GetUncompressedForwardDatasources(geometry_index.id); + } + else + { + id_vector = facade.GetUncompressedReverseGeometry(geometry_index.id); + weight_vector = facade.GetUncompressedReverseWeights(geometry_index.id); + duration_vector = facade.GetUncompressedReverseDurations(geometry_index.id); + datasource_vector = facade.GetUncompressedReverseDatasources(geometry_index.id); + } + BOOST_ASSERT(id_vector.size() > 0); + BOOST_ASSERT(datasource_vector.size() > 0); + BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1); + BOOST_ASSERT(duration_vector.size() == id_vector.size() - 1); + const bool is_first_segment = unpacked_path.empty(); - double GetPathDistance(const FacadeT &facade, - const std::vector &packed_path, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const; + const std::size_t start_index = + (is_first_segment + ? ((start_traversed_in_reverse) + ? weight_vector.size() - + phantom_node_pair.source_phantom.fwd_segment_position - 1 + : phantom_node_pair.source_phantom.fwd_segment_position) + : 0); + const std::size_t end_index = weight_vector.size(); - // Requires the heaps for be empty - // If heaps should be adjusted to be initialized outside of this function, - // the addition of force_loop parameters might be required - double GetNetworkDistanceWithCore(const FacadeT &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) const; + BOOST_ASSERT(start_index >= 0); + BOOST_ASSERT(start_index < end_index); + for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx) + { + unpacked_path.push_back(PathData{id_vector[segment_idx + 1], + name_index, + weight_vector[segment_idx], + duration_vector[segment_idx], + extractor::guidance::TurnInstruction::NO_TURN(), + {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, + travel_mode, + INVALID_ENTRY_CLASSID, + datasource_vector[segment_idx], + util::guidance::TurnBearing(0), + util::guidance::TurnBearing(0)}); + } + BOOST_ASSERT(unpacked_path.size() > 0); + if (facade.hasLaneData(edge_data.id)) + unpacked_path.back().lane_data = facade.GetLaneData(edge_data.id); - // Requires the heaps for be empty - // If heaps should be adjusted to be initialized outside of this function, - // the addition of force_loop parameters might be required - double GetNetworkDistance(const FacadeT &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom, - int duration_upper_bound = INVALID_EDGE_WEIGHT) const; -}; + unpacked_path.back().entry_classid = facade.GetEntryClassID(edge_data.id); + unpacked_path.back().turn_instruction = turn_instruction; + unpacked_path.back().duration_until_turn += + facade.GetDurationPenaltyForEdgeID(edge_data.id); + unpacked_path.back().weight_until_turn += + facade.GetWeightPenaltyForEdgeID(edge_data.id); + unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(edge_data.id); + unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(edge_data.id); + }); + + std::size_t start_index = 0, end_index = 0; + std::vector id_vector; + std::vector weight_vector; + std::vector duration_vector; + std::vector datasource_vector; + const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == + phantom_node_pair.target_phantom.packed_geometry_id) && + unpacked_path.empty(); + + if (target_traversed_in_reverse) + { + id_vector = facade.GetUncompressedReverseGeometry( + phantom_node_pair.target_phantom.packed_geometry_id); + + weight_vector = facade.GetUncompressedReverseWeights( + phantom_node_pair.target_phantom.packed_geometry_id); + + duration_vector = facade.GetUncompressedReverseDurations( + phantom_node_pair.target_phantom.packed_geometry_id); + + datasource_vector = facade.GetUncompressedReverseDatasources( + phantom_node_pair.target_phantom.packed_geometry_id); + + if (is_local_path) + { + start_index = + weight_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1; + } + end_index = + weight_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1; + } + else + { + if (is_local_path) + { + start_index = phantom_node_pair.source_phantom.fwd_segment_position; + } + end_index = phantom_node_pair.target_phantom.fwd_segment_position; + + id_vector = facade.GetUncompressedForwardGeometry( + phantom_node_pair.target_phantom.packed_geometry_id); + + weight_vector = facade.GetUncompressedForwardWeights( + phantom_node_pair.target_phantom.packed_geometry_id); + + duration_vector = facade.GetUncompressedForwardDurations( + phantom_node_pair.target_phantom.packed_geometry_id); + + datasource_vector = facade.GetUncompressedForwardDatasources( + phantom_node_pair.target_phantom.packed_geometry_id); + } + + // Given the following compressed geometry: + // U---v---w---x---y---Z + // s t + // s: fwd_segment 0 + // t: fwd_segment 3 + // -> (U, v), (v, w), (w, x) + // note that (x, t) is _not_ included but needs to be added later. + for (std::size_t segment_idx = start_index; segment_idx != end_index; + (start_index < end_index ? ++segment_idx : --segment_idx)) + { + BOOST_ASSERT(segment_idx < id_vector.size() - 1); + BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0); + unpacked_path.push_back(PathData{ + id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], + phantom_node_pair.target_phantom.name_id, + weight_vector[segment_idx], + duration_vector[segment_idx], + extractor::guidance::TurnInstruction::NO_TURN(), + {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, + target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode + : phantom_node_pair.target_phantom.forward_travel_mode, + INVALID_ENTRY_CLASSID, + datasource_vector[segment_idx], + util::guidance::TurnBearing(0), + util::guidance::TurnBearing(0)}); + } + + if (unpacked_path.size() > 0) + { + const auto source_weight = start_traversed_in_reverse + ? phantom_node_pair.source_phantom.reverse_weight + : phantom_node_pair.source_phantom.forward_weight; + const auto source_duration = start_traversed_in_reverse + ? phantom_node_pair.source_phantom.reverse_duration + : phantom_node_pair.source_phantom.forward_duration; + // The above code will create segments for (v, w), (w,x), (x, y) and (y, Z). + // However the first segment duration needs to be adjusted to the fact that the source + // phantom is in the middle of the segment. We do this by subtracting v--s from the + // duration. + + // Since it's possible duration_until_turn can be less than source_weight here if + // a negative enough turn penalty is used to modify this edge weight during + // osrm-contract, we clamp to 0 here so as not to return a negative duration + // for this segment. + + // TODO this creates a scenario where it's possible the duration from a phantom + // node to the first turn would be the same as from end to end of a segment, + // which is obviously incorrect and not ideal... + unpacked_path.front().weight_until_turn = + std::max(unpacked_path.front().weight_until_turn - source_weight, 0); + unpacked_path.front().duration_until_turn = + std::max(unpacked_path.front().duration_until_turn - source_duration, 0); + } + + // there is no equivalent to a node-based node in an edge-expanded graph. + // two equivalent routes may start (or end) at different node-based edges + // as they are added with the offset how much "weight" on the edge + // has already been traversed. Depending on offset one needs to remove + // the last node. + if (unpacked_path.size() > 1) + { + const std::size_t last_index = unpacked_path.size() - 1; + const std::size_t second_to_last_index = last_index - 1; + + if (unpacked_path[last_index].turn_via_node == + unpacked_path[second_to_last_index].turn_via_node) + { + unpacked_path.pop_back(); + } + BOOST_ASSERT(!unpacked_path.empty()); + } +} + +/** + * Unpacks a single edge (NodeID->NodeID) from the CH graph down to it's original non-shortcut + * route. + * @param from the node the CH edge starts at + * @param to the node the CH edge finishes at + * @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge + */ +void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const NodeID from, + const NodeID to, + std::vector &unpacked_path); + +void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, + const SearchEngineData::QueryHeap &reverse_heap, + const NodeID middle_node_id, + std::vector &packed_path); + +void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, + const NodeID middle_node_id, + std::vector &packed_path); + +// assumes that heaps are already setup correctly. +// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node +// Offsets. +// In case additional offsets are supplied, you might have to force a loop first. +// 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 +// than the target +// then a force loop is required (e.g. source_phantom.forward_segment_id == +// target_phantom.forward_segment_id +// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) +// requires +// a force loop, if the heaps have been initialized with positive offsets. +void search(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + 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); + +// 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 +// than the target +// then a force loop is required (e.g. source_phantom.forward_segment_id == +// target_phantom.forward_segment_id +// && 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); + +bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom); + +bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom); + +double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &packed_path, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom); + +// Requires the heaps for be empty +// If heaps should be adjusted to be initialized outside of this function, +// the addition of force_loop parameters might be required +double getNetworkDistanceWithCore( + 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, +// the addition of force_loop parameters might be required +double +getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + int duration_upper_bound = INVALID_EDGE_WEIGHT); } // namespace routing_algorithms } // namespace engine diff --git a/include/engine/routing_algorithms/shortest_path.hpp b/include/engine/routing_algorithms/shortest_path.hpp index 69e5a2421..59159dfd0 100644 --- a/include/engine/routing_algorithms/shortest_path.hpp +++ b/include/engine/routing_algorithms/shortest_path.hpp @@ -4,13 +4,8 @@ #include "engine/algorithm.hpp" #include "engine/routing_algorithms/routing_base.hpp" #include "engine/search_engine_data.hpp" -#include "util/integer_range.hpp" #include "util/typedefs.hpp" -#include -#include -#include - namespace osrm { namespace engine @@ -18,75 +13,12 @@ namespace engine namespace routing_algorithms { -template class ShortestPathRouting; +InternalRouteResult +shortestPathSearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector, + const boost::optional continue_straight_at_waypoint); -template <> class ShortestPathRouting final : public BasicRouting -{ - using super = BasicRouting; - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; - using QueryHeap = SearchEngineData::QueryHeap; - SearchEngineData &engine_working_data; - const static constexpr bool DO_NOT_FORCE_LOOP = false; - - public: - ShortestPathRouting(SearchEngineData &engine_working_data) - : engine_working_data(engine_working_data) - { - } - - ~ShortestPathRouting() {} - - // allows a uturn at the target_phantom - // searches source forward/reverse -> target forward/reverse - void SearchWithUTurn(const FacadeT &facade, - QueryHeap &forward_heap, - QueryHeap &reverse_heap, - QueryHeap &forward_core_heap, - QueryHeap &reverse_core_heap, - const bool search_from_forward_node, - const bool search_from_reverse_node, - const bool search_to_forward_node, - const bool search_to_reverse_node, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom, - const int total_weight_to_forward, - const int total_weight_to_reverse, - int &new_total_weight, - std::vector &leg_packed_path) const; - - // searches shortest path between: - // source forward/reverse -> target forward - // source forward/reverse -> target reverse - void Search(const FacadeT &facade, - QueryHeap &forward_heap, - QueryHeap &reverse_heap, - QueryHeap &forward_core_heap, - QueryHeap &reverse_core_heap, - const bool search_from_forward_node, - const bool search_from_reverse_node, - const bool search_to_forward_node, - const bool search_to_reverse_node, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom, - const int total_weight_to_forward, - const int total_weight_to_reverse, - int &new_total_weight_to_forward, - int &new_total_weight_to_reverse, - std::vector &leg_packed_path_forward, - std::vector &leg_packed_path_reverse) const; - - void UnpackLegs(const FacadeT &facade, - const std::vector &phantom_nodes_vector, - const std::vector &total_packed_path, - const std::vector &packed_leg_begin, - const int shortest_path_length, - InternalRouteResult &raw_route_data) const; - - void operator()(const FacadeT &facade, - const std::vector &phantom_nodes_vector, - const boost::optional continue_straight_at_waypoint, - InternalRouteResult &raw_route_data) const; -}; } // namespace routing_algorithms } // namespace engine } // namespace osrm diff --git a/include/engine/routing_algorithms/tile_turns.hpp b/include/engine/routing_algorithms/tile_turns.hpp index f3f92c545..6baa8ef0d 100644 --- a/include/engine/routing_algorithms/tile_turns.hpp +++ b/include/engine/routing_algorithms/tile_turns.hpp @@ -1,12 +1,14 @@ #ifndef OSRM_ENGINE_ROUTING_ALGORITHMS_TILE_TURNS_HPP #define OSRM_ENGINE_ROUTING_ALGORITHMS_TILE_TURNS_HPP -#include "engine/routing_algorithms/routing_base.hpp" - #include "engine/algorithm.hpp" -#include "engine/search_engine_data.hpp" +#include "engine/datafacade/contiguous_internalmem_datafacade.hpp" + +#include "util/coordinate.hpp" #include "util/typedefs.hpp" +#include + namespace osrm { namespace engine @@ -14,8 +16,6 @@ namespace engine namespace routing_algorithms { -template class TileTurns; - // Used to accumulate all the information we want in the tile about a turn. struct TurnData final { @@ -25,19 +25,12 @@ struct TurnData final const int weight; }; -/// This class is used to extract turn information for the tile plugin from a CH graph -template <> class TileTurns final : public BasicRouting -{ - using super = BasicRouting; - using FacadeT = datafacade::ContiguousInternalMemoryDataFacade; +using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf; - using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf; - - public: - std::vector operator()(const FacadeT &facade, - const std::vector &edges, - const std::vector &sorted_edge_indexes) const; -}; +std::vector +getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &edges, + const std::vector &sorted_edge_indexes); } // namespace routing_algorithms } // namespace engine diff --git a/src/engine/plugins/match.cpp b/src/engine/plugins/match.cpp index de9216b86..eeedf478f 100644 --- a/src/engine/plugins/match.cpp +++ b/src/engine/plugins/match.cpp @@ -208,8 +208,8 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData // force uturns to be on, since we split the phantom nodes anyway and only have // bi-directional // phantom nodes for possible uturns - algorithms.ShortestRouting( - sub_routes[index].segment_end_coordinates, {false}, sub_routes[index]); + sub_routes[index] = + algorithms.ShortestRouting(sub_routes[index].segment_end_coordinates, {false}); BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT); } diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index 2bea804a3..9168cee11 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -1,5 +1,4 @@ #include "engine/plugins/tile.hpp" -#include "engine/edge_unpacker.hpp" #include "engine/plugins/plugin_base.hpp" #include "util/coordinate_calculation.hpp" diff --git a/src/engine/plugins/trip.cpp b/src/engine/plugins/trip.cpp index dbcd85033..fa67a3199 100644 --- a/src/engine/plugins/trip.cpp +++ b/src/engine/plugins/trip.cpp @@ -85,7 +85,7 @@ InternalRouteResult TripPlugin::ComputeRoute(const RoutingAlgorithmsInterface &a BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size() - 1); } - algorithms.ShortestRouting(min_route.segment_end_coordinates, {false}, min_route); + min_route = algorithms.ShortestRouting(min_route.segment_end_coordinates, {false}); BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route"); return min_route; } diff --git a/src/engine/plugins/viaroute.cpp b/src/engine/plugins/viaroute.cpp index 86ea8b300..7c5d6f1e2 100644 --- a/src/engine/plugins/viaroute.cpp +++ b/src/engine/plugins/viaroute.cpp @@ -89,17 +89,17 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca { if (route_parameters.alternatives && algorithms.HasAlternativeRouting()) { - algorithms.AlternativeRouting(raw_route.segment_end_coordinates.front(), raw_route); + raw_route = algorithms.AlternativeRouting(raw_route.segment_end_coordinates.front()); } else { - algorithms.DirectShortestPathRouting(raw_route.segment_end_coordinates, raw_route); + raw_route = algorithms.DirectShortestPathRouting(raw_route.segment_end_coordinates); } } else { - algorithms.ShortestRouting( - raw_route.segment_end_coordinates, route_parameters.continue_straight, raw_route); + raw_route = algorithms.ShortestRouting(raw_route.segment_end_coordinates, + route_parameters.continue_straight); } // we can only know this after the fact, different SCC ids still diff --git a/src/engine/routing_algorithms/alternative_path.cpp b/src/engine/routing_algorithms/alternative_path.cpp index 3da1dd5e4..769094c3e 100644 --- a/src/engine/routing_algorithms/alternative_path.cpp +++ b/src/engine/routing_algorithms/alternative_path.cpp @@ -1,4 +1,17 @@ #include "engine/routing_algorithms/alternative_path.hpp" +#include "engine/routing_algorithms/routing_base.hpp" + +#include "util/integer_range.hpp" + +#include + +#include +#include +#include +#include +#include + +#include namespace osrm { @@ -7,335 +20,131 @@ namespace engine namespace routing_algorithms { -void AlternativeRouting::operator()(const FacadeT &facade, - const PhantomNodes &phantom_node_pair, - InternalRouteResult &raw_route_data) +namespace { - std::vector alternative_path; - std::vector via_node_candidate_list; - std::vector forward_search_space; - std::vector reverse_search_space; +const double constexpr VIAPATH_ALPHA = 0.10; +const double constexpr VIAPATH_EPSILON = 0.15; // alternative at most 15% longer +const double constexpr VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest. - // Init queues, semi-expensive because access to TSS invokes a sys-call - engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); - engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes()); - engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes()); +using QueryHeap = SearchEngineData::QueryHeap; +using SearchSpaceEdge = std::pair; - QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1); - QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1); - QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2); - QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2); - - EdgeWeight upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT; - NodeID middle_node = SPECIAL_NODEID; - const EdgeWeight min_edge_offset = - std::min(phantom_node_pair.source_phantom.forward_segment_id.enabled - ? -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset() - : 0, - phantom_node_pair.source_phantom.reverse_segment_id.enabled - ? -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset() - : 0); - - if (phantom_node_pair.source_phantom.forward_segment_id.enabled) +struct RankedCandidateNode +{ + RankedCandidateNode(const NodeID node, const int length, const int sharing) + : node(node), length(length), sharing(sharing) { - BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID); - forward_heap1.Insert(phantom_node_pair.source_phantom.forward_segment_id.id, - -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), - phantom_node_pair.source_phantom.forward_segment_id.id); - } - if (phantom_node_pair.source_phantom.reverse_segment_id.enabled) - { - BOOST_ASSERT(phantom_node_pair.source_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID); - forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_segment_id.id, - -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), - phantom_node_pair.source_phantom.reverse_segment_id.id); } - if (phantom_node_pair.target_phantom.forward_segment_id.enabled) - { - BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id != SPECIAL_SEGMENTID); - reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_segment_id.id, - phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), - phantom_node_pair.target_phantom.forward_segment_id.id); - } - if (phantom_node_pair.target_phantom.reverse_segment_id.enabled) - { - BOOST_ASSERT(phantom_node_pair.target_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID); - reverse_heap1.Insert(phantom_node_pair.target_phantom.reverse_segment_id.id, - phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), - phantom_node_pair.target_phantom.reverse_segment_id.id); - } + NodeID node; + int length; + int sharing; - // search from s and t till new_min/(1+epsilon) > length_of_shortest_path - while (0 < (forward_heap1.Size() + reverse_heap1.Size())) + bool operator<(const RankedCandidateNode &other) const { - if (0 < forward_heap1.Size()) - { - AlternativeRoutingStep(facade, - forward_heap1, - reverse_heap1, - &middle_node, - &upper_bound_to_shortest_path_weight, - via_node_candidate_list, - forward_search_space, - min_edge_offset); - } - if (0 < reverse_heap1.Size()) - { - AlternativeRoutingStep(facade, - forward_heap1, - reverse_heap1, - &middle_node, - &upper_bound_to_shortest_path_weight, - via_node_candidate_list, - reverse_search_space, - min_edge_offset); - } + return (2 * length + sharing) < (2 * other.length + other.sharing); } +}; - if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_weight) +// todo: reorder parameters +template +void alternativeRoutingStep( + const datafacade::ContiguousInternalMemoryDataFacade &facade, + QueryHeap &heap1, + QueryHeap &heap2, + NodeID *middle_node, + EdgeWeight *upper_bound_to_shortest_path_weight, + std::vector &search_space_intersection, + std::vector &search_space, + const EdgeWeight min_edge_offset) +{ + QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2); + QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1); + + const NodeID node = forward_heap.DeleteMin(); + const EdgeWeight weight = forward_heap.GetKey(node); + + const auto scaled_weight = + static_cast((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)) { + forward_heap.DeleteAll(); return; } - std::sort(begin(via_node_candidate_list), end(via_node_candidate_list)); - auto unique_end = std::unique(begin(via_node_candidate_list), end(via_node_candidate_list)); - via_node_candidate_list.resize(unique_end - begin(via_node_candidate_list)); + search_space.emplace_back(forward_heap.GetData(node).parent, node); - std::vector packed_forward_path; - std::vector packed_reverse_path; - - const bool path_is_a_loop = - upper_bound_to_shortest_path_weight != - forward_heap1.GetKey(middle_node) + reverse_heap1.GetKey(middle_node); - if (path_is_a_loop) + if (reverse_heap.WasInserted(node)) { - // Self Loop - packed_forward_path.push_back(middle_node); - packed_forward_path.push_back(middle_node); - } - else - { - - super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path); - super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path); - } - - // this set is is used as an indicator if a node is on the shortest path - std::unordered_set nodes_in_path(packed_forward_path.size() + - packed_reverse_path.size()); - nodes_in_path.insert(packed_forward_path.begin(), packed_forward_path.end()); - nodes_in_path.insert(middle_node); - nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end()); - - std::unordered_map approximated_forward_sharing; - std::unordered_map approximated_reverse_sharing; - - // sweep over search space, compute forward sharing for each current edge (u,v) - for (const SearchSpaceEdge ¤t_edge : forward_search_space) - { - const NodeID u = current_edge.first; - const NodeID v = current_edge.second; - - if (nodes_in_path.find(v) != nodes_in_path.end()) + search_space_intersection.emplace_back(node); + const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight; + if (new_weight < *upper_bound_to_shortest_path_weight) { - // current_edge is on shortest path => sharing(v):=queue.GetKey(v); - approximated_forward_sharing.emplace(v, forward_heap1.GetKey(v)); - } - else - { - // current edge is not on shortest path. Check if we know a value for the other - // endpoint - const auto sharing_of_u_iterator = approximated_forward_sharing.find(u); - if (sharing_of_u_iterator != approximated_forward_sharing.end()) + if (new_weight >= 0) { - approximated_forward_sharing.emplace(v, sharing_of_u_iterator->second); + *middle_node = node; + *upper_bound_to_shortest_path_weight = new_weight; + } + else + { + // check whether there is a loop present at the node + const auto loop_weight = getLoopWeight(facade, 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; + *upper_bound_to_shortest_path_weight = loop_weight; + } } } } - // sweep over search space, compute backward sharing - for (const SearchSpaceEdge ¤t_edge : reverse_search_space) + for (auto edge : facade.GetAdjacentEdgeRange(node)) { - const NodeID u = current_edge.first; - const NodeID v = current_edge.second; - if (nodes_in_path.find(v) != nodes_in_path.end()) + const auto &data = facade.GetEdgeData(edge); + const bool edge_is_forward_directed = (is_forward_directed ? data.forward : data.backward); + if (edge_is_forward_directed) { - // current_edge is on shortest path => sharing(u):=queue.GetKey(u); - approximated_reverse_sharing.emplace(v, reverse_heap1.GetKey(v)); - } - else - { - // current edge is not on shortest path. Check if we know a value for the other - // endpoint - const auto sharing_of_u_iterator = approximated_reverse_sharing.find(u); - if (sharing_of_u_iterator != approximated_reverse_sharing.end()) + const NodeID to = facade.GetTarget(edge); + const EdgeWeight edge_weight = data.weight; + + BOOST_ASSERT(edge_weight > 0); + const EdgeWeight to_weight = weight + edge_weight; + + // New Node discovered -> Add to Heap + Node Info Storage + if (!forward_heap.WasInserted(to)) { - approximated_reverse_sharing.emplace(v, sharing_of_u_iterator->second); + forward_heap.Insert(to, to_weight, node); + } + // Found a shorter Path -> Update weight + else if (to_weight < forward_heap.GetKey(to)) + { + // new parent + forward_heap.GetData(to).parent = node; + // decreased weight + forward_heap.DecreaseKey(to, to_weight); } } } - - // util::Log(logDEBUG) << "fwd_search_space size: " << - // forward_search_space.size() << ", marked " << approximated_forward_sharing.size() << " - // nodes"; - // util::Log(logDEBUG) << "rev_search_space size: " << - // reverse_search_space.size() << ", marked " << approximated_reverse_sharing.size() << " - // nodes"; - - std::vector preselected_node_list; - for (const NodeID node : via_node_candidate_list) - { - if (node == middle_node) - continue; - const auto fwd_iterator = approximated_forward_sharing.find(node); - const int fwd_sharing = - (fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0; - const auto rev_iterator = approximated_reverse_sharing.find(node); - const int rev_sharing = - (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0; - - const int approximated_sharing = fwd_sharing + rev_sharing; - const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node); - const bool length_passes = - (approximated_length < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON)); - const bool sharing_passes = - (approximated_sharing <= upper_bound_to_shortest_path_weight * VIAPATH_GAMMA); - const bool stretch_passes = - (approximated_length - approximated_sharing) < - ((1. + VIAPATH_ALPHA) * (upper_bound_to_shortest_path_weight - approximated_sharing)); - - if (length_passes && sharing_passes && stretch_passes) - { - preselected_node_list.emplace_back(node); - } - } - - std::vector &packed_shortest_path = packed_forward_path; - if (!path_is_a_loop) - { - std::reverse(packed_shortest_path.begin(), packed_shortest_path.end()); - packed_shortest_path.emplace_back(middle_node); - packed_shortest_path.insert( - packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end()); - } - std::vector ranked_candidates_list; - - // prioritizing via nodes for deep inspection - for (const NodeID node : preselected_node_list) - { - int length_of_via_path = 0, sharing_of_via_path = 0; - ComputeLengthAndSharingOfViaPath(facade, - node, - &length_of_via_path, - &sharing_of_via_path, - packed_shortest_path, - min_edge_offset); - const int maximum_allowed_sharing = - static_cast(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA); - if (sharing_of_via_path <= maximum_allowed_sharing && - length_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON)) - { - ranked_candidates_list.emplace_back(node, length_of_via_path, sharing_of_via_path); - } - } - std::sort(ranked_candidates_list.begin(), ranked_candidates_list.end()); - - NodeID selected_via_node = SPECIAL_NODEID; - int length_of_via_path = INVALID_EDGE_WEIGHT; - NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID; - for (const RankedCandidateNode &candidate : ranked_candidates_list) - { - if (ViaNodeCandidatePassesTTest(facade, - forward_heap1, - reverse_heap1, - forward_heap2, - reverse_heap2, - candidate, - upper_bound_to_shortest_path_weight, - &length_of_via_path, - &s_v_middle, - &v_t_middle, - min_edge_offset)) - { - // select first admissable - selected_via_node = candidate.node; - break; - } - } - - // Unpack shortest path and alternative, if they exist - if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_weight) - { - BOOST_ASSERT(!packed_shortest_path.empty()); - raw_route_data.unpacked_path_segments.resize(1); - raw_route_data.source_traversed_in_reverse.push_back( - (packed_shortest_path.front() != - phantom_node_pair.source_phantom.forward_segment_id.id)); - raw_route_data.target_traversed_in_reverse.push_back(( - packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); - - super::UnpackPath(facade, - // -- packed input - packed_shortest_path.begin(), - packed_shortest_path.end(), - // -- start of route - phantom_node_pair, - // -- unpacked output - raw_route_data.unpacked_path_segments.front()); - raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight; - } - - if (SPECIAL_NODEID != selected_via_node) - { - std::vector packed_alternate_path; - // retrieve alternate path - RetrievePackedAlternatePath(forward_heap1, - reverse_heap1, - forward_heap2, - reverse_heap2, - s_v_middle, - v_t_middle, - packed_alternate_path); - - raw_route_data.alt_source_traversed_in_reverse.push_back( - (packed_alternate_path.front() != - phantom_node_pair.source_phantom.forward_segment_id.id)); - raw_route_data.alt_target_traversed_in_reverse.push_back( - (packed_alternate_path.back() != - phantom_node_pair.target_phantom.forward_segment_id.id)); - - // unpack the alternate path - super::UnpackPath(facade, - packed_alternate_path.begin(), - packed_alternate_path.end(), - phantom_node_pair, - raw_route_data.unpacked_alternative); - - raw_route_data.alternative_path_length = length_of_via_path; - } - else - { - BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT); - } } -void AlternativeRouting::RetrievePackedAlternatePath( - const QueryHeap &forward_heap1, - const QueryHeap &reverse_heap1, - const QueryHeap &forward_heap2, - const QueryHeap &reverse_heap2, - const NodeID s_v_middle, - const NodeID v_t_middle, - std::vector &packed_path) const +void retrievePackedAlternatePath(const QueryHeap &forward_heap1, + const QueryHeap &reverse_heap1, + const QueryHeap &forward_heap2, + const QueryHeap &reverse_heap2, + const NodeID s_v_middle, + const NodeID v_t_middle, + std::vector &packed_path) { // fetch packed path [s,v) std::vector packed_v_t_path; - super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path); + retrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path); packed_path.pop_back(); // remove middle node. It's in both half-paths // fetch patched path [v,t] - super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path); + retrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path); packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end()); } @@ -344,8 +153,9 @@ void AlternativeRouting::RetrievePackedAlternatePath( // compute and unpack and by exploring search spaces // from v and intersecting against queues. only half-searches have to be // done at this stage -void AlternativeRouting::ComputeLengthAndSharingOfViaPath( - const FacadeT &facade, +void computeLengthAndSharingOfViaPath( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path, @@ -373,16 +183,16 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath( const bool constexpr DO_NOT_FORCE_LOOPS = false; while (!new_reverse_heap.Empty()) { - super::RoutingStep(facade, - new_reverse_heap, - existing_forward_heap, - s_v_middle, - upper_bound_s_v_path_length, - min_edge_offset, - false, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_reverse_heap, + existing_forward_heap, + s_v_middle, + upper_bound_s_v_path_length, + min_edge_offset, + false, + STALLING_ENABLED, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } // compute path by reusing backward search from node t NodeID v_t_middle = SPECIAL_NODEID; @@ -390,16 +200,16 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath( new_forward_heap.Insert(via_node, 0, via_node); while (!new_forward_heap.Empty()) { - super::RoutingStep(facade, - new_forward_heap, - existing_reverse_heap, - v_t_middle, - upper_bound_of_v_t_path_length, - min_edge_offset, - true, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_forward_heap, + existing_reverse_heap, + v_t_middle, + upper_bound_of_v_t_path_length, + min_edge_offset, + true, + STALLING_ENABLED, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } *real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; @@ -409,9 +219,9 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath( } // retrieve packed paths - super::RetrievePackedPathFromHeap( + retrievePackedPathFromHeap( existing_forward_heap, new_reverse_heap, s_v_middle, packed_s_v_path); - super::RetrievePackedPathFromHeap( + retrievePackedPathFromHeap( new_forward_heap, existing_reverse_heap, v_t_middle, packed_v_t_path); // partial unpacking, compute sharing @@ -431,14 +241,14 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath( { if (packed_s_v_path[current_node] == packed_shortest_path[current_node]) { - super::UnpackEdge(facade, - packed_s_v_path[current_node], - packed_s_v_path[current_node + 1], - partially_unpacked_via_path); - super::UnpackEdge(facade, - packed_shortest_path[current_node], - packed_shortest_path[current_node + 1], - partially_unpacked_shortest_path); + unpackEdge(facade, + packed_s_v_path[current_node], + packed_s_v_path[current_node + 1], + partially_unpacked_via_path); + unpackEdge(facade, + packed_shortest_path[current_node], + packed_shortest_path[current_node + 1], + partially_unpacked_shortest_path); break; } } @@ -477,14 +287,14 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath( { if (packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index]) { - super::UnpackEdge(facade, - packed_v_t_path[via_path_index - 1], - packed_v_t_path[via_path_index], - partially_unpacked_via_path); - super::UnpackEdge(facade, - packed_shortest_path[shortest_path_index - 1], - packed_shortest_path[shortest_path_index], - partially_unpacked_shortest_path); + unpackEdge(facade, + packed_v_t_path[via_path_index - 1], + packed_v_t_path[via_path_index], + partially_unpacked_via_path); + unpackEdge(facade, + packed_shortest_path[shortest_path_index - 1], + packed_shortest_path[shortest_path_index], + partially_unpacked_shortest_path); break; } } @@ -514,8 +324,9 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath( } // conduct T-Test -bool AlternativeRouting::ViaNodeCandidatePassesTTest( - const FacadeT &facade, +bool viaNodeCandidatePassesTTest( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, QueryHeap &existing_forward_heap, QueryHeap &existing_reverse_heap, QueryHeap &new_forward_heap, @@ -525,7 +336,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( int *length_of_via_path, NodeID *s_v_middle, NodeID *v_t_middle, - const EdgeWeight min_edge_offset) const + const EdgeWeight min_edge_offset) { new_forward_heap.Clear(); new_reverse_heap.Clear(); @@ -540,16 +351,16 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( const bool constexpr DO_NOT_FORCE_LOOPS = false; while (new_reverse_heap.Size() > 0) { - super::RoutingStep(facade, - new_reverse_heap, - existing_forward_heap, - *s_v_middle, - upper_bound_s_v_path_length, - min_edge_offset, - false, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_reverse_heap, + existing_forward_heap, + *s_v_middle, + upper_bound_s_v_path_length, + min_edge_offset, + false, + STALLING_ENABLED, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length) @@ -563,16 +374,16 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( new_forward_heap.Insert(candidate.node, 0, candidate.node); while (new_forward_heap.Size() > 0) { - super::RoutingStep(facade, - new_forward_heap, - existing_reverse_heap, - *v_t_middle, - upper_bound_of_v_t_path_length, - min_edge_offset, - true, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + new_forward_heap, + existing_reverse_heap, + *v_t_middle, + upper_bound_of_v_t_path_length, + min_edge_offset, + true, + STALLING_ENABLED, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length) @@ -583,10 +394,10 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; // retrieve packed paths - super::RetrievePackedPathFromHeap( + retrievePackedPathFromHeap( existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path); - super::RetrievePackedPathFromHeap( + retrievePackedPathFromHeap( new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path); NodeID s_P = *s_v_middle, t_P = *v_t_middle; @@ -632,7 +443,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( return false; } - const EdgeData ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id); + const auto ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id); const bool current_edge_is_shortcut = current_edge_data.shortcut; if (current_edge_is_shortcut) { @@ -694,7 +505,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( return false; } - const EdgeData ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id); + const auto ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id); const bool IsViaEdgeShortCut = current_edge_data.shortcut; if (IsViaEdgeShortCut) { @@ -738,33 +549,346 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest( { if (!forward_heap3.Empty()) { - super::RoutingStep(facade, - forward_heap3, - reverse_heap3, - middle, - upper_bound, - min_edge_offset, - true, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + forward_heap3, + reverse_heap3, + middle, + upper_bound, + min_edge_offset, + true, + STALLING_ENABLED, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } if (!reverse_heap3.Empty()) { - super::RoutingStep(facade, - reverse_heap3, - forward_heap3, - middle, - upper_bound, - min_edge_offset, - false, - STALLING_ENABLED, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + routingStep(facade, + reverse_heap3, + forward_heap3, + middle, + upper_bound, + min_edge_offset, + false, + STALLING_ENABLED, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } } return (upper_bound <= t_test_path_length); } +} + +InternalRouteResult +alternativePathSearch(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const PhantomNodes &phantom_node_pair) +{ + InternalRouteResult raw_route_data; + std::vector alternative_path; + std::vector via_node_candidate_list; + std::vector forward_search_space; + std::vector reverse_search_space; + + // Init queues, semi-expensive because access to TSS invokes a sys-call + engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); + engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes()); + engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes()); + + QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1); + QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2); + QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2); + + EdgeWeight upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT; + NodeID middle_node = SPECIAL_NODEID; + const EdgeWeight min_edge_offset = + std::min(phantom_node_pair.source_phantom.forward_segment_id.enabled + ? -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset() + : 0, + phantom_node_pair.source_phantom.reverse_segment_id.enabled + ? -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset() + : 0); + + if (phantom_node_pair.source_phantom.forward_segment_id.enabled) + { + BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID); + forward_heap1.Insert(phantom_node_pair.source_phantom.forward_segment_id.id, + -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.forward_segment_id.id); + } + if (phantom_node_pair.source_phantom.reverse_segment_id.enabled) + { + BOOST_ASSERT(phantom_node_pair.source_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID); + forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_segment_id.id, + -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.source_phantom.reverse_segment_id.id); + } + + if (phantom_node_pair.target_phantom.forward_segment_id.enabled) + { + BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id != SPECIAL_SEGMENTID); + reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_segment_id.id, + phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.target_phantom.forward_segment_id.id); + } + if (phantom_node_pair.target_phantom.reverse_segment_id.enabled) + { + BOOST_ASSERT(phantom_node_pair.target_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID); + reverse_heap1.Insert(phantom_node_pair.target_phantom.reverse_segment_id.id, + phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.target_phantom.reverse_segment_id.id); + } + + // search from s and t till new_min/(1+epsilon) > length_of_shortest_path + while (0 < (forward_heap1.Size() + reverse_heap1.Size())) + { + if (0 < forward_heap1.Size()) + { + alternativeRoutingStep(facade, + forward_heap1, + reverse_heap1, + &middle_node, + &upper_bound_to_shortest_path_weight, + via_node_candidate_list, + forward_search_space, + min_edge_offset); + } + if (0 < reverse_heap1.Size()) + { + alternativeRoutingStep(facade, + forward_heap1, + reverse_heap1, + &middle_node, + &upper_bound_to_shortest_path_weight, + via_node_candidate_list, + reverse_search_space, + min_edge_offset); + } + } + + if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_weight) + { + return raw_route_data; + } + + std::sort(begin(via_node_candidate_list), end(via_node_candidate_list)); + auto unique_end = std::unique(begin(via_node_candidate_list), end(via_node_candidate_list)); + via_node_candidate_list.resize(unique_end - begin(via_node_candidate_list)); + + std::vector packed_forward_path; + std::vector packed_reverse_path; + + const bool path_is_a_loop = + upper_bound_to_shortest_path_weight != + forward_heap1.GetKey(middle_node) + reverse_heap1.GetKey(middle_node); + if (path_is_a_loop) + { + // Self Loop + packed_forward_path.push_back(middle_node); + packed_forward_path.push_back(middle_node); + } + else + { + + retrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path); + retrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path); + } + + // this set is is used as an indicator if a node is on the shortest path + std::unordered_set nodes_in_path(packed_forward_path.size() + + packed_reverse_path.size()); + nodes_in_path.insert(packed_forward_path.begin(), packed_forward_path.end()); + nodes_in_path.insert(middle_node); + nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end()); + + std::unordered_map approximated_forward_sharing; + std::unordered_map approximated_reverse_sharing; + + // sweep over search space, compute forward sharing for each current edge (u,v) + for (const SearchSpaceEdge ¤t_edge : forward_search_space) + { + const NodeID u = current_edge.first; + const NodeID v = current_edge.second; + + if (nodes_in_path.find(v) != nodes_in_path.end()) + { + // current_edge is on shortest path => sharing(v):=queue.GetKey(v); + approximated_forward_sharing.emplace(v, forward_heap1.GetKey(v)); + } + else + { + // current edge is not on shortest path. Check if we know a value for the other + // endpoint + const auto sharing_of_u_iterator = approximated_forward_sharing.find(u); + if (sharing_of_u_iterator != approximated_forward_sharing.end()) + { + approximated_forward_sharing.emplace(v, sharing_of_u_iterator->second); + } + } + } + + // sweep over search space, compute backward sharing + for (const SearchSpaceEdge ¤t_edge : reverse_search_space) + { + const NodeID u = current_edge.first; + const NodeID v = current_edge.second; + if (nodes_in_path.find(v) != nodes_in_path.end()) + { + // current_edge is on shortest path => sharing(u):=queue.GetKey(u); + approximated_reverse_sharing.emplace(v, reverse_heap1.GetKey(v)); + } + else + { + // current edge is not on shortest path. Check if we know a value for the other + // endpoint + const auto sharing_of_u_iterator = approximated_reverse_sharing.find(u); + if (sharing_of_u_iterator != approximated_reverse_sharing.end()) + { + approximated_reverse_sharing.emplace(v, sharing_of_u_iterator->second); + } + } + } + + std::vector preselected_node_list; + for (const NodeID node : via_node_candidate_list) + { + if (node == middle_node) + continue; + const auto fwd_iterator = approximated_forward_sharing.find(node); + const int fwd_sharing = + (fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0; + const auto rev_iterator = approximated_reverse_sharing.find(node); + const int rev_sharing = + (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0; + + const int approximated_sharing = fwd_sharing + rev_sharing; + const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node); + const bool length_passes = + (approximated_length < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON)); + const bool sharing_passes = + (approximated_sharing <= upper_bound_to_shortest_path_weight * VIAPATH_GAMMA); + const bool stretch_passes = + (approximated_length - approximated_sharing) < + ((1. + VIAPATH_ALPHA) * (upper_bound_to_shortest_path_weight - approximated_sharing)); + + if (length_passes && sharing_passes && stretch_passes) + { + preselected_node_list.emplace_back(node); + } + } + + std::vector &packed_shortest_path = packed_forward_path; + if (!path_is_a_loop) + { + std::reverse(packed_shortest_path.begin(), packed_shortest_path.end()); + packed_shortest_path.emplace_back(middle_node); + packed_shortest_path.insert( + packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end()); + } + std::vector ranked_candidates_list; + + // prioritizing via nodes for deep inspection + for (const NodeID node : preselected_node_list) + { + int length_of_via_path = 0, sharing_of_via_path = 0; + computeLengthAndSharingOfViaPath(engine_working_data, + facade, + node, + &length_of_via_path, + &sharing_of_via_path, + packed_shortest_path, + min_edge_offset); + const int maximum_allowed_sharing = + static_cast(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA); + if (sharing_of_via_path <= maximum_allowed_sharing && + length_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON)) + { + ranked_candidates_list.emplace_back(node, length_of_via_path, sharing_of_via_path); + } + } + std::sort(ranked_candidates_list.begin(), ranked_candidates_list.end()); + + NodeID selected_via_node = SPECIAL_NODEID; + int length_of_via_path = INVALID_EDGE_WEIGHT; + NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID; + for (const RankedCandidateNode &candidate : ranked_candidates_list) + { + if (viaNodeCandidatePassesTTest(engine_working_data, + facade, + forward_heap1, + reverse_heap1, + forward_heap2, + reverse_heap2, + candidate, + upper_bound_to_shortest_path_weight, + &length_of_via_path, + &s_v_middle, + &v_t_middle, + min_edge_offset)) + { + // select first admissable + selected_via_node = candidate.node; + break; + } + } + + // Unpack shortest path and alternative, if they exist + if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_weight) + { + BOOST_ASSERT(!packed_shortest_path.empty()); + raw_route_data.unpacked_path_segments.resize(1); + raw_route_data.source_traversed_in_reverse.push_back( + (packed_shortest_path.front() != + phantom_node_pair.source_phantom.forward_segment_id.id)); + raw_route_data.target_traversed_in_reverse.push_back(( + packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); + + unpackPath(facade, + // -- packed input + packed_shortest_path.begin(), + packed_shortest_path.end(), + // -- start of route + phantom_node_pair, + // -- unpacked output + raw_route_data.unpacked_path_segments.front()); + raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight; + } + + if (SPECIAL_NODEID != selected_via_node) + { + std::vector packed_alternate_path; + // retrieve alternate path + retrievePackedAlternatePath(forward_heap1, + reverse_heap1, + forward_heap2, + reverse_heap2, + s_v_middle, + v_t_middle, + packed_alternate_path); + + raw_route_data.alt_source_traversed_in_reverse.push_back( + (packed_alternate_path.front() != + phantom_node_pair.source_phantom.forward_segment_id.id)); + raw_route_data.alt_target_traversed_in_reverse.push_back( + (packed_alternate_path.back() != + phantom_node_pair.target_phantom.forward_segment_id.id)); + + // unpack the alternate path + unpackPath(facade, + packed_alternate_path.begin(), + packed_alternate_path.end(), + phantom_node_pair, + raw_route_data.unpacked_alternative); + + raw_route_data.alternative_path_length = length_of_via_path; + } + else + { + BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT); + } + + return raw_route_data; +} } // namespace routing_algorithms } // namespace engine diff --git a/src/engine/routing_algorithms/direct_shortest_path.cpp b/src/engine/routing_algorithms/direct_shortest_path.cpp index 9052367c8..5d0bfd072 100644 --- a/src/engine/routing_algorithms/direct_shortest_path.cpp +++ b/src/engine/routing_algorithms/direct_shortest_path.cpp @@ -1,5 +1,7 @@ #include "engine/routing_algorithms/direct_shortest_path.hpp" +#include "engine/routing_algorithms/routing_base.hpp" + namespace osrm { namespace engine @@ -13,11 +15,12 @@ namespace routing_algorithms /// by the previous route. /// This variation is only an optimazation for graphs with slow queries, for example /// not fully contracted graphs. -void DirectShortestPathRouting:: -operator()(const FacadeT &facade, - const std::vector &phantom_nodes_vector, - InternalRouteResult &raw_route_data) const +InternalRouteResult directShortestPathSearch( + SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector) { + 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. " @@ -27,8 +30,8 @@ operator()(const FacadeT &facade, const auto &target_phantom = phantom_node_pair.target_phantom; engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); - QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); - QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); + auto &forward_heap = *(engine_working_data.forward_heap_1); + auto &reverse_heap = *(engine_working_data.reverse_heap_1); forward_heap.Clear(); reverse_heap.Clear(); @@ -71,30 +74,30 @@ operator()(const FacadeT &facade, if (facade.GetCoreSize() > 0) { engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes()); - QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2); - QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2); + 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(); - super::SearchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - weight, - packed_leg, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + searchWithCore(facade, + forward_heap, + reverse_heap, + forward_core_heap, + reverse_core_heap, + weight, + packed_leg, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } else { - super::Search(facade, - forward_heap, - reverse_heap, - weight, - packed_leg, - DO_NOT_FORCE_LOOPS, - DO_NOT_FORCE_LOOPS); + search(facade, + forward_heap, + reverse_heap, + weight, + packed_leg, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS); } // No path found for both target nodes? @@ -102,7 +105,7 @@ operator()(const FacadeT &facade, { raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT; raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT; - return; + return raw_route_data; } BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty"); @@ -114,11 +117,13 @@ operator()(const FacadeT &facade, raw_route_data.target_traversed_in_reverse.push_back( (packed_leg.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); - super::UnpackPath(facade, - packed_leg.begin(), - packed_leg.end(), - phantom_node_pair, - raw_route_data.unpacked_path_segments.front()); + unpackPath(facade, + packed_leg.begin(), + packed_leg.end(), + phantom_node_pair, + raw_route_data.unpacked_path_segments.front()); + + return raw_route_data; } } // 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 149e88cfe..370cb50ef 100644 --- a/src/engine/routing_algorithms/many_to_many.cpp +++ b/src/engine/routing_algorithms/many_to_many.cpp @@ -1,4 +1,12 @@ #include "engine/routing_algorithms/many_to_many.hpp" +#include "engine/routing_algorithms/routing_base.hpp" + +#include + +#include +#include +#include +#include namespace osrm { @@ -7,11 +15,172 @@ namespace engine namespace routing_algorithms { -std::vector ManyToManyRouting:: -operator()(const FacadeT &facade, - const std::vector &phantom_nodes, - const std::vector &source_indices, - const std::vector &target_indices) const +using QueryHeap = SearchEngineData::ManyToManyQueryHeap; + +namespace +{ +struct NodeBucket +{ + unsigned target_id; // essentially a row in the weight matrix + EdgeWeight weight; + EdgeWeight duration; + NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration) + : target_id(target_id), weight(weight), duration(duration) + { + } +}; +// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking +using SearchSpaceWithBuckets = std::unordered_map>; + +template +void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const NodeID node, + const EdgeWeight weight, + const EdgeWeight duration, + QueryHeap &query_heap) +{ + for (auto edge : facade.GetAdjacentEdgeRange(node)) + { + const auto &data = facade.GetEdgeData(edge); + const bool direction_flag = (forward_direction ? data.forward : data.backward); + if (direction_flag) + { + const NodeID to = facade.GetTarget(edge); + const EdgeWeight edge_weight = data.weight; + const EdgeWeight edge_duration = data.duration; + + BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); + const EdgeWeight to_weight = weight + edge_weight; + const EdgeWeight to_duration = duration + edge_duration; + + // New Node discovered -> Add to Heap + Node Info Storage + if (!query_heap.WasInserted(to)) + { + query_heap.Insert(to, to_weight, {node, to_duration}); + } + // Found a shorter Path -> Update weight + else if (to_weight < query_heap.GetKey(to)) + { + // new parent + query_heap.GetData(to) = {node, to_duration}; + query_heap.DecreaseKey(to, to_weight); + } + } + } +} + +// Stalling +template +bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const NodeID node, + const EdgeWeight weight, + QueryHeap &query_heap) +{ + for (auto edge : facade.GetAdjacentEdgeRange(node)) + { + const auto &data = facade.GetEdgeData(edge); + const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward); + if (reverse_flag) + { + const NodeID to = facade.GetTarget(edge); + const EdgeWeight edge_weight = data.weight; + BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); + if (query_heap.WasInserted(to)) + { + if (query_heap.GetKey(to) + edge_weight < weight) + { + return true; + } + } + } + } + return false; +} + +void ForwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const unsigned row_idx, + const unsigned number_of_targets, + QueryHeap &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 = 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 + + getLoopWeight(facade, node)); + } + } + else if (new_weight < current_weight) + { + current_weight = new_weight; + current_duration = source_duration + target_duration; + } + } + } + if (stallAtNode(facade, node, source_weight, query_heap)) + { + return; + } + relaxOutgoingEdges(facade, node, source_weight, source_duration, query_heap); +} + +void backwardRoutingStep( + const datafacade::ContiguousInternalMemoryDataFacade &facade, + const unsigned column_idx, + QueryHeap &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 (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(); @@ -24,7 +193,7 @@ operator()(const FacadeT &facade, engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes()); - QueryHeap &query_heap = *(engine_working_data.many_to_many_heap); + auto &query_heap = *(engine_working_data.many_to_many_heap); SearchSpaceWithBuckets search_space_with_buckets; @@ -49,7 +218,7 @@ operator()(const FacadeT &facade, // explore search space while (!query_heap.Empty()) { - BackwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets); + backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets); } ++column_idx; }; @@ -122,84 +291,6 @@ operator()(const FacadeT &facade, return durations_table; } -void ManyToManyRouting::ForwardRoutingStep( - const FacadeT &facade, - const unsigned row_idx, - const unsigned number_of_targets, - QueryHeap &query_heap, - const SearchSpaceWithBuckets &search_space_with_buckets, - std::vector &weights_table, - std::vector &durations_table) const -{ - 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 = super::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 + - super::GetLoopWeight(facade, node)); - } - } - else if (new_weight < current_weight) - { - current_weight = new_weight; - current_duration = source_duration + target_duration; - } - } - } - if (StallAtNode(facade, node, source_weight, query_heap)) - { - return; - } - RelaxOutgoingEdges(facade, node, source_weight, source_duration, query_heap); -} - -void ManyToManyRouting::BackwardRoutingStep( - const FacadeT &facade, - const unsigned column_idx, - QueryHeap &query_heap, - SearchSpaceWithBuckets &search_space_with_buckets) const -{ - 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 (StallAtNode(facade, node, target_weight, query_heap)) - { - return; - } - - RelaxOutgoingEdges(facade, node, target_weight, target_duration, query_heap); -} - } // 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 b19200eb8..4fde68304 100644 --- a/src/engine/routing_algorithms/map_matching.cpp +++ b/src/engine/routing_algorithms/map_matching.cpp @@ -1,4 +1,20 @@ #include "engine/routing_algorithms/map_matching.hpp" +#include "engine/routing_algorithms/routing_base.hpp" + +#include "engine/map_matching/hidden_markov_model.hpp" +#include "engine/map_matching/matching_confidence.hpp" +#include "engine/map_matching/sub_matching.hpp" + +#include "util/coordinate_calculation.hpp" +#include "util/for_each_pair.hpp" + +#include +#include +#include +#include +#include +#include +#include namespace osrm { @@ -7,8 +23,15 @@ namespace engine namespace routing_algorithms { -unsigned -MapMatching::GetMedianSampleTime(const std::vector ×tamps) const +namespace +{ +using HMM = map_matching::HiddenMarkovModel; + +constexpr static const unsigned MAX_BROKEN_STATES = 10; +constexpr static const double MATCHING_BETA = 10; +constexpr static const double MAX_DISTANCE_DELTA = 2000.; + +unsigned getMedianSampleTime(const std::vector ×tamps) { BOOST_ASSERT(timestamps.size() > 1); @@ -22,14 +45,20 @@ MapMatching::GetMedianSampleTime(const std::vector &tim std::nth_element(first_elem, median, sample_times.end()); return *median; } +} -SubMatchingList MapMatching:: -operator()(const FacadeT &facade, - const CandidateLists &candidates_list, - const std::vector &trace_coordinates, - const std::vector &trace_timestamps, - const std::vector> &trace_gps_precision) const +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) { + map_matching::MatchingConfidence confidence; + map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION); + map_matching::TransitionLogProbability transition_log_probability(MATCHING_BETA); + SubMatchingList sub_matchings; BOOST_ASSERT(candidates_list.size() == trace_coordinates.size()); @@ -40,7 +69,7 @@ operator()(const FacadeT &facade, const auto median_sample_time = [&] { if (use_timestamps) { - return std::max(1u, GetMedianSampleTime(trace_timestamps)); + return std::max(1u, getMedianSampleTime(trace_timestamps)); } else { @@ -68,7 +97,7 @@ operator()(const FacadeT &facade, std::transform(candidates_list[t].begin(), candidates_list[t].end(), emission_log_probabilities[t].begin(), - [this](const PhantomNodeWithDistance &candidate) { + [&](const PhantomNodeWithDistance &candidate) { return default_emission_log_probability(candidate.distance); }); } @@ -95,7 +124,7 @@ operator()(const FacadeT &facade, std::transform(candidates_list[t].begin(), candidates_list[t].end(), emission_log_probabilities[t].begin(), - [this](const PhantomNodeWithDistance &candidate) { + [&](const PhantomNodeWithDistance &candidate) { return default_emission_log_probability(candidate.distance); }); } @@ -113,10 +142,10 @@ operator()(const FacadeT &facade, engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); engine_working_data.InitializeOrClearSecondThreadLocalStorage(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); + 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); std::size_t breakage_begin = map_matching::INVALID_STATE; std::vector split_points; @@ -187,7 +216,7 @@ operator()(const FacadeT &facade, { forward_core_heap.Clear(); reverse_core_heap.Clear(); - network_distance = super::GetNetworkDistanceWithCore( + network_distance = getNetworkDistanceWithCore( facade, forward_heap, reverse_heap, @@ -199,12 +228,12 @@ operator()(const FacadeT &facade, } else { - network_distance = super::GetNetworkDistance( - facade, - forward_heap, - reverse_heap, - prev_unbroken_timestamps_list[s].phantom_node, - current_timestamps_list[s_prime].phantom_node); + network_distance = + getNetworkDistance(facade, + forward_heap, + reverse_heap, + prev_unbroken_timestamps_list[s].phantom_node, + current_timestamps_list[s_prime].phantom_node); } // get distance diff between loc1/2 and locs/s_prime diff --git a/src/engine/routing_algorithms/routing_base.cpp b/src/engine/routing_algorithms/routing_base.cpp index 354471fa4..7cff2f8aa 100644 --- a/src/engine/routing_algorithms/routing_base.cpp +++ b/src/engine/routing_algorithms/routing_base.cpp @@ -7,16 +7,16 @@ namespace engine namespace routing_algorithms { -void BasicRouting::RoutingStep(const FacadeT &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - NodeID &middle_node_id, - EdgeWeight &upper_bound, - EdgeWeight min_edge_offset, - const bool forward_direction, - const bool stalling, - const bool force_loop_forward, - const bool force_loop_reverse) const +void routingStep(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + NodeID &middle_node_id, + EdgeWeight &upper_bound, + EdgeWeight min_edge_offset, + const bool forward_direction, + const bool stalling, + const bool force_loop_forward, + const bool force_loop_reverse) { const NodeID node = forward_heap.DeleteMin(); const EdgeWeight weight = forward_heap.GetKey(node); @@ -36,7 +36,7 @@ void BasicRouting::RoutingStep(const FacadeT &facade, // check whether there is a loop present at the node for (const auto edge : facade.GetAdjacentEdgeRange(node)) { - const EdgeData &data = facade.GetEdgeData(edge); + const auto &data = facade.GetEdgeData(edge); bool forward_directionFlag = (forward_direction ? data.forward : data.backward); if (forward_directionFlag) { @@ -78,7 +78,7 @@ void BasicRouting::RoutingStep(const FacadeT &facade, { for (const auto edge : facade.GetAdjacentEdgeRange(node)) { - const EdgeData &data = facade.GetEdgeData(edge); + const auto &data = facade.GetEdgeData(edge); const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward); if (reverse_flag) { @@ -100,7 +100,7 @@ void BasicRouting::RoutingStep(const FacadeT &facade, for (const auto edge : facade.GetAdjacentEdgeRange(node)) { - const EdgeData &data = facade.GetEdgeData(edge); + const auto &data = facade.GetEdgeData(edge); bool forward_directionFlag = (forward_direction ? data.forward : data.backward); if (forward_directionFlag) { @@ -133,38 +133,35 @@ void BasicRouting::RoutingStep(const FacadeT &facade, * @param to the node the CH edge finishes at * @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge */ -void BasicRouting::UnpackEdge(const FacadeT &facade, - const NodeID from, - const NodeID to, - std::vector &unpacked_path) const +void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const NodeID from, + const NodeID to, + std::vector &unpacked_path) { std::array path{{from, to}}; - UnpackCHPath( - facade, - path.begin(), - path.end(), - [&unpacked_path](const std::pair &edge, const EdgeData & /* data */) { - unpacked_path.emplace_back(edge.first); - }); + unpackPath(facade, + path.begin(), + path.end(), + [&unpacked_path](const std::pair &edge, const auto & /* data */) { + unpacked_path.emplace_back(edge.first); + }); unpacked_path.emplace_back(to); } -void BasicRouting::RetrievePackedPathFromHeap( - const SearchEngineData::QueryHeap &forward_heap, - const SearchEngineData::QueryHeap &reverse_heap, - const NodeID middle_node_id, - std::vector &packed_path) const +void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, + const SearchEngineData::QueryHeap &reverse_heap, + const NodeID middle_node_id, + std::vector &packed_path) { - RetrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path); + retrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path); std::reverse(packed_path.begin(), packed_path.end()); packed_path.emplace_back(middle_node_id); - RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path); + retrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path); } -void BasicRouting::RetrievePackedPathFromSingleHeap( - const SearchEngineData::QueryHeap &search_heap, - const NodeID middle_node_id, - std::vector &packed_path) const +void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, + const NodeID middle_node_id, + std::vector &packed_path) { NodeID current_node_id = middle_node_id; // all initial nodes will have itself as parent, or a node not in the heap @@ -191,14 +188,14 @@ void BasicRouting::RetrievePackedPathFromSingleHeap( // && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) // requires // a force loop, if the heaps have been initialized with positive offsets. -void BasicRouting::Search(const FacadeT &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - EdgeWeight &weight, - std::vector &packed_leg, - const bool force_loop_forward, - const bool force_loop_reverse, - const EdgeWeight weight_upper_bound) const +void search(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + EdgeWeight &weight, + std::vector &packed_leg, + const bool force_loop_forward, + const bool force_loop_reverse, + const EdgeWeight weight_upper_bound) { NodeID middle = SPECIAL_NODEID; weight = weight_upper_bound; @@ -215,7 +212,7 @@ void BasicRouting::Search(const FacadeT &facade, { if (!forward_heap.Empty()) { - RoutingStep(facade, + routingStep(facade, forward_heap, reverse_heap, middle, @@ -228,7 +225,7 @@ void BasicRouting::Search(const FacadeT &facade, } if (!reverse_heap.Empty()) { - RoutingStep(facade, + routingStep(facade, reverse_heap, forward_heap, middle, @@ -260,7 +257,7 @@ void BasicRouting::Search(const FacadeT &facade, } else { - RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); + retrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); } } @@ -273,16 +270,16 @@ void BasicRouting::Search(const FacadeT &facade, // && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset()) // requires // a force loop, if the heaps have been initialized with positive offsets. -void BasicRouting::SearchWithCore(const FacadeT &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) const +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) { NodeID middle = SPECIAL_NODEID; weight = weight_upper_bound; @@ -310,7 +307,7 @@ void BasicRouting::SearchWithCore(const FacadeT &facade, } else { - RoutingStep(facade, + routingStep(facade, forward_heap, reverse_heap, middle, @@ -332,7 +329,7 @@ void BasicRouting::SearchWithCore(const FacadeT &facade, } else { - RoutingStep(facade, + routingStep(facade, reverse_heap, forward_heap, middle, @@ -385,7 +382,7 @@ void BasicRouting::SearchWithCore(const FacadeT &facade, while (0 < forward_core_heap.Size() && 0 < reverse_core_heap.Size() && weight > (forward_core_heap.MinKey() + reverse_core_heap.MinKey())) { - RoutingStep(facade, + routingStep(facade, forward_core_heap, reverse_core_heap, middle, @@ -396,7 +393,7 @@ void BasicRouting::SearchWithCore(const FacadeT &facade, force_loop_forward, force_loop_reverse); - RoutingStep(facade, + routingStep(facade, reverse_core_heap, forward_core_heap, middle, @@ -432,13 +429,13 @@ void BasicRouting::SearchWithCore(const FacadeT &facade, else { std::vector packed_core_leg; - RetrievePackedPathFromHeap( + 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); + 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); + retrievePackedPathFromSingleHeap(reverse_heap, packed_core_leg.back(), packed_leg); } } else @@ -453,13 +450,12 @@ void BasicRouting::SearchWithCore(const FacadeT &facade, } else { - RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); + retrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg); } } } -bool BasicRouting::NeedsLoopForward(const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const +bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom) { return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled && source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id && @@ -467,8 +463,7 @@ bool BasicRouting::NeedsLoopForward(const PhantomNode &source_pha target_phantom.GetForwardWeightPlusOffset(); } -bool BasicRouting::NeedsLoopBackwards(const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const +bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom) { return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled && source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id && @@ -476,16 +471,16 @@ bool BasicRouting::NeedsLoopBackwards(const PhantomNode &source_p target_phantom.GetReverseWeightPlusOffset(); } -double BasicRouting::GetPathDistance(const FacadeT &facade, - const std::vector &packed_path, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom) const +double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &packed_path, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom) { std::vector unpacked_path; PhantomNodes nodes; nodes.source_phantom = source_phantom; nodes.target_phantom = target_phantom; - UnpackPath(facade, packed_path.begin(), packed_path.end(), nodes, unpacked_path); + unpackPath(facade, packed_path.begin(), packed_path.end(), nodes, unpacked_path); using util::coordinate_calculation::detail::DEGREE_TO_RAD; using util::coordinate_calculation::detail::EARTH_RADIUS; @@ -535,15 +530,15 @@ double BasicRouting::GetPathDistance(const FacadeT &facade, // Requires the heaps for be empty // If heaps should be adjusted to be initialized outside of this function, // the addition of force_loop parameters might be required -double BasicRouting::GetNetworkDistanceWithCore( - const FacadeT &facade, +double getNetworkDistanceWithCore( + 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) const + EdgeWeight weight_upper_bound) { BOOST_ASSERT(forward_heap.Empty()); BOOST_ASSERT(reverse_heap.Empty()); @@ -579,7 +574,7 @@ double BasicRouting::GetNetworkDistanceWithCore( EdgeWeight weight = INVALID_EDGE_WEIGHT; std::vector packed_path; - SearchWithCore(facade, + searchWithCore(facade, forward_heap, reverse_heap, forward_core_heap, @@ -593,7 +588,7 @@ double BasicRouting::GetNetworkDistanceWithCore( double distance = std::numeric_limits::max(); if (weight != INVALID_EDGE_WEIGHT) { - return GetPathDistance(facade, packed_path, source_phantom, target_phantom); + return getPathDistance(facade, packed_path, source_phantom, target_phantom); } return distance; } @@ -601,12 +596,13 @@ double BasicRouting::GetNetworkDistanceWithCore( // Requires the heaps for be empty // If heaps should be adjusted to be initialized outside of this function, // the addition of force_loop parameters might be required -double BasicRouting::GetNetworkDistance(const FacadeT &facade, - SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom, - EdgeWeight weight_upper_bound) const +double +getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade &facade, + SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + EdgeWeight weight_upper_bound) { BOOST_ASSERT(forward_heap.Empty()); BOOST_ASSERT(reverse_heap.Empty()); @@ -642,7 +638,7 @@ double BasicRouting::GetNetworkDistance(const FacadeT &facade, EdgeWeight weight = INVALID_EDGE_WEIGHT; std::vector packed_path; - Search(facade, + search(facade, forward_heap, reverse_heap, weight, @@ -656,7 +652,7 @@ double BasicRouting::GetNetworkDistance(const FacadeT &facade, return std::numeric_limits::max(); } - return GetPathDistance(facade, packed_path, source_phantom, target_phantom); + return getPathDistance(facade, packed_path, source_phantom, target_phantom); } } // namespace routing_algorithms diff --git a/src/engine/routing_algorithms/shortest_path.cpp b/src/engine/routing_algorithms/shortest_path.cpp index 167276221..31544e677 100644 --- a/src/engine/routing_algorithms/shortest_path.cpp +++ b/src/engine/routing_algorithms/shortest_path.cpp @@ -1,4 +1,9 @@ #include "engine/routing_algorithms/shortest_path.hpp" +#include "engine/routing_algorithms/routing_base.hpp" + +#include +#include +#include namespace osrm { @@ -7,23 +12,26 @@ namespace engine namespace routing_algorithms { +const static constexpr bool DO_NOT_FORCE_LOOP = false; +using QueryHeap = SearchEngineData::QueryHeap; + // allows a uturn at the target_phantom // searches source forward/reverse -> target forward/reverse -void ShortestPathRouting::SearchWithUTurn(const FacadeT &facade, - QueryHeap &forward_heap, - QueryHeap &reverse_heap, - QueryHeap &forward_core_heap, - QueryHeap &reverse_core_heap, - const bool search_from_forward_node, - const bool search_from_reverse_node, - const bool search_to_forward_node, - const bool search_to_reverse_node, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom, - const int total_weight_to_forward, - const int total_weight_to_reverse, - int &new_total_weight, - std::vector &leg_packed_path) const +void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade &facade, + QueryHeap &forward_heap, + QueryHeap &reverse_heap, + QueryHeap &forward_core_heap, + QueryHeap &reverse_core_heap, + const bool search_from_forward_node, + const bool search_from_reverse_node, + const bool search_to_forward_node, + const bool search_to_reverse_node, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + const int total_weight_to_forward, + const int total_weight_to_reverse, + int &new_total_weight, + std::vector &leg_packed_path) { forward_heap.Clear(); reverse_heap.Clear(); @@ -59,35 +67,34 @@ void ShortestPathRouting::SearchWithUTurn(const FacadeT &facade, auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node); auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node); // we only enable loops here if we can't search from forward to backward node - auto needs_loop_forwad = - is_oneway_source && super::NeedsLoopForward(source_phantom, target_phantom); + auto needs_loop_forwad = is_oneway_source && needsLoopForward(source_phantom, target_phantom); auto needs_loop_backwards = - is_oneway_target && super::NeedsLoopBackwards(source_phantom, target_phantom); + is_oneway_target && needsLoopBackwards(source_phantom, target_phantom); 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); - super::SearchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - new_total_weight, - leg_packed_path, - needs_loop_forwad, - needs_loop_backwards); + 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 { - super::Search(facade, - forward_heap, - reverse_heap, - new_total_weight, - leg_packed_path, - needs_loop_forwad, - needs_loop_backwards); + search(facade, + forward_heap, + reverse_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 @@ -99,23 +106,23 @@ void ShortestPathRouting::SearchWithUTurn(const FacadeT &facade, // searches shortest path between: // source forward/reverse -> target forward // source forward/reverse -> target reverse -void ShortestPathRouting::Search(const FacadeT &facade, - QueryHeap &forward_heap, - QueryHeap &reverse_heap, - QueryHeap &forward_core_heap, - QueryHeap &reverse_core_heap, - const bool search_from_forward_node, - const bool search_from_reverse_node, - const bool search_to_forward_node, - const bool search_to_reverse_node, - const PhantomNode &source_phantom, - const PhantomNode &target_phantom, - const int total_weight_to_forward, - const int total_weight_to_reverse, - int &new_total_weight_to_forward, - int &new_total_weight_to_reverse, - std::vector &leg_packed_path_forward, - std::vector &leg_packed_path_reverse) const +void Search(const datafacade::ContiguousInternalMemoryDataFacade &facade, + QueryHeap &forward_heap, + QueryHeap &reverse_heap, + QueryHeap &forward_core_heap, + QueryHeap &reverse_core_heap, + const bool search_from_forward_node, + const bool search_from_reverse_node, + const bool search_to_forward_node, + const bool search_to_reverse_node, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom, + const int total_weight_to_forward, + const int total_weight_to_reverse, + int &new_total_weight_to_forward, + int &new_total_weight_to_reverse, + std::vector &leg_packed_path_forward, + std::vector &leg_packed_path_reverse) { if (search_to_forward_node) { @@ -148,25 +155,25 @@ void ShortestPathRouting::Search(const FacadeT &facade, reverse_core_heap.Clear(); BOOST_ASSERT(forward_core_heap.Size() == 0); BOOST_ASSERT(reverse_core_heap.Size() == 0); - super::SearchWithCore(facade, - forward_heap, - reverse_heap, - forward_core_heap, - reverse_core_heap, - new_total_weight_to_forward, - leg_packed_path_forward, - super::NeedsLoopForward(source_phantom, target_phantom), - DO_NOT_FORCE_LOOP); + 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 { - super::Search(facade, - forward_heap, - reverse_heap, - new_total_weight_to_forward, - leg_packed_path_forward, - super::NeedsLoopForward(source_phantom, target_phantom), - DO_NOT_FORCE_LOOP); + search(facade, + forward_heap, + reverse_heap, + new_total_weight_to_forward, + leg_packed_path_forward, + needsLoopForward(source_phantom, target_phantom), + DO_NOT_FORCE_LOOP); } } @@ -199,36 +206,35 @@ void ShortestPathRouting::Search(const FacadeT &facade, reverse_core_heap.Clear(); BOOST_ASSERT(forward_core_heap.Size() == 0); BOOST_ASSERT(reverse_core_heap.Size() == 0); - super::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, - super::NeedsLoopBackwards(source_phantom, target_phantom)); + 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 { - super::Search(facade, - forward_heap, - reverse_heap, - new_total_weight_to_reverse, - leg_packed_path_reverse, - DO_NOT_FORCE_LOOP, - super::NeedsLoopBackwards(source_phantom, target_phantom)); + search(facade, + forward_heap, + reverse_heap, + new_total_weight_to_reverse, + leg_packed_path_reverse, + DO_NOT_FORCE_LOOP, + needsLoopBackwards(source_phantom, target_phantom)); } } } -void ShortestPathRouting::UnpackLegs( - const FacadeT &facade, - const std::vector &phantom_nodes_vector, - const std::vector &total_packed_path, - const std::vector &packed_leg_begin, - const int shortest_path_length, - InternalRouteResult &raw_route_data) const +void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &phantom_nodes_vector, + const std::vector &total_packed_path, + const std::vector &packed_leg_begin, + const int shortest_path_length, + InternalRouteResult &raw_route_data) { raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1); @@ -239,11 +245,11 @@ void ShortestPathRouting::UnpackLegs( auto leg_begin = total_packed_path.begin() + packed_leg_begin[current_leg]; auto leg_end = total_packed_path.begin() + packed_leg_begin[current_leg + 1]; const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg]; - super::UnpackPath(facade, - leg_begin, - leg_end, - unpack_phantom_node_pair, - raw_route_data.unpacked_path_segments[current_leg]); + unpackPath(facade, + leg_begin, + leg_end, + unpack_phantom_node_pair, + raw_route_data.unpacked_path_segments[current_leg]); raw_route_data.source_traversed_in_reverse.push_back( (*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id)); @@ -253,12 +259,13 @@ void ShortestPathRouting::UnpackLegs( } } -void ShortestPathRouting:: -operator()(const FacadeT &facade, - const std::vector &phantom_nodes_vector, - const boost::optional continue_straight_at_waypoint, - InternalRouteResult &raw_route_data) const +InternalRouteResult +shortestPathSearch(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 = !(continue_straight_at_waypoint ? *continue_straight_at_waypoint : facade.GetContinueStraightDefault()); @@ -312,7 +319,7 @@ operator()(const FacadeT &facade, { if (allow_uturn_at_waypoint) { - SearchWithUTurn(facade, + searchWithUTurn(facade, forward_heap, reverse_heap, forward_core_heap, @@ -370,7 +377,7 @@ operator()(const FacadeT &facade, { raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT; raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT; - return; + return raw_route_data; } // we need to figure out how the new legs connect to the previous ones @@ -473,7 +480,7 @@ operator()(const FacadeT &facade, packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size()); BOOST_ASSERT(packed_leg_to_reverse_begin.size() == phantom_nodes_vector.size() + 1); - UnpackLegs(facade, + unpackLegs(facade, phantom_nodes_vector, total_packed_path_to_reverse, packed_leg_to_reverse_begin, @@ -486,13 +493,15 @@ operator()(const FacadeT &facade, packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size()); BOOST_ASSERT(packed_leg_to_forward_begin.size() == phantom_nodes_vector.size() + 1); - UnpackLegs(facade, + unpackLegs(facade, phantom_nodes_vector, total_packed_path_to_forward, packed_leg_to_forward_begin, total_weight_to_forward, raw_route_data); } + + return raw_route_data; } } // namespace routing_algorithms diff --git a/src/engine/routing_algorithms/tile_turns.cpp b/src/engine/routing_algorithms/tile_turns.cpp index e6a2e4b13..6449dcd96 100644 --- a/src/engine/routing_algorithms/tile_turns.cpp +++ b/src/engine/routing_algorithms/tile_turns.cpp @@ -7,10 +7,10 @@ namespace engine namespace routing_algorithms { -std::vector TileTurns:: -operator()(const FacadeT &facade, - const std::vector &edges, - const std::vector &sorted_edge_indexes) const +std::vector +getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade &facade, + const std::vector &edges, + const std::vector &sorted_edge_indexes) { std::vector all_turn_data;