Split routing_base into CH and non-CH parts
This commit is contained in:
		
							parent
							
								
									43a7e8e08a
								
							
						
					
					
						commit
						6829f46c31
					
				@ -1,5 +1,5 @@
 | 
				
			|||||||
#ifndef ROUTING_BASE_HPP
 | 
					#ifndef OSRM_ENGINE_ROUTING_BASE_HPP
 | 
				
			||||||
#define ROUTING_BASE_HPP
 | 
					#define OSRM_ENGINE_ROUTING_BASE_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "extractor/guidance/turn_instruction.hpp"
 | 
					#include "extractor/guidance/turn_instruction.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -35,381 +35,150 @@ namespace routing_algorithms
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
static constexpr bool FORWARD_DIRECTION = true;
 | 
					static constexpr bool FORWARD_DIRECTION = true;
 | 
				
			||||||
static constexpr bool REVERSE_DIRECTION = false;
 | 
					static constexpr bool REVERSE_DIRECTION = false;
 | 
				
			||||||
 | 
					static constexpr bool DO_NOT_FORCE_LOOPS = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Stalling
 | 
					template <bool DIRECTION, typename Heap>
 | 
				
			||||||
template <bool DIRECTION, typename HeapT>
 | 
					void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
 | 
				
			||||||
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                 const NodeID node,
 | 
					 | 
				
			||||||
                 const EdgeWeight weight,
 | 
					 | 
				
			||||||
                 const HeapT &query_heap)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (auto edge : facade.GetAdjacentEdgeRange(node))
 | 
					    BOOST_ASSERT(phantom_node.IsValid());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
 | 
				
			||||||
 | 
					    if (phantom_node.forward_segment_id.enabled)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const auto &data = facade.GetEdgeData(edge);
 | 
					        heap.Insert(phantom_node.forward_segment_id.id,
 | 
				
			||||||
        if (DIRECTION == REVERSE_DIRECTION ? data.forward : data.backward)
 | 
					                    weight_sign * phantom_node.GetForwardWeightPlusOffset(),
 | 
				
			||||||
        {
 | 
					                    phantom_node.forward_segment_id.id);
 | 
				
			||||||
            const NodeID to = facade.GetTarget(edge);
 | 
					    }
 | 
				
			||||||
            const EdgeWeight edge_weight = data.weight;
 | 
					    if (phantom_node.reverse_segment_id.enabled)
 | 
				
			||||||
            BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
 | 
					    {
 | 
				
			||||||
            if (query_heap.WasInserted(to))
 | 
					        heap.Insert(phantom_node.reverse_segment_id.id,
 | 
				
			||||||
            {
 | 
					                    weight_sign * phantom_node.GetReverseWeightPlusOffset(),
 | 
				
			||||||
                if (query_heap.GetKey(to) + edge_weight < weight)
 | 
					                    phantom_node.reverse_segment_id.id);
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    return true;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <bool DIRECTION>
 | 
					template <bool DIRECTION>
 | 
				
			||||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					void insertNodesInHeap(SearchEngineData::ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
 | 
				
			||||||
                        const NodeID node,
 | 
					 | 
				
			||||||
                        const EdgeWeight weight,
 | 
					 | 
				
			||||||
                        SearchEngineData::QueryHeap &heap)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (const auto edge : facade.GetAdjacentEdgeRange(node))
 | 
					    BOOST_ASSERT(phantom_node.IsValid());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
 | 
				
			||||||
 | 
					    if (phantom_node.forward_segment_id.enabled)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const auto &data = facade.GetEdgeData(edge);
 | 
					        heap.Insert(
 | 
				
			||||||
        if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
 | 
					            phantom_node.forward_segment_id.id,
 | 
				
			||||||
        {
 | 
					            weight_sign * phantom_node.GetForwardWeightPlusOffset(),
 | 
				
			||||||
            const NodeID to = facade.GetTarget(edge);
 | 
					            {phantom_node.forward_segment_id.id, weight_sign * phantom_node.GetForwardDuration()});
 | 
				
			||||||
            const EdgeWeight edge_weight = data.weight;
 | 
					    }
 | 
				
			||||||
 | 
					    if (phantom_node.reverse_segment_id.enabled)
 | 
				
			||||||
            BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
 | 
					    {
 | 
				
			||||||
            const EdgeWeight to_weight = weight + edge_weight;
 | 
					        heap.Insert(
 | 
				
			||||||
 | 
					            phantom_node.reverse_segment_id.id,
 | 
				
			||||||
            // New Node discovered -> Add to Heap + Node Info Storage
 | 
					            weight_sign * phantom_node.GetReverseWeightPlusOffset(),
 | 
				
			||||||
            if (!heap.WasInserted(to))
 | 
					            {phantom_node.reverse_segment_id.id, weight_sign * phantom_node.GetReverseDuration()});
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                heap.Insert(to, to_weight, node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // Found a shorter Path -> Update weight
 | 
					 | 
				
			||||||
            else if (to_weight < heap.GetKey(to))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // new parent
 | 
					 | 
				
			||||||
                heap.GetData(to).parent = node;
 | 
					 | 
				
			||||||
                heap.DecreaseKey(to, to_weight);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					template <typename Heap>
 | 
				
			||||||
min_edge_offset is needed in case we use multiple
 | 
					void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
 | 
				
			||||||
nodes as start/target nodes with different (even negative) offsets.
 | 
					 | 
				
			||||||
In that case the termination criterion is not correct
 | 
					 | 
				
			||||||
anymore.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example:
 | 
					 | 
				
			||||||
forward heap: a(-100), b(0),
 | 
					 | 
				
			||||||
reverse heap: c(0), d(100)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
a --- d
 | 
					 | 
				
			||||||
  \ /
 | 
					 | 
				
			||||||
  / \
 | 
					 | 
				
			||||||
b --- c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This is equivalent to running a bi-directional Dijkstra on the following graph:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
static constexpr bool ENABLE_STALLING = true;
 | 
					 | 
				
			||||||
static constexpr bool DISABLE_STALLING = false;
 | 
					 | 
				
			||||||
static constexpr bool DO_NOT_FORCE_LOOPS = false;
 | 
					 | 
				
			||||||
template <bool DIRECTION, bool STALLING = ENABLE_STALLING>
 | 
					 | 
				
			||||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                 SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
                 SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
                 NodeID &middle_node_id,
 | 
					 | 
				
			||||||
                 EdgeWeight &upper_bound,
 | 
					 | 
				
			||||||
                 EdgeWeight min_edge_offset,
 | 
					 | 
				
			||||||
                 const bool force_loop_forward,
 | 
					 | 
				
			||||||
                 const bool force_loop_reverse)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const NodeID node = forward_heap.DeleteMin();
 | 
					    insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
 | 
				
			||||||
    const EdgeWeight weight = forward_heap.GetKey(node);
 | 
					    insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (reverse_heap.WasInserted(node))
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
 | 
					 | 
				
			||||||
        if (new_weight < upper_bound)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // if loops are forced, they are so at the source
 | 
					 | 
				
			||||||
            if ((force_loop_forward && forward_heap.GetData(node).parent == node) ||
 | 
					 | 
				
			||||||
                (force_loop_reverse && reverse_heap.GetData(node).parent == node) ||
 | 
					 | 
				
			||||||
                // in this case we are looking at a bi-directional way where the source
 | 
					 | 
				
			||||||
                // and target phantom are on the same edge based node
 | 
					 | 
				
			||||||
                new_weight < 0)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // check whether there is a loop present at the node
 | 
					 | 
				
			||||||
                for (const auto edge : facade.GetAdjacentEdgeRange(node))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    const auto &data = facade.GetEdgeData(edge);
 | 
					 | 
				
			||||||
                    if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        const NodeID to = facade.GetTarget(edge);
 | 
					 | 
				
			||||||
                        if (to == node)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            const EdgeWeight edge_weight = data.weight;
 | 
					 | 
				
			||||||
                            const EdgeWeight loop_weight = new_weight + edge_weight;
 | 
					 | 
				
			||||||
                            if (loop_weight >= 0 && loop_weight < upper_bound)
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                middle_node_id = node;
 | 
					 | 
				
			||||||
                                upper_bound = loop_weight;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                BOOST_ASSERT(new_weight >= 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                middle_node_id = node;
 | 
					 | 
				
			||||||
                upper_bound = new_weight;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // make sure we don't terminate too early if we initialize the weight
 | 
					 | 
				
			||||||
    // for the nodes in the forward heap with the forward/reverse offset
 | 
					 | 
				
			||||||
    BOOST_ASSERT(min_edge_offset <= 0);
 | 
					 | 
				
			||||||
    if (weight + min_edge_offset > upper_bound)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        forward_heap.DeleteAll();
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Stalling
 | 
					 | 
				
			||||||
    if (STALLING && stallAtNode<DIRECTION>(facade, node, weight, forward_heap))
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    relaxOutgoingEdges<DIRECTION>(facade, node, weight, forward_heap);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <bool UseDuration>
 | 
					template <typename FacadeT>
 | 
				
			||||||
EdgeWeight
 | 
					void annotatePath(const FacadeT &facade,
 | 
				
			||||||
getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					                  const NodeID source_node,
 | 
				
			||||||
              NodeID node)
 | 
					                  const NodeID target_node,
 | 
				
			||||||
 | 
					                  const std::vector<EdgeID> &unpacked_edges,
 | 
				
			||||||
 | 
					                  const PhantomNodes &phantom_node_pair,
 | 
				
			||||||
 | 
					                  std::vector<PathData> &unpacked_path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
 | 
					    BOOST_ASSERT(source_node != SPECIAL_NODEID && target_node != SPECIAL_NODEID);
 | 
				
			||||||
    for (auto edge : facade.GetAdjacentEdgeRange(node))
 | 
					    BOOST_ASSERT(!unpacked_edges.empty() || source_node == target_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const bool start_traversed_in_reverse =
 | 
				
			||||||
 | 
					        phantom_node_pair.source_phantom.forward_segment_id.id != source_node;
 | 
				
			||||||
 | 
					    const bool target_traversed_in_reverse =
 | 
				
			||||||
 | 
					        phantom_node_pair.target_phantom.forward_segment_id.id != target_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id == source_node ||
 | 
				
			||||||
 | 
					                 phantom_node_pair.source_phantom.reverse_segment_id.id == source_node);
 | 
				
			||||||
 | 
					    BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node ||
 | 
				
			||||||
 | 
					                 phantom_node_pair.target_phantom.reverse_segment_id.id == target_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (auto edge_id : unpacked_edges)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const auto &data = facade.GetEdgeData(edge);
 | 
					        const auto &edge_data = facade.GetEdgeData(edge_id);
 | 
				
			||||||
        if (data.forward)
 | 
					        const auto turn_id = edge_data.turn_id; // edge-based node ID
 | 
				
			||||||
 | 
					        const auto name_index = facade.GetNameIndexFromEdgeID(turn_id);
 | 
				
			||||||
 | 
					        const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
 | 
				
			||||||
 | 
					        const extractor::TravelMode travel_mode =
 | 
				
			||||||
 | 
					            (unpacked_path.empty() && start_traversed_in_reverse)
 | 
				
			||||||
 | 
					                ? phantom_node_pair.source_phantom.backward_travel_mode
 | 
				
			||||||
 | 
					                : facade.GetTravelModeForEdgeID(turn_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto geometry_index = facade.GetGeometryIndexForEdgeID(turn_id);
 | 
				
			||||||
 | 
					        std::vector<NodeID> id_vector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::vector<EdgeWeight> weight_vector;
 | 
				
			||||||
 | 
					        std::vector<EdgeWeight> duration_vector;
 | 
				
			||||||
 | 
					        std::vector<DatasourceID> datasource_vector;
 | 
				
			||||||
 | 
					        if (geometry_index.forward)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const NodeID to = facade.GetTarget(edge);
 | 
					            id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id);
 | 
				
			||||||
            if (to == node)
 | 
					            weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id);
 | 
				
			||||||
            {
 | 
					            duration_vector = facade.GetUncompressedForwardDurations(geometry_index.id);
 | 
				
			||||||
                const auto value = UseDuration ? data.duration : data.weight;
 | 
					            datasource_vector = facade.GetUncompressedForwardDatasources(geometry_index.id);
 | 
				
			||||||
                loop_weight = std::min(loop_weight, value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    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<NodeID, NodeID>, const EdgeData &) called for each
 | 
					 | 
				
			||||||
 * original edge found.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename BidirectionalIterator, typename Callback>
 | 
					 | 
				
			||||||
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &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<std::pair<NodeID, NodeID>> 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<NodeID, NodeID> 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 auto &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 auto &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<EdgeWeight>::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.turn_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
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // We found an original edge, call our callback.
 | 
					            id_vector = facade.GetUncompressedReverseGeometry(geometry_index.id);
 | 
				
			||||||
            std::forward<Callback>(callback)(edge, data);
 | 
					            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(turn_id))
 | 
				
			||||||
 | 
					            unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
 | 
				
			||||||
 | 
					        unpacked_path.back().turn_instruction = turn_instruction;
 | 
				
			||||||
 | 
					        unpacked_path.back().duration_until_turn += facade.GetDurationPenaltyForEdgeID(turn_id);
 | 
				
			||||||
 | 
					        unpacked_path.back().weight_until_turn += facade.GetWeightPenaltyForEdgeID(turn_id);
 | 
				
			||||||
 | 
					        unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id);
 | 
				
			||||||
 | 
					        unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Should work both for CH and not CH if the unpackPath function above is implemented a proper
 | 
					 | 
				
			||||||
// implementation.
 | 
					 | 
				
			||||||
template <typename RandomIter, typename FacadeT>
 | 
					 | 
				
			||||||
void unpackPath(const FacadeT &facade,
 | 
					 | 
				
			||||||
                RandomIter packed_path_begin,
 | 
					 | 
				
			||||||
                RandomIter packed_path_end,
 | 
					 | 
				
			||||||
                const PhantomNodes &phantom_node_pair,
 | 
					 | 
				
			||||||
                std::vector<PathData> &unpacked_path)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unpackPath(
 | 
					 | 
				
			||||||
        facade,
 | 
					 | 
				
			||||||
        packed_path_begin,
 | 
					 | 
				
			||||||
        packed_path_end,
 | 
					 | 
				
			||||||
        [&facade,
 | 
					 | 
				
			||||||
         &unpacked_path,
 | 
					 | 
				
			||||||
         &phantom_node_pair,
 | 
					 | 
				
			||||||
         &start_traversed_in_reverse,
 | 
					 | 
				
			||||||
         &target_traversed_in_reverse](std::pair<NodeID, NodeID> & /* edge */,
 | 
					 | 
				
			||||||
                                       const auto &edge_data) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            BOOST_ASSERT_MSG(!edge_data.shortcut, "original edge flagged as shortcut");
 | 
					 | 
				
			||||||
            const auto turn_id = edge_data.turn_id; // edge-based node ID
 | 
					 | 
				
			||||||
            const auto name_index = facade.GetNameIndexFromEdgeID(turn_id);
 | 
					 | 
				
			||||||
            const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
 | 
					 | 
				
			||||||
            const extractor::TravelMode travel_mode =
 | 
					 | 
				
			||||||
                (unpacked_path.empty() && start_traversed_in_reverse)
 | 
					 | 
				
			||||||
                    ? phantom_node_pair.source_phantom.backward_travel_mode
 | 
					 | 
				
			||||||
                    : facade.GetTravelModeForEdgeID(turn_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const auto geometry_index = facade.GetGeometryIndexForEdgeID(turn_id);
 | 
					 | 
				
			||||||
            std::vector<NodeID> id_vector;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::vector<EdgeWeight> weight_vector;
 | 
					 | 
				
			||||||
            std::vector<EdgeWeight> duration_vector;
 | 
					 | 
				
			||||||
            std::vector<DatasourceID> 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(turn_id))
 | 
					 | 
				
			||||||
                unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
 | 
					 | 
				
			||||||
            unpacked_path.back().turn_instruction = turn_instruction;
 | 
					 | 
				
			||||||
            unpacked_path.back().duration_until_turn += facade.GetDurationPenaltyForEdgeID(turn_id);
 | 
					 | 
				
			||||||
            unpacked_path.back().weight_until_turn += facade.GetWeightPenaltyForEdgeID(turn_id);
 | 
					 | 
				
			||||||
            unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id);
 | 
					 | 
				
			||||||
            unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::size_t start_index = 0, end_index = 0;
 | 
					    std::size_t start_index = 0, end_index = 0;
 | 
				
			||||||
    std::vector<unsigned> id_vector;
 | 
					    std::vector<unsigned> id_vector;
 | 
				
			||||||
@ -536,140 +305,8 @@ void unpackPath(const FacadeT &facade,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                const NodeID from,
 | 
					 | 
				
			||||||
                const NodeID to,
 | 
					 | 
				
			||||||
                std::vector<NodeID> &unpacked_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
                                const SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
                                const NodeID middle_node_id,
 | 
					 | 
				
			||||||
                                std::vector<NodeID> &packed_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
 | 
					 | 
				
			||||||
                                      const NodeID middle_node_id,
 | 
					 | 
				
			||||||
                                      std::vector<NodeID> &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<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
            SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
            SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
            std::int32_t &weight,
 | 
					 | 
				
			||||||
            std::vector<NodeID> &packed_leg,
 | 
					 | 
				
			||||||
            const bool force_loop_forward,
 | 
					 | 
				
			||||||
            const bool force_loop_reverse,
 | 
					 | 
				
			||||||
            const int duration_upper_bound = INVALID_EDGE_WEIGHT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
 | 
					 | 
				
			||||||
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &,
 | 
					 | 
				
			||||||
                   std::int32_t &weight,
 | 
					 | 
				
			||||||
                   std::vector<NodeID> &packed_leg,
 | 
					 | 
				
			||||||
                   const bool force_loop_forward,
 | 
					 | 
				
			||||||
                   const bool force_loop_reverse,
 | 
					 | 
				
			||||||
                   const int duration_upper_bound = INVALID_EDGE_WEIGHT)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    search(facade,
 | 
					 | 
				
			||||||
           forward_heap,
 | 
					 | 
				
			||||||
           reverse_heap,
 | 
					 | 
				
			||||||
           weight,
 | 
					 | 
				
			||||||
           packed_leg,
 | 
					 | 
				
			||||||
           force_loop_forward,
 | 
					 | 
				
			||||||
           force_loop_reverse,
 | 
					 | 
				
			||||||
           duration_upper_bound);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// assumes that heaps are already setup correctly.
 | 
					 | 
				
			||||||
// A forced loop might be necessary, if source and target are on the same segment.
 | 
					 | 
				
			||||||
// If this is the case and the offsets of the respective direction are larger for the source
 | 
					 | 
				
			||||||
// 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<algorithm::CoreCH> &facade,
 | 
					 | 
				
			||||||
            SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
            SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
            SearchEngineData::QueryHeap &forward_core_heap,
 | 
					 | 
				
			||||||
            SearchEngineData::QueryHeap &reverse_core_heap,
 | 
					 | 
				
			||||||
            int &weight,
 | 
					 | 
				
			||||||
            std::vector<NodeID> &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<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                       const std::vector<NodeID> &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
 | 
					 | 
				
			||||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &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<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
                   const PhantomNode &source_phantom,
 | 
					 | 
				
			||||||
                   const PhantomNode &target_phantom,
 | 
					 | 
				
			||||||
                   int duration_upper_bound = INVALID_EDGE_WEIGHT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
 | 
					 | 
				
			||||||
inline double
 | 
					 | 
				
			||||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &,
 | 
					 | 
				
			||||||
                   const PhantomNode &source_phantom,
 | 
					 | 
				
			||||||
                   const PhantomNode &target_phantom,
 | 
					 | 
				
			||||||
                   int duration_upper_bound = INVALID_EDGE_WEIGHT)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return getNetworkDistance(
 | 
					 | 
				
			||||||
        facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace routing_algorithms
 | 
					} // namespace routing_algorithms
 | 
				
			||||||
} // namespace engine
 | 
					} // namespace engine
 | 
				
			||||||
} // namespace osrm
 | 
					} // namespace osrm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // ROUTING_BASE_HPP
 | 
					#endif // OSRM_ENGINE_ROUTING_BASE_HPP
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										475
									
								
								include/engine/routing_algorithms/routing_base_ch.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								include/engine/routing_algorithms/routing_base_ch.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,475 @@
 | 
				
			|||||||
 | 
					#ifndef OSRM_ENGINE_ROUTING_BASE_CH_HPP
 | 
				
			||||||
 | 
					#define OSRM_ENGINE_ROUTING_BASE_CH_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "extractor/guidance/turn_instruction.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "engine/algorithm.hpp"
 | 
				
			||||||
 | 
					#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
 | 
				
			||||||
 | 
					#include "engine/internal_route_result.hpp"
 | 
				
			||||||
 | 
					#include "engine/routing_algorithms/routing_base.hpp"
 | 
				
			||||||
 | 
					#include "engine/search_engine_data.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "util/coordinate_calculation.hpp"
 | 
				
			||||||
 | 
					#include "util/guidance/turn_bearing.hpp"
 | 
				
			||||||
 | 
					#include "util/typedefs.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/assert.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <numeric>
 | 
				
			||||||
 | 
					#include <stack>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace osrm
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace engine
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace routing_algorithms
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ch
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Stalling
 | 
				
			||||||
 | 
					template <bool DIRECTION, typename HeapT>
 | 
				
			||||||
 | 
					bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                 const NodeID node,
 | 
				
			||||||
 | 
					                 const EdgeWeight weight,
 | 
				
			||||||
 | 
					                 const HeapT &query_heap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    for (auto edge : facade.GetAdjacentEdgeRange(node))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto &data = facade.GetEdgeData(edge);
 | 
				
			||||||
 | 
					        if (DIRECTION == REVERSE_DIRECTION ? data.forward : data.backward)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <bool DIRECTION>
 | 
				
			||||||
 | 
					void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                        const NodeID node,
 | 
				
			||||||
 | 
					                        const EdgeWeight weight,
 | 
				
			||||||
 | 
					                        SearchEngineData::QueryHeap &heap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    for (const auto edge : facade.GetAdjacentEdgeRange(node))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto &data = facade.GetEdgeData(edge);
 | 
				
			||||||
 | 
					        if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const NodeID to = facade.GetTarget(edge);
 | 
				
			||||||
 | 
					            const EdgeWeight edge_weight = data.weight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
 | 
				
			||||||
 | 
					            const EdgeWeight to_weight = weight + edge_weight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // New Node discovered -> Add to Heap + Node Info Storage
 | 
				
			||||||
 | 
					            if (!heap.WasInserted(to))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                heap.Insert(to, to_weight, node);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // Found a shorter Path -> Update weight
 | 
				
			||||||
 | 
					            else if (to_weight < heap.GetKey(to))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // new parent
 | 
				
			||||||
 | 
					                heap.GetData(to).parent = node;
 | 
				
			||||||
 | 
					                heap.DecreaseKey(to, to_weight);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					forward heap: a(-100), b(0),
 | 
				
			||||||
 | 
					reverse heap: c(0), d(100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a --- d
 | 
				
			||||||
 | 
					  \ /
 | 
				
			||||||
 | 
					  / \
 | 
				
			||||||
 | 
					b --- c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is equivalent to running a bi-directional Dijkstra on the following graph:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					static constexpr bool ENABLE_STALLING = true;
 | 
				
			||||||
 | 
					static constexpr bool DISABLE_STALLING = false;
 | 
				
			||||||
 | 
					template <bool DIRECTION, bool STALLING = ENABLE_STALLING>
 | 
				
			||||||
 | 
					void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                 SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					                 SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					                 NodeID &middle_node_id,
 | 
				
			||||||
 | 
					                 EdgeWeight &upper_bound,
 | 
				
			||||||
 | 
					                 EdgeWeight min_edge_offset,
 | 
				
			||||||
 | 
					                 const bool force_loop_forward,
 | 
				
			||||||
 | 
					                 const bool force_loop_reverse)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const NodeID node = forward_heap.DeleteMin();
 | 
				
			||||||
 | 
					    const EdgeWeight weight = forward_heap.GetKey(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (reverse_heap.WasInserted(node))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
 | 
				
			||||||
 | 
					        if (new_weight < upper_bound)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // if loops are forced, they are so at the source
 | 
				
			||||||
 | 
					            if ((force_loop_forward && forward_heap.GetData(node).parent == node) ||
 | 
				
			||||||
 | 
					                (force_loop_reverse && reverse_heap.GetData(node).parent == node) ||
 | 
				
			||||||
 | 
					                // in this case we are looking at a bi-directional way where the source
 | 
				
			||||||
 | 
					                // and target phantom are on the same edge based node
 | 
				
			||||||
 | 
					                new_weight < 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // check whether there is a loop present at the node
 | 
				
			||||||
 | 
					                for (const auto edge : facade.GetAdjacentEdgeRange(node))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    const auto &data = facade.GetEdgeData(edge);
 | 
				
			||||||
 | 
					                    if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        const NodeID to = facade.GetTarget(edge);
 | 
				
			||||||
 | 
					                        if (to == node)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            const EdgeWeight edge_weight = data.weight;
 | 
				
			||||||
 | 
					                            const EdgeWeight loop_weight = new_weight + edge_weight;
 | 
				
			||||||
 | 
					                            if (loop_weight >= 0 && loop_weight < upper_bound)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                middle_node_id = node;
 | 
				
			||||||
 | 
					                                upper_bound = loop_weight;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                BOOST_ASSERT(new_weight >= 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                middle_node_id = node;
 | 
				
			||||||
 | 
					                upper_bound = new_weight;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // make sure we don't terminate too early if we initialize the weight
 | 
				
			||||||
 | 
					    // for the nodes in the forward heap with the forward/reverse offset
 | 
				
			||||||
 | 
					    BOOST_ASSERT(min_edge_offset <= 0);
 | 
				
			||||||
 | 
					    if (weight + min_edge_offset > upper_bound)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        forward_heap.DeleteAll();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Stalling
 | 
				
			||||||
 | 
					    if (STALLING && stallAtNode<DIRECTION>(facade, node, weight, forward_heap))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    relaxOutgoingEdges<DIRECTION>(facade, node, weight, forward_heap);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <bool UseDuration>
 | 
				
			||||||
 | 
					EdgeWeight
 | 
				
			||||||
 | 
					getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					              NodeID 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 NodeID to = facade.GetTarget(edge);
 | 
				
			||||||
 | 
					            if (to == node)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const auto value = UseDuration ? data.duration : data.weight;
 | 
				
			||||||
 | 
					                loop_weight = std::min(loop_weight, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    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<NodeID, NodeID>, const EdgeID &) called for each
 | 
				
			||||||
 | 
					 * original edge found.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename BidirectionalIterator, typename Callback>
 | 
				
			||||||
 | 
					void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &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<std::pair<NodeID, NodeID>> 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<NodeID, NodeID> 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 auto &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 auto &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<EdgeWeight>::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.turn_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>(callback)(edge, smaller_edge_id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename RandomIter, typename FacadeT>
 | 
				
			||||||
 | 
					void unpackPath(const FacadeT &facade,
 | 
				
			||||||
 | 
					                RandomIter packed_path_begin,
 | 
				
			||||||
 | 
					                RandomIter packed_path_end,
 | 
				
			||||||
 | 
					                const PhantomNodes &phantom_nodes,
 | 
				
			||||||
 | 
					                std::vector<PathData> &unpacked_path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
 | 
				
			||||||
 | 
					    BOOST_ASSERT(nodes_number > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<EdgeID> unpacked_edges;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto source_node = *packed_path_begin, target_node = *packed_path_begin;
 | 
				
			||||||
 | 
					    if (nodes_number > 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        target_node = *std::prev(packed_path_end);
 | 
				
			||||||
 | 
					        unpacked_edges.reserve(std::distance(packed_path_begin, packed_path_end));
 | 
				
			||||||
 | 
					        unpackPath(
 | 
				
			||||||
 | 
					            facade,
 | 
				
			||||||
 | 
					            packed_path_begin,
 | 
				
			||||||
 | 
					            packed_path_end,
 | 
				
			||||||
 | 
					            [&facade, &unpacked_edges](std::pair<NodeID, NodeID> & /* edge */,
 | 
				
			||||||
 | 
					                                       const auto &edge_id) { unpacked_edges.push_back(edge_id); });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                const NodeID from,
 | 
				
			||||||
 | 
					                const NodeID to,
 | 
				
			||||||
 | 
					                std::vector<NodeID> &unpacked_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					                                const SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					                                const NodeID middle_node_id,
 | 
				
			||||||
 | 
					                                std::vector<NodeID> &packed_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
 | 
				
			||||||
 | 
					                                      const NodeID middle_node_id,
 | 
				
			||||||
 | 
					                                      std::vector<NodeID> &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<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					            SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					            SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					            std::int32_t &weight,
 | 
				
			||||||
 | 
					            std::vector<NodeID> &packed_leg,
 | 
				
			||||||
 | 
					            const bool force_loop_forward,
 | 
				
			||||||
 | 
					            const bool force_loop_reverse,
 | 
				
			||||||
 | 
					            const int duration_upper_bound = INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Alias to be compatible with the overload for CoreCH that needs 4 heaps
 | 
				
			||||||
 | 
					inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &,
 | 
				
			||||||
 | 
					                   std::int32_t &weight,
 | 
				
			||||||
 | 
					                   std::vector<NodeID> &packed_leg,
 | 
				
			||||||
 | 
					                   const bool force_loop_forward,
 | 
				
			||||||
 | 
					                   const bool force_loop_reverse,
 | 
				
			||||||
 | 
					                   const int duration_upper_bound = INVALID_EDGE_WEIGHT)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    search(facade,
 | 
				
			||||||
 | 
					           forward_heap,
 | 
				
			||||||
 | 
					           reverse_heap,
 | 
				
			||||||
 | 
					           weight,
 | 
				
			||||||
 | 
					           packed_leg,
 | 
				
			||||||
 | 
					           force_loop_forward,
 | 
				
			||||||
 | 
					           force_loop_reverse,
 | 
				
			||||||
 | 
					           duration_upper_bound);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// assumes that heaps are already setup correctly.
 | 
				
			||||||
 | 
					// A forced loop might be necessary, if source and target are on the same segment.
 | 
				
			||||||
 | 
					// If this is the case and the offsets of the respective direction are larger for the source
 | 
				
			||||||
 | 
					// 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<algorithm::CoreCH> &facade,
 | 
				
			||||||
 | 
					            SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					            SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					            SearchEngineData::QueryHeap &forward_core_heap,
 | 
				
			||||||
 | 
					            SearchEngineData::QueryHeap &reverse_core_heap,
 | 
				
			||||||
 | 
					            int &weight,
 | 
				
			||||||
 | 
					            std::vector<NodeID> &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<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                       const std::vector<NodeID> &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
 | 
				
			||||||
 | 
					getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &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<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					                   const PhantomNode &source_phantom,
 | 
				
			||||||
 | 
					                   const PhantomNode &target_phantom,
 | 
				
			||||||
 | 
					                   int duration_upper_bound = INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Alias to be compatible with the overload for CoreCH that needs 4 heaps
 | 
				
			||||||
 | 
					inline double
 | 
				
			||||||
 | 
					getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &forward_heap,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &reverse_heap,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &,
 | 
				
			||||||
 | 
					                   SearchEngineData::QueryHeap &,
 | 
				
			||||||
 | 
					                   const PhantomNode &source_phantom,
 | 
				
			||||||
 | 
					                   const PhantomNode &target_phantom,
 | 
				
			||||||
 | 
					                   int duration_upper_bound = INVALID_EDGE_WEIGHT)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return getNetworkDistance(
 | 
				
			||||||
 | 
					        facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace ch
 | 
				
			||||||
 | 
					} // namespace routing_algorithms
 | 
				
			||||||
 | 
					} // namespace engine
 | 
				
			||||||
 | 
					} // namespace osrm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // OSRM_ENGINE_ROUTING_BASE_CH_HPP
 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
#include "engine/routing_algorithms/alternative_path.hpp"
 | 
					#include "engine/routing_algorithms/alternative_path.hpp"
 | 
				
			||||||
#include "engine/routing_algorithms/routing_base.hpp"
 | 
					#include "engine/routing_algorithms/routing_base_ch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util/integer_range.hpp"
 | 
					#include "util/integer_range.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -89,7 +89,7 @@ void alternativeRoutingStep(
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // check whether there is a loop present at the node
 | 
					                // check whether there is a loop present at the node
 | 
				
			||||||
                const auto loop_weight = getLoopWeight<false>(facade, node);
 | 
					                const auto loop_weight = ch::getLoopWeight<false>(facade, node);
 | 
				
			||||||
                const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
 | 
					                const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
 | 
				
			||||||
                if (loop_weight != INVALID_EDGE_WEIGHT &&
 | 
					                if (loop_weight != INVALID_EDGE_WEIGHT &&
 | 
				
			||||||
                    new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
 | 
					                    new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
 | 
				
			||||||
@ -139,11 +139,11 @@ void retrievePackedAlternatePath(const QueryHeap &forward_heap1,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    // fetch packed path [s,v)
 | 
					    // fetch packed path [s,v)
 | 
				
			||||||
    std::vector<NodeID> packed_v_t_path;
 | 
					    std::vector<NodeID> packed_v_t_path;
 | 
				
			||||||
    retrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path);
 | 
					    ch::retrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path);
 | 
				
			||||||
    packed_path.pop_back(); // remove middle node. It's in both half-paths
 | 
					    packed_path.pop_back(); // remove middle node. It's in both half-paths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // fetch patched path [v,t]
 | 
					    // fetch patched path [v,t]
 | 
				
			||||||
    retrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path);
 | 
					    ch::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());
 | 
					    packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -180,14 +180,14 @@ void computeLengthAndSharingOfViaPath(
 | 
				
			|||||||
    // compute path <s,..,v> by reusing forward search from s
 | 
					    // compute path <s,..,v> by reusing forward search from s
 | 
				
			||||||
    while (!new_reverse_heap.Empty())
 | 
					    while (!new_reverse_heap.Empty())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        routingStep<REVERSE_DIRECTION>(facade,
 | 
					        ch::routingStep<REVERSE_DIRECTION>(facade,
 | 
				
			||||||
                                       new_reverse_heap,
 | 
					                                           new_reverse_heap,
 | 
				
			||||||
                                       existing_forward_heap,
 | 
					                                           existing_forward_heap,
 | 
				
			||||||
                                       s_v_middle,
 | 
					                                           s_v_middle,
 | 
				
			||||||
                                       upper_bound_s_v_path_length,
 | 
					                                           upper_bound_s_v_path_length,
 | 
				
			||||||
                                       min_edge_offset,
 | 
					                                           min_edge_offset,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS,
 | 
					                                           DO_NOT_FORCE_LOOPS,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS);
 | 
					                                           DO_NOT_FORCE_LOOPS);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // compute path <v,..,t> by reusing backward search from node t
 | 
					    // compute path <v,..,t> by reusing backward search from node t
 | 
				
			||||||
    NodeID v_t_middle = SPECIAL_NODEID;
 | 
					    NodeID v_t_middle = SPECIAL_NODEID;
 | 
				
			||||||
@ -195,14 +195,14 @@ void computeLengthAndSharingOfViaPath(
 | 
				
			|||||||
    new_forward_heap.Insert(via_node, 0, via_node);
 | 
					    new_forward_heap.Insert(via_node, 0, via_node);
 | 
				
			||||||
    while (!new_forward_heap.Empty())
 | 
					    while (!new_forward_heap.Empty())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        routingStep<FORWARD_DIRECTION>(facade,
 | 
					        ch::routingStep<FORWARD_DIRECTION>(facade,
 | 
				
			||||||
                                       new_forward_heap,
 | 
					                                           new_forward_heap,
 | 
				
			||||||
                                       existing_reverse_heap,
 | 
					                                           existing_reverse_heap,
 | 
				
			||||||
                                       v_t_middle,
 | 
					                                           v_t_middle,
 | 
				
			||||||
                                       upper_bound_of_v_t_path_length,
 | 
					                                           upper_bound_of_v_t_path_length,
 | 
				
			||||||
                                       min_edge_offset,
 | 
					                                           min_edge_offset,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS,
 | 
					                                           DO_NOT_FORCE_LOOPS,
 | 
				
			||||||
                                       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;
 | 
					    *real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -212,9 +212,9 @@ void computeLengthAndSharingOfViaPath(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // retrieve packed paths
 | 
					    // retrieve packed paths
 | 
				
			||||||
    retrievePackedPathFromHeap(
 | 
					    ch::retrievePackedPathFromHeap(
 | 
				
			||||||
        existing_forward_heap, new_reverse_heap, s_v_middle, packed_s_v_path);
 | 
					        existing_forward_heap, new_reverse_heap, s_v_middle, packed_s_v_path);
 | 
				
			||||||
    retrievePackedPathFromHeap(
 | 
					    ch::retrievePackedPathFromHeap(
 | 
				
			||||||
        new_forward_heap, existing_reverse_heap, v_t_middle, packed_v_t_path);
 | 
					        new_forward_heap, existing_reverse_heap, v_t_middle, packed_v_t_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // partial unpacking, compute sharing
 | 
					    // partial unpacking, compute sharing
 | 
				
			||||||
@ -234,14 +234,14 @@ void computeLengthAndSharingOfViaPath(
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (packed_s_v_path[current_node] == packed_shortest_path[current_node])
 | 
					            if (packed_s_v_path[current_node] == packed_shortest_path[current_node])
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                unpackEdge(facade,
 | 
					                ch::unpackEdge(facade,
 | 
				
			||||||
                           packed_s_v_path[current_node],
 | 
					                               packed_s_v_path[current_node],
 | 
				
			||||||
                           packed_s_v_path[current_node + 1],
 | 
					                               packed_s_v_path[current_node + 1],
 | 
				
			||||||
                           partially_unpacked_via_path);
 | 
					                               partially_unpacked_via_path);
 | 
				
			||||||
                unpackEdge(facade,
 | 
					                ch::unpackEdge(facade,
 | 
				
			||||||
                           packed_shortest_path[current_node],
 | 
					                               packed_shortest_path[current_node],
 | 
				
			||||||
                           packed_shortest_path[current_node + 1],
 | 
					                               packed_shortest_path[current_node + 1],
 | 
				
			||||||
                           partially_unpacked_shortest_path);
 | 
					                               partially_unpacked_shortest_path);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -280,14 +280,14 @@ void computeLengthAndSharingOfViaPath(
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index])
 | 
					            if (packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index])
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                unpackEdge(facade,
 | 
					                ch::unpackEdge(facade,
 | 
				
			||||||
                           packed_v_t_path[via_path_index - 1],
 | 
					                               packed_v_t_path[via_path_index - 1],
 | 
				
			||||||
                           packed_v_t_path[via_path_index],
 | 
					                               packed_v_t_path[via_path_index],
 | 
				
			||||||
                           partially_unpacked_via_path);
 | 
					                               partially_unpacked_via_path);
 | 
				
			||||||
                unpackEdge(facade,
 | 
					                ch::unpackEdge(facade,
 | 
				
			||||||
                           packed_shortest_path[shortest_path_index - 1],
 | 
					                               packed_shortest_path[shortest_path_index - 1],
 | 
				
			||||||
                           packed_shortest_path[shortest_path_index],
 | 
					                               packed_shortest_path[shortest_path_index],
 | 
				
			||||||
                           partially_unpacked_shortest_path);
 | 
					                               partially_unpacked_shortest_path);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -342,14 +342,14 @@ bool viaNodeCandidatePassesTTest(
 | 
				
			|||||||
    new_reverse_heap.Insert(candidate.node, 0, candidate.node);
 | 
					    new_reverse_heap.Insert(candidate.node, 0, candidate.node);
 | 
				
			||||||
    while (new_reverse_heap.Size() > 0)
 | 
					    while (new_reverse_heap.Size() > 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        routingStep<REVERSE_DIRECTION>(facade,
 | 
					        ch::routingStep<REVERSE_DIRECTION>(facade,
 | 
				
			||||||
                                       new_reverse_heap,
 | 
					                                           new_reverse_heap,
 | 
				
			||||||
                                       existing_forward_heap,
 | 
					                                           existing_forward_heap,
 | 
				
			||||||
                                       *s_v_middle,
 | 
					                                           *s_v_middle,
 | 
				
			||||||
                                       upper_bound_s_v_path_length,
 | 
					                                           upper_bound_s_v_path_length,
 | 
				
			||||||
                                       min_edge_offset,
 | 
					                                           min_edge_offset,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS,
 | 
					                                           DO_NOT_FORCE_LOOPS,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS);
 | 
					                                           DO_NOT_FORCE_LOOPS);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length)
 | 
					    if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length)
 | 
				
			||||||
@ -363,14 +363,14 @@ bool viaNodeCandidatePassesTTest(
 | 
				
			|||||||
    new_forward_heap.Insert(candidate.node, 0, candidate.node);
 | 
					    new_forward_heap.Insert(candidate.node, 0, candidate.node);
 | 
				
			||||||
    while (new_forward_heap.Size() > 0)
 | 
					    while (new_forward_heap.Size() > 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        routingStep<FORWARD_DIRECTION>(facade,
 | 
					        ch::routingStep<FORWARD_DIRECTION>(facade,
 | 
				
			||||||
                                       new_forward_heap,
 | 
					                                           new_forward_heap,
 | 
				
			||||||
                                       existing_reverse_heap,
 | 
					                                           existing_reverse_heap,
 | 
				
			||||||
                                       *v_t_middle,
 | 
					                                           *v_t_middle,
 | 
				
			||||||
                                       upper_bound_of_v_t_path_length,
 | 
					                                           upper_bound_of_v_t_path_length,
 | 
				
			||||||
                                       min_edge_offset,
 | 
					                                           min_edge_offset,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS,
 | 
					                                           DO_NOT_FORCE_LOOPS,
 | 
				
			||||||
                                       DO_NOT_FORCE_LOOPS);
 | 
					                                           DO_NOT_FORCE_LOOPS);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length)
 | 
					    if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length)
 | 
				
			||||||
@ -381,10 +381,10 @@ bool viaNodeCandidatePassesTTest(
 | 
				
			|||||||
    *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
 | 
					    *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // retrieve packed paths
 | 
					    // retrieve packed paths
 | 
				
			||||||
    retrievePackedPathFromHeap(
 | 
					    ch::retrievePackedPathFromHeap(
 | 
				
			||||||
        existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path);
 | 
					        existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    retrievePackedPathFromHeap(
 | 
					    ch::retrievePackedPathFromHeap(
 | 
				
			||||||
        new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path);
 | 
					        new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NodeID s_P = *s_v_middle, t_P = *v_t_middle;
 | 
					    NodeID s_P = *s_v_middle, t_P = *v_t_middle;
 | 
				
			||||||
@ -536,25 +536,25 @@ bool viaNodeCandidatePassesTTest(
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!forward_heap3.Empty())
 | 
					        if (!forward_heap3.Empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            routingStep<FORWARD_DIRECTION>(facade,
 | 
					            ch::routingStep<FORWARD_DIRECTION>(facade,
 | 
				
			||||||
                                           forward_heap3,
 | 
					                                               forward_heap3,
 | 
				
			||||||
                                           reverse_heap3,
 | 
					                                               reverse_heap3,
 | 
				
			||||||
                                           middle,
 | 
					                                               middle,
 | 
				
			||||||
                                           upper_bound,
 | 
					                                               upper_bound,
 | 
				
			||||||
                                           min_edge_offset,
 | 
					                                               min_edge_offset,
 | 
				
			||||||
                                           DO_NOT_FORCE_LOOPS,
 | 
					                                               DO_NOT_FORCE_LOOPS,
 | 
				
			||||||
                                           DO_NOT_FORCE_LOOPS);
 | 
					                                               DO_NOT_FORCE_LOOPS);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (!reverse_heap3.Empty())
 | 
					        if (!reverse_heap3.Empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            routingStep<REVERSE_DIRECTION>(facade,
 | 
					            ch::routingStep<REVERSE_DIRECTION>(facade,
 | 
				
			||||||
                                           reverse_heap3,
 | 
					                                               reverse_heap3,
 | 
				
			||||||
                                           forward_heap3,
 | 
					                                               forward_heap3,
 | 
				
			||||||
                                           middle,
 | 
					                                               middle,
 | 
				
			||||||
                                           upper_bound,
 | 
					                                               upper_bound,
 | 
				
			||||||
                                           min_edge_offset,
 | 
					                                               min_edge_offset,
 | 
				
			||||||
                                           DO_NOT_FORCE_LOOPS,
 | 
					                                               DO_NOT_FORCE_LOOPS,
 | 
				
			||||||
                                           DO_NOT_FORCE_LOOPS);
 | 
					                                               DO_NOT_FORCE_LOOPS);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return (upper_bound <= t_test_path_length);
 | 
					    return (upper_bound <= t_test_path_length);
 | 
				
			||||||
@ -593,35 +593,7 @@ alternativePathSearch(SearchEngineData &engine_working_data,
 | 
				
			|||||||
                     ? -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()
 | 
					                     ? -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()
 | 
				
			||||||
                     : 0);
 | 
					                     : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (phantom_node_pair.source_phantom.forward_segment_id.enabled)
 | 
					    insertNodesInHeaps(forward_heap1, reverse_heap1, phantom_node_pair);
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        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
 | 
					    // search from s and t till new_min/(1+epsilon) > length_of_shortest_path
 | 
				
			||||||
    while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
 | 
					    while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
 | 
				
			||||||
@ -674,8 +646,8 @@ alternativePathSearch(SearchEngineData &engine_working_data,
 | 
				
			|||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        retrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
 | 
					        ch::retrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
 | 
				
			||||||
        retrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
 | 
					        ch::retrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // this set is is used as an indicator if a node is on the shortest path
 | 
					    // this set is is used as an indicator if a node is on the shortest path
 | 
				
			||||||
@ -827,14 +799,14 @@ alternativePathSearch(SearchEngineData &engine_working_data,
 | 
				
			|||||||
        raw_route_data.target_traversed_in_reverse.push_back((
 | 
					        raw_route_data.target_traversed_in_reverse.push_back((
 | 
				
			||||||
            packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
 | 
					            packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unpackPath(facade,
 | 
					        ch::unpackPath(facade,
 | 
				
			||||||
                   // -- packed input
 | 
					                       // -- packed input
 | 
				
			||||||
                   packed_shortest_path.begin(),
 | 
					                       packed_shortest_path.begin(),
 | 
				
			||||||
                   packed_shortest_path.end(),
 | 
					                       packed_shortest_path.end(),
 | 
				
			||||||
                   // -- start of route
 | 
					                       // -- start of route
 | 
				
			||||||
                   phantom_node_pair,
 | 
					                       phantom_node_pair,
 | 
				
			||||||
                   // -- unpacked output
 | 
					                       // -- unpacked output
 | 
				
			||||||
                   raw_route_data.unpacked_path_segments.front());
 | 
					                       raw_route_data.unpacked_path_segments.front());
 | 
				
			||||||
        raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight;
 | 
					        raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -858,11 +830,11 @@ alternativePathSearch(SearchEngineData &engine_working_data,
 | 
				
			|||||||
             phantom_node_pair.target_phantom.forward_segment_id.id));
 | 
					             phantom_node_pair.target_phantom.forward_segment_id.id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // unpack the alternate path
 | 
					        // unpack the alternate path
 | 
				
			||||||
        unpackPath(facade,
 | 
					        ch::unpackPath(facade,
 | 
				
			||||||
                   packed_alternate_path.begin(),
 | 
					                       packed_alternate_path.begin(),
 | 
				
			||||||
                   packed_alternate_path.end(),
 | 
					                       packed_alternate_path.end(),
 | 
				
			||||||
                   phantom_node_pair,
 | 
					                       phantom_node_pair,
 | 
				
			||||||
                   raw_route_data.unpacked_alternative);
 | 
					                       raw_route_data.unpacked_alternative);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        raw_route_data.alternative_path_length = length_of_via_path;
 | 
					        raw_route_data.alternative_path_length = length_of_via_path;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
#include "engine/routing_algorithms/direct_shortest_path.hpp"
 | 
					#include "engine/routing_algorithms/direct_shortest_path.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "engine/routing_algorithms/routing_base.hpp"
 | 
					#include "engine/routing_algorithms/routing_base.hpp"
 | 
				
			||||||
 | 
					#include "engine/routing_algorithms/routing_base_ch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace osrm
 | 
					namespace osrm
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -9,44 +10,8 @@ namespace engine
 | 
				
			|||||||
namespace routing_algorithms
 | 
					namespace routing_algorithms
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace
 | 
					namespace ch
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
void insertInHeaps(SearchEngineData::QueryHeap &forward_heap,
 | 
					 | 
				
			||||||
                   SearchEngineData::QueryHeap &reverse_heap,
 | 
					 | 
				
			||||||
                   const PhantomNodes &nodes)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    const auto &source_phantom = nodes.source_phantom;
 | 
					 | 
				
			||||||
    const auto &target_phantom = nodes.target_phantom;
 | 
					 | 
				
			||||||
    BOOST_ASSERT(source_phantom.IsValid());
 | 
					 | 
				
			||||||
    BOOST_ASSERT(target_phantom.IsValid());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (source_phantom.forward_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        forward_heap.Insert(source_phantom.forward_segment_id.id,
 | 
					 | 
				
			||||||
                            -source_phantom.GetForwardWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            source_phantom.forward_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (source_phantom.reverse_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        forward_heap.Insert(source_phantom.reverse_segment_id.id,
 | 
					 | 
				
			||||||
                            -source_phantom.GetReverseWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            source_phantom.reverse_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (target_phantom.forward_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        reverse_heap.Insert(target_phantom.forward_segment_id.id,
 | 
					 | 
				
			||||||
                            target_phantom.GetForwardWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            target_phantom.forward_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (target_phantom.reverse_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        reverse_heap.Insert(target_phantom.reverse_segment_id.id,
 | 
					 | 
				
			||||||
                            target_phantom.GetReverseWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            target_phantom.reverse_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename AlgorithmT>
 | 
					template <typename AlgorithmT>
 | 
				
			||||||
InternalRouteResult
 | 
					InternalRouteResult
 | 
				
			||||||
@ -82,7 +47,6 @@ extractRoute(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &f
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return raw_route_data;
 | 
					    return raw_route_data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// This is a striped down version of the general shortest path algorithm.
 | 
					/// 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
 | 
					/// The general algorithm always computes two queries for each leg. This is only
 | 
				
			||||||
@ -109,7 +73,7 @@ InternalRouteResult directShortestPathSearchImpl(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int weight = INVALID_EDGE_WEIGHT;
 | 
					    int weight = INVALID_EDGE_WEIGHT;
 | 
				
			||||||
    std::vector<NodeID> packed_leg;
 | 
					    std::vector<NodeID> packed_leg;
 | 
				
			||||||
    insertInHeaps(forward_heap, reverse_heap, phantom_nodes);
 | 
					    insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    search(facade,
 | 
					    search(facade,
 | 
				
			||||||
           forward_heap,
 | 
					           forward_heap,
 | 
				
			||||||
@ -124,12 +88,14 @@ InternalRouteResult directShortestPathSearchImpl(
 | 
				
			|||||||
    return extractRoute(facade, weight, packed_leg, phantom_nodes);
 | 
					    return extractRoute(facade, weight, packed_leg, phantom_nodes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace ch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
InternalRouteResult directShortestPathSearch(
 | 
					InternalRouteResult directShortestPathSearch(
 | 
				
			||||||
    SearchEngineData &engine_working_data,
 | 
					    SearchEngineData &engine_working_data,
 | 
				
			||||||
    const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
 | 
					    const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
 | 
				
			||||||
    const PhantomNodes &phantom_nodes)
 | 
					    const PhantomNodes &phantom_nodes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
 | 
					    return ch::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
InternalRouteResult directShortestPathSearch(
 | 
					InternalRouteResult directShortestPathSearch(
 | 
				
			||||||
@ -137,7 +103,7 @@ InternalRouteResult directShortestPathSearch(
 | 
				
			|||||||
    const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
					    const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
 | 
				
			||||||
    const PhantomNodes &phantom_nodes)
 | 
					    const PhantomNodes &phantom_nodes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
 | 
					    return ch::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace routing_algorithms
 | 
					} // namespace routing_algorithms
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
#include "engine/routing_algorithms/many_to_many.hpp"
 | 
					#include "engine/routing_algorithms/many_to_many.hpp"
 | 
				
			||||||
#include "engine/routing_algorithms/routing_base.hpp"
 | 
					#include "engine/routing_algorithms/routing_base_ch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <boost/assert.hpp>
 | 
					#include <boost/assert.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -101,14 +101,14 @@ void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<alg
 | 
				
			|||||||
            const EdgeWeight new_weight = source_weight + target_weight;
 | 
					            const EdgeWeight new_weight = source_weight + target_weight;
 | 
				
			||||||
            if (new_weight < 0)
 | 
					            if (new_weight < 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                const EdgeWeight loop_weight = getLoopWeight<false>(facade, node);
 | 
					                const EdgeWeight loop_weight = ch::getLoopWeight<false>(facade, node);
 | 
				
			||||||
                const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
 | 
					                const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
 | 
				
			||||||
                if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0)
 | 
					                if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    current_weight = std::min(current_weight, new_weight_with_loop);
 | 
					                    current_weight = std::min(current_weight, new_weight_with_loop);
 | 
				
			||||||
                    current_duration = std::min(current_duration,
 | 
					                    current_duration = std::min(current_duration,
 | 
				
			||||||
                                                source_duration + target_duration +
 | 
					                                                source_duration + target_duration +
 | 
				
			||||||
                                                    getLoopWeight<true>(facade, node));
 | 
					                                                    ch::getLoopWeight<true>(facade, node));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (new_weight < current_weight)
 | 
					            else if (new_weight < current_weight)
 | 
				
			||||||
@ -118,7 +118,7 @@ void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<alg
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (stallAtNode<FORWARD_DIRECTION>(facade, node, source_weight, query_heap))
 | 
					    if (ch::stallAtNode<FORWARD_DIRECTION>(facade, node, source_weight, query_heap))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -139,7 +139,7 @@ void backwardRoutingStep(
 | 
				
			|||||||
    // store settled nodes in search space bucket
 | 
					    // store settled nodes in search space bucket
 | 
				
			||||||
    search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
 | 
					    search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (stallAtNode<REVERSE_DIRECTION>(facade, node, target_weight, query_heap))
 | 
					    if (ch::stallAtNode<REVERSE_DIRECTION>(facade, node, target_weight, query_heap))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -172,21 +172,9 @@ manyToManySearch(SearchEngineData &engine_working_data,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    unsigned column_idx = 0;
 | 
					    unsigned column_idx = 0;
 | 
				
			||||||
    const auto search_target_phantom = [&](const PhantomNode &phantom) {
 | 
					    const auto search_target_phantom = [&](const PhantomNode &phantom) {
 | 
				
			||||||
 | 
					        // clear heap and insert target nodes
 | 
				
			||||||
        query_heap.Clear();
 | 
					        query_heap.Clear();
 | 
				
			||||||
        // insert target(s) at weight 0
 | 
					        insertNodesInHeap<REVERSE_DIRECTION>(query_heap, phantom);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (phantom.forward_segment_id.enabled)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            query_heap.Insert(phantom.forward_segment_id.id,
 | 
					 | 
				
			||||||
                              phantom.GetForwardWeightPlusOffset(),
 | 
					 | 
				
			||||||
                              {phantom.forward_segment_id.id, phantom.GetForwardDuration()});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (phantom.reverse_segment_id.enabled)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            query_heap.Insert(phantom.reverse_segment_id.id,
 | 
					 | 
				
			||||||
                              phantom.GetReverseWeightPlusOffset(),
 | 
					 | 
				
			||||||
                              {phantom.reverse_segment_id.id, phantom.GetReverseDuration()});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // explore search space
 | 
					        // explore search space
 | 
				
			||||||
        while (!query_heap.Empty())
 | 
					        while (!query_heap.Empty())
 | 
				
			||||||
@ -199,21 +187,9 @@ manyToManySearch(SearchEngineData &engine_working_data,
 | 
				
			|||||||
    // for each source do forward search
 | 
					    // for each source do forward search
 | 
				
			||||||
    unsigned row_idx = 0;
 | 
					    unsigned row_idx = 0;
 | 
				
			||||||
    const auto search_source_phantom = [&](const PhantomNode &phantom) {
 | 
					    const auto search_source_phantom = [&](const PhantomNode &phantom) {
 | 
				
			||||||
 | 
					        // clear heap and insert source nodes
 | 
				
			||||||
        query_heap.Clear();
 | 
					        query_heap.Clear();
 | 
				
			||||||
        // insert target(s) at weight 0
 | 
					        insertNodesInHeap<FORWARD_DIRECTION>(query_heap, phantom);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (phantom.forward_segment_id.enabled)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            query_heap.Insert(phantom.forward_segment_id.id,
 | 
					 | 
				
			||||||
                              -phantom.GetForwardWeightPlusOffset(),
 | 
					 | 
				
			||||||
                              {phantom.forward_segment_id.id, -phantom.GetForwardDuration()});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (phantom.reverse_segment_id.enabled)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            query_heap.Insert(phantom.reverse_segment_id.id,
 | 
					 | 
				
			||||||
                              -phantom.GetReverseWeightPlusOffset(),
 | 
					 | 
				
			||||||
                              {phantom.reverse_segment_id.id, -phantom.GetReverseDuration()});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // explore search space
 | 
					        // explore search space
 | 
				
			||||||
        while (!query_heap.Empty())
 | 
					        while (!query_heap.Empty())
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
#include "engine/routing_algorithms/map_matching.hpp"
 | 
					#include "engine/routing_algorithms/map_matching.hpp"
 | 
				
			||||||
#include "engine/routing_algorithms/routing_base.hpp"
 | 
					#include "engine/routing_algorithms/routing_base_ch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "engine/map_matching/hidden_markov_model.hpp"
 | 
					#include "engine/map_matching/hidden_markov_model.hpp"
 | 
				
			||||||
#include "engine/map_matching/matching_confidence.hpp"
 | 
					#include "engine/map_matching/matching_confidence.hpp"
 | 
				
			||||||
@ -210,14 +210,14 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    double network_distance =
 | 
					                    double network_distance =
 | 
				
			||||||
                        getNetworkDistance(facade,
 | 
					                        ch::getNetworkDistance(facade,
 | 
				
			||||||
                                           forward_heap,
 | 
					                                               forward_heap,
 | 
				
			||||||
                                           reverse_heap,
 | 
					                                               reverse_heap,
 | 
				
			||||||
                                           forward_core_heap,
 | 
					                                               forward_core_heap,
 | 
				
			||||||
                                           reverse_core_heap,
 | 
					                                               reverse_core_heap,
 | 
				
			||||||
                                           prev_unbroken_timestamps_list[s].phantom_node,
 | 
					                                               prev_unbroken_timestamps_list[s].phantom_node,
 | 
				
			||||||
                                           current_timestamps_list[s_prime].phantom_node,
 | 
					                                               current_timestamps_list[s_prime].phantom_node,
 | 
				
			||||||
                                           duration_upper_bound);
 | 
					                                               duration_upper_bound);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // get distance diff between loc1/2 and locs/s_prime
 | 
					                    // get distance diff between loc1/2 and locs/s_prime
 | 
				
			||||||
                    const auto d_t = std::abs(network_distance - haversine_distance);
 | 
					                    const auto d_t = std::abs(network_distance - haversine_distance);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
#include "engine/routing_algorithms/routing_base.hpp"
 | 
					#include "engine/routing_algorithms/routing_base_ch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace osrm
 | 
					namespace osrm
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -6,6 +6,8 @@ namespace engine
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
namespace routing_algorithms
 | 
					namespace routing_algorithms
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					namespace ch
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Unpacks a single edge (NodeID->NodeID) from the CH graph down to it's original non-shortcut
 | 
					 * Unpacks a single edge (NodeID->NodeID) from the CH graph down to it's original non-shortcut
 | 
				
			||||||
@ -411,31 +413,7 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorith
 | 
				
			|||||||
    forward_core_heap.Clear();
 | 
					    forward_core_heap.Clear();
 | 
				
			||||||
    reverse_core_heap.Clear();
 | 
					    reverse_core_heap.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (source_phantom.forward_segment_id.enabled)
 | 
					    insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        forward_heap.Insert(source_phantom.forward_segment_id.id,
 | 
					 | 
				
			||||||
                            -source_phantom.GetForwardWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            source_phantom.forward_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (source_phantom.reverse_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        forward_heap.Insert(source_phantom.reverse_segment_id.id,
 | 
					 | 
				
			||||||
                            -source_phantom.GetReverseWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            source_phantom.reverse_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (target_phantom.forward_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        reverse_heap.Insert(target_phantom.forward_segment_id.id,
 | 
					 | 
				
			||||||
                            target_phantom.GetForwardWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            target_phantom.forward_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (target_phantom.reverse_segment_id.enabled)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        reverse_heap.Insert(target_phantom.reverse_segment_id.id,
 | 
					 | 
				
			||||||
                            target_phantom.GetReverseWeightPlusOffset(),
 | 
					 | 
				
			||||||
                            target_phantom.reverse_segment_id.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EdgeWeight weight = INVALID_EDGE_WEIGHT;
 | 
					    EdgeWeight weight = INVALID_EDGE_WEIGHT;
 | 
				
			||||||
    std::vector<NodeID> packed_path;
 | 
					    std::vector<NodeID> packed_path;
 | 
				
			||||||
@ -517,6 +495,7 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorith
 | 
				
			|||||||
    return getPathDistance(facade, packed_path, source_phantom, target_phantom);
 | 
					    return getPathDistance(facade, packed_path, source_phantom, target_phantom);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace ch
 | 
				
			||||||
} // namespace routing_algorithms
 | 
					} // namespace routing_algorithms
 | 
				
			||||||
} // namespace engine
 | 
					} // namespace engine
 | 
				
			||||||
} // namespace osrm
 | 
					} // namespace osrm
 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
#include "engine/routing_algorithms/shortest_path.hpp"
 | 
					#include "engine/routing_algorithms/shortest_path.hpp"
 | 
				
			||||||
#include "engine/routing_algorithms/routing_base.hpp"
 | 
					#include "engine/routing_algorithms/routing_base_ch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <boost/assert.hpp>
 | 
					#include <boost/assert.hpp>
 | 
				
			||||||
#include <boost/optional.hpp>
 | 
					#include <boost/optional.hpp>
 | 
				
			||||||
@ -71,23 +71,24 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algori
 | 
				
			|||||||
    auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
 | 
					    auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
 | 
				
			||||||
    auto is_oneway_target = !(search_to_forward_node && search_to_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
 | 
					    // we only enable loops here if we can't search from forward to backward node
 | 
				
			||||||
    auto needs_loop_forwad = is_oneway_source && needsLoopForward(source_phantom, target_phantom);
 | 
					    auto needs_loop_forwad =
 | 
				
			||||||
 | 
					        is_oneway_source && ch::needsLoopForward(source_phantom, target_phantom);
 | 
				
			||||||
    auto needs_loop_backwards =
 | 
					    auto needs_loop_backwards =
 | 
				
			||||||
        is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
 | 
					        is_oneway_target && ch::needsLoopBackwards(source_phantom, target_phantom);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    forward_core_heap.Clear();
 | 
					    forward_core_heap.Clear();
 | 
				
			||||||
    reverse_core_heap.Clear();
 | 
					    reverse_core_heap.Clear();
 | 
				
			||||||
    BOOST_ASSERT(forward_core_heap.Size() == 0);
 | 
					    BOOST_ASSERT(forward_core_heap.Size() == 0);
 | 
				
			||||||
    BOOST_ASSERT(reverse_core_heap.Size() == 0);
 | 
					    BOOST_ASSERT(reverse_core_heap.Size() == 0);
 | 
				
			||||||
    routing_algorithms::search(facade,
 | 
					    ch::search(facade,
 | 
				
			||||||
                               forward_heap,
 | 
					               forward_heap,
 | 
				
			||||||
                               reverse_heap,
 | 
					               reverse_heap,
 | 
				
			||||||
                               forward_core_heap,
 | 
					               forward_core_heap,
 | 
				
			||||||
                               reverse_core_heap,
 | 
					               reverse_core_heap,
 | 
				
			||||||
                               new_total_weight,
 | 
					               new_total_weight,
 | 
				
			||||||
                               leg_packed_path,
 | 
					               leg_packed_path,
 | 
				
			||||||
                               needs_loop_forwad,
 | 
					               needs_loop_forwad,
 | 
				
			||||||
                               needs_loop_backwards);
 | 
					               needs_loop_backwards);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // if no route is found between two parts of the via-route, the entire route becomes
 | 
					    // 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
 | 
					    // invalid. Adding to invalid edge weight sadly doesn't return an invalid edge weight. Here
 | 
				
			||||||
@ -147,15 +148,15 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &fa
 | 
				
			|||||||
        reverse_core_heap.Clear();
 | 
					        reverse_core_heap.Clear();
 | 
				
			||||||
        BOOST_ASSERT(forward_core_heap.Size() == 0);
 | 
					        BOOST_ASSERT(forward_core_heap.Size() == 0);
 | 
				
			||||||
        BOOST_ASSERT(reverse_core_heap.Size() == 0);
 | 
					        BOOST_ASSERT(reverse_core_heap.Size() == 0);
 | 
				
			||||||
        routing_algorithms::search(facade,
 | 
					        ch::search(facade,
 | 
				
			||||||
                                   forward_heap,
 | 
					                   forward_heap,
 | 
				
			||||||
                                   reverse_heap,
 | 
					                   reverse_heap,
 | 
				
			||||||
                                   forward_core_heap,
 | 
					                   forward_core_heap,
 | 
				
			||||||
                                   reverse_core_heap,
 | 
					                   reverse_core_heap,
 | 
				
			||||||
                                   new_total_weight_to_forward,
 | 
					                   new_total_weight_to_forward,
 | 
				
			||||||
                                   leg_packed_path_forward,
 | 
					                   leg_packed_path_forward,
 | 
				
			||||||
                                   needsLoopForward(source_phantom, target_phantom),
 | 
					                   ch::needsLoopForward(source_phantom, target_phantom),
 | 
				
			||||||
                                   DO_NOT_FORCE_LOOP);
 | 
					                   DO_NOT_FORCE_LOOP);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (search_to_reverse_node)
 | 
					    if (search_to_reverse_node)
 | 
				
			||||||
@ -185,15 +186,15 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &fa
 | 
				
			|||||||
        reverse_core_heap.Clear();
 | 
					        reverse_core_heap.Clear();
 | 
				
			||||||
        BOOST_ASSERT(forward_core_heap.Size() == 0);
 | 
					        BOOST_ASSERT(forward_core_heap.Size() == 0);
 | 
				
			||||||
        BOOST_ASSERT(reverse_core_heap.Size() == 0);
 | 
					        BOOST_ASSERT(reverse_core_heap.Size() == 0);
 | 
				
			||||||
        routing_algorithms::search(facade,
 | 
					        ch::search(facade,
 | 
				
			||||||
                                   forward_heap,
 | 
					                   forward_heap,
 | 
				
			||||||
                                   reverse_heap,
 | 
					                   reverse_heap,
 | 
				
			||||||
                                   forward_core_heap,
 | 
					                   forward_core_heap,
 | 
				
			||||||
                                   reverse_core_heap,
 | 
					                   reverse_core_heap,
 | 
				
			||||||
                                   new_total_weight_to_reverse,
 | 
					                   new_total_weight_to_reverse,
 | 
				
			||||||
                                   leg_packed_path_reverse,
 | 
					                   leg_packed_path_reverse,
 | 
				
			||||||
                                   DO_NOT_FORCE_LOOP,
 | 
					                   DO_NOT_FORCE_LOOP,
 | 
				
			||||||
                                   needsLoopBackwards(source_phantom, target_phantom));
 | 
					                   ch::needsLoopBackwards(source_phantom, target_phantom));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -213,11 +214,11 @@ void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::
 | 
				
			|||||||
        auto leg_begin = total_packed_path.begin() + packed_leg_begin[current_leg];
 | 
					        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];
 | 
					        auto leg_end = total_packed_path.begin() + packed_leg_begin[current_leg + 1];
 | 
				
			||||||
        const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg];
 | 
					        const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg];
 | 
				
			||||||
        unpackPath(facade,
 | 
					        ch::unpackPath(facade,
 | 
				
			||||||
                   leg_begin,
 | 
					                       leg_begin,
 | 
				
			||||||
                   leg_end,
 | 
					                       leg_end,
 | 
				
			||||||
                   unpack_phantom_node_pair,
 | 
					                       unpack_phantom_node_pair,
 | 
				
			||||||
                   raw_route_data.unpacked_path_segments[current_leg]);
 | 
					                       raw_route_data.unpacked_path_segments[current_leg]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        raw_route_data.source_traversed_in_reverse.push_back(
 | 
					        raw_route_data.source_traversed_in_reverse.push_back(
 | 
				
			||||||
            (*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id));
 | 
					            (*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id));
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user