Refactor routing_algorithms to only contain free functions
This commit is contained in:
parent
2fa8d0f534
commit
436b34ffea
@ -1,107 +0,0 @@
|
|||||||
#ifndef EDGE_UNPACKER_H
|
|
||||||
#define EDGE_UNPACKER_H
|
|
||||||
|
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
|
||||||
#include "extractor/travel_mode.hpp"
|
|
||||||
#include "engine/phantom_node.hpp"
|
|
||||||
#include "osrm/coordinate.hpp"
|
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a sequence of connected `NodeID`s in the CH graph, performs a depth-first unpacking of
|
|
||||||
* the shortcut
|
|
||||||
* edges. For every "original" edge found, it calls the `callback` with the two NodeIDs for the
|
|
||||||
* edge, and the EdgeData
|
|
||||||
* for that edge.
|
|
||||||
*
|
|
||||||
* The primary purpose of this unpacking is to expand a path through the CH into the original
|
|
||||||
* route through the
|
|
||||||
* pre-contracted graph.
|
|
||||||
*
|
|
||||||
* Because of the depth-first-search, the `callback` will effectively be called in sequence for
|
|
||||||
* the original route
|
|
||||||
* from beginning to end.
|
|
||||||
*
|
|
||||||
* @param packed_path_begin iterator pointing to the start of the NodeID list
|
|
||||||
* @param packed_path_end iterator pointing to the end of the NodeID list
|
|
||||||
* @param callback void(const std::pair<NodeID, NodeID>, const EdgeData &) called for each
|
|
||||||
* original edge found.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename DataFacadeT, typename BidirectionalIterator, typename Callback>
|
|
||||||
inline void UnpackCHPath(const DataFacadeT &facade,
|
|
||||||
BidirectionalIterator packed_path_begin,
|
|
||||||
BidirectionalIterator packed_path_end,
|
|
||||||
Callback &&callback)
|
|
||||||
{
|
|
||||||
// make sure we have at least something to unpack
|
|
||||||
if (packed_path_begin == packed_path_end)
|
|
||||||
return;
|
|
||||||
|
|
||||||
using EdgeData = typename DataFacadeT::EdgeData;
|
|
||||||
|
|
||||||
std::stack<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 EdgeData &data) { return data.forward; });
|
|
||||||
|
|
||||||
// If we didn't find one there, the we might be looking at a part of the path that
|
|
||||||
// was found using the backward search. Here, we flip the node order (.second, .first)
|
|
||||||
// and only consider edges with the `.backward` flag.
|
|
||||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
|
||||||
{
|
|
||||||
smaller_edge_id = facade.FindSmallestEdge(
|
|
||||||
edge.second, edge.first, [](const EdgeData &data) { return data.backward; });
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't find anything *still*, then something is broken and someone has
|
|
||||||
// called this function with bad values.
|
|
||||||
BOOST_ASSERT_MSG(smaller_edge_id != SPECIAL_EDGEID, "Invalid smaller edge ID");
|
|
||||||
|
|
||||||
const auto &data = facade.GetEdgeData(smaller_edge_id);
|
|
||||||
BOOST_ASSERT_MSG(data.weight != std::numeric_limits<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.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, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // EDGE_UNPACKER_H
|
|
@ -19,15 +19,14 @@ namespace engine
|
|||||||
class RoutingAlgorithmsInterface
|
class RoutingAlgorithmsInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void AlternativeRouting(const PhantomNodes &phantom_node_pair,
|
virtual InternalRouteResult AlternativeRouting(const PhantomNodes &phantom_node_pair) const = 0;
|
||||||
InternalRouteResult &raw_route_data) const = 0;
|
|
||||||
|
|
||||||
virtual void ShortestRouting(const std::vector<PhantomNodes> &phantom_node_pair,
|
virtual InternalRouteResult
|
||||||
const boost::optional<bool> continue_straight_at_waypoint,
|
ShortestRouting(const std::vector<PhantomNodes> &phantom_node_pair,
|
||||||
InternalRouteResult &raw_route_data) const = 0;
|
const boost::optional<bool> continue_straight_at_waypoint) const = 0;
|
||||||
|
|
||||||
virtual void DirectShortestPathRouting(const std::vector<PhantomNodes> &phantom_node_pair,
|
virtual InternalRouteResult
|
||||||
InternalRouteResult &raw_route_data) const = 0;
|
DirectShortestPathRouting(const std::vector<PhantomNodes> &phantom_node_pair) const = 0;
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
virtual std::vector<EdgeWeight>
|
||||||
ManyToManyRouting(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManyRouting(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
@ -53,29 +52,28 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
|||||||
public:
|
public:
|
||||||
RoutingAlgorithms(SearchEngineData &heaps,
|
RoutingAlgorithms(SearchEngineData &heaps,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade)
|
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade)
|
||||||
: facade(facade), alternative_routing(heaps), shortest_path_routing(heaps),
|
: heaps(heaps), facade(facade)
|
||||||
direct_shortest_path_routing(heaps), many_to_many_routing(heaps), map_matching(heaps)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlternativeRouting(const PhantomNodes &phantom_node_pair,
|
InternalRouteResult
|
||||||
InternalRouteResult &raw_route_data) const final override
|
AlternativeRouting(const PhantomNodes &phantom_node_pair) const final override
|
||||||
{
|
{
|
||||||
alternative_routing(facade, phantom_node_pair, raw_route_data);
|
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortestRouting(const std::vector<PhantomNodes> &phantom_node_pair,
|
InternalRouteResult
|
||||||
const boost::optional<bool> continue_straight_at_waypoint,
|
ShortestRouting(const std::vector<PhantomNodes> &phantom_node_pair,
|
||||||
InternalRouteResult &raw_route_data) const final override
|
const boost::optional<bool> continue_straight_at_waypoint) const final override
|
||||||
{
|
{
|
||||||
shortest_path_routing(
|
return routing_algorithms::shortestPathSearch(
|
||||||
facade, phantom_node_pair, continue_straight_at_waypoint, raw_route_data);
|
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectShortestPathRouting(const std::vector<PhantomNodes> &phantom_node_pair,
|
InternalRouteResult DirectShortestPathRouting(
|
||||||
InternalRouteResult &raw_route_data) const final override
|
const std::vector<PhantomNodes> &phantom_node_pair) const final override
|
||||||
{
|
{
|
||||||
direct_shortest_path_routing(facade, phantom_node_pair, raw_route_data);
|
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_node_pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<EdgeWeight>
|
std::vector<EdgeWeight>
|
||||||
@ -83,7 +81,8 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
|||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const final override
|
const std::vector<std::size_t> &target_indices) const final override
|
||||||
{
|
{
|
||||||
return many_to_many_routing(facade, phantom_nodes, source_indices, target_indices);
|
return routing_algorithms::manyToManySearch(
|
||||||
|
heaps, facade, phantom_nodes, source_indices, target_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
routing_algorithms::SubMatchingList MapMatching(
|
routing_algorithms::SubMatchingList MapMatching(
|
||||||
@ -92,32 +91,30 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
|||||||
const std::vector<unsigned> &trace_timestamps,
|
const std::vector<unsigned> &trace_timestamps,
|
||||||
const std::vector<boost::optional<double>> &trace_gps_precision) const final override
|
const std::vector<boost::optional<double>> &trace_gps_precision) const final override
|
||||||
{
|
{
|
||||||
return map_matching(
|
return routing_algorithms::mapMatching(heaps,
|
||||||
facade, candidates_list, trace_coordinates, trace_timestamps, trace_gps_precision);
|
facade,
|
||||||
|
candidates_list,
|
||||||
|
trace_coordinates,
|
||||||
|
trace_timestamps,
|
||||||
|
trace_gps_precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<routing_algorithms::TurnData>
|
std::vector<routing_algorithms::TurnData>
|
||||||
TileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
TileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||||
const std::vector<std::size_t> &sorted_edge_indexes) const final override
|
const std::vector<std::size_t> &sorted_edge_indexes) const final override
|
||||||
{
|
{
|
||||||
return tile_turns(facade, edges, sorted_edge_indexes);
|
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasAlternativeRouting() const final override
|
bool HasAlternativeRouting() const final override
|
||||||
{
|
{
|
||||||
return algorithm_trais::HasAlternativeRouting<AlgorithmT>()(facade);
|
return algorithm_trais::HasAlternativeRouting<AlgorithmT>()(facade);
|
||||||
};
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SearchEngineData &heaps;
|
||||||
// Owned by shared-ptr passed to the query
|
// Owned by shared-ptr passed to the query
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
|
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
|
||||||
|
|
||||||
mutable routing_algorithms::AlternativeRouting<AlgorithmT> alternative_routing;
|
|
||||||
mutable routing_algorithms::ShortestPathRouting<AlgorithmT> shortest_path_routing;
|
|
||||||
mutable routing_algorithms::DirectShortestPathRouting<AlgorithmT> direct_shortest_path_routing;
|
|
||||||
mutable routing_algorithms::ManyToManyRouting<AlgorithmT> many_to_many_routing;
|
|
||||||
mutable routing_algorithms::MapMatching<AlgorithmT> map_matching;
|
|
||||||
routing_algorithms::TileTurns<AlgorithmT> tile_turns;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,11 @@
|
|||||||
#ifndef ALTERNATIVE_PATH_ROUTING_HPP
|
#ifndef ALTERNATIVE_PATH_ROUTING_HPP
|
||||||
#define ALTERNATIVE_PATH_ROUTING_HPP
|
#define ALTERNATIVE_PATH_ROUTING_HPP
|
||||||
|
|
||||||
#include "engine/datafacade/datafacade_base.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
#include "engine/routing_algorithms/routing_base.hpp"
|
#include "engine/internal_route_result.hpp"
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
#include "util/integer_range.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -25,181 +14,13 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
const double constexpr VIAPATH_ALPHA = 0.10;
|
InternalRouteResult
|
||||||
const double constexpr VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
|
alternativePathSearch(SearchEngineData &search_engine_data,
|
||||||
const double constexpr VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const PhantomNodes &phantom_node_pair);
|
||||||
template <typename AlgorithmT> class AlternativeRouting;
|
|
||||||
|
|
||||||
template <> class AlternativeRouting<algorithm::CH> final : private BasicRouting<algorithm::CH>
|
|
||||||
{
|
|
||||||
using super = BasicRouting<algorithm::CH>;
|
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
using QueryHeap = SearchEngineData::QueryHeap;
|
|
||||||
using SearchSpaceEdge = std::pair<NodeID, NodeID>;
|
|
||||||
|
|
||||||
struct RankedCandidateNode
|
|
||||||
{
|
|
||||||
RankedCandidateNode(const NodeID node, const int length, const int sharing)
|
|
||||||
: node(node), length(length), sharing(sharing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID node;
|
|
||||||
int length;
|
|
||||||
int sharing;
|
|
||||||
|
|
||||||
bool operator<(const RankedCandidateNode &other) const
|
|
||||||
{
|
|
||||||
return (2 * length + sharing) < (2 * other.length + other.sharing);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
SearchEngineData &engine_working_data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AlternativeRouting(SearchEngineData &engine_working_data)
|
|
||||||
: engine_working_data(engine_working_data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~AlternativeRouting() {}
|
|
||||||
|
|
||||||
void operator()(const FacadeT &facade,
|
|
||||||
const PhantomNodes &phantom_node_pair,
|
|
||||||
InternalRouteResult &raw_route_data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// unpack alternate <s,..,v,..,t> by exploring search spaces from v
|
|
||||||
void RetrievePackedAlternatePath(const QueryHeap &forward_heap1,
|
|
||||||
const QueryHeap &reverse_heap1,
|
|
||||||
const QueryHeap &forward_heap2,
|
|
||||||
const QueryHeap &reverse_heap2,
|
|
||||||
const NodeID s_v_middle,
|
|
||||||
const NodeID v_t_middle,
|
|
||||||
std::vector<NodeID> &packed_path) const;
|
|
||||||
|
|
||||||
// TODO: reorder parameters
|
|
||||||
// compute and unpack <s,..,v> and <v,..,t> by exploring search spaces
|
|
||||||
// from v and intersecting against queues. only half-searches have to be
|
|
||||||
// done at this stage
|
|
||||||
void ComputeLengthAndSharingOfViaPath(const FacadeT &facade,
|
|
||||||
const NodeID via_node,
|
|
||||||
int *real_length_of_via_path,
|
|
||||||
int *sharing_of_via_path,
|
|
||||||
const std::vector<NodeID> &packed_shortest_path,
|
|
||||||
const EdgeWeight min_edge_offset);
|
|
||||||
|
|
||||||
// todo: reorder parameters
|
|
||||||
template <bool is_forward_directed>
|
|
||||||
void AlternativeRoutingStep(const FacadeT &facade,
|
|
||||||
QueryHeap &heap1,
|
|
||||||
QueryHeap &heap2,
|
|
||||||
NodeID *middle_node,
|
|
||||||
EdgeWeight *upper_bound_to_shortest_path_weight,
|
|
||||||
std::vector<NodeID> &search_space_intersection,
|
|
||||||
std::vector<SearchSpaceEdge> &search_space,
|
|
||||||
const EdgeWeight min_edge_offset) const
|
|
||||||
{
|
|
||||||
QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2);
|
|
||||||
QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1);
|
|
||||||
|
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
|
||||||
const EdgeWeight weight = forward_heap.GetKey(node);
|
|
||||||
// const NodeID parentnode = forward_heap.GetData(node).parent;
|
|
||||||
// util::Log() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled
|
|
||||||
// edge ("
|
|
||||||
// << parentnode << "," << node << "), dist: " << weight;
|
|
||||||
|
|
||||||
const auto scaled_weight =
|
|
||||||
static_cast<EdgeWeight>((weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
|
||||||
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
|
|
||||||
(scaled_weight > *upper_bound_to_shortest_path_weight))
|
|
||||||
{
|
|
||||||
forward_heap.DeleteAll();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
search_space.emplace_back(forward_heap.GetData(node).parent, node);
|
|
||||||
|
|
||||||
if (reverse_heap.WasInserted(node))
|
|
||||||
{
|
|
||||||
search_space_intersection.emplace_back(node);
|
|
||||||
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
|
||||||
if (new_weight < *upper_bound_to_shortest_path_weight)
|
|
||||||
{
|
|
||||||
if (new_weight >= 0)
|
|
||||||
{
|
|
||||||
*middle_node = node;
|
|
||||||
*upper_bound_to_shortest_path_weight = new_weight;
|
|
||||||
// util::Log() << "accepted middle_node " << *middle_node
|
|
||||||
// << " at
|
|
||||||
// weight " << new_weight;
|
|
||||||
// } else {
|
|
||||||
// util::Log() << "discarded middle_node " << *middle_node
|
|
||||||
// << "
|
|
||||||
// at weight " << new_weight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// check whether there is a loop present at the node
|
|
||||||
const auto loop_weight = super::GetLoopWeight<false>(facade, node);
|
|
||||||
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
|
||||||
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
|
||||||
{
|
|
||||||
*middle_node = node;
|
|
||||||
*upper_bound_to_shortest_path_weight = loop_weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
const bool edge_is_forward_directed =
|
|
||||||
(is_forward_directed ? data.forward : data.backward);
|
|
||||||
if (edge_is_forward_directed)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
|
|
||||||
BOOST_ASSERT(edge_weight > 0);
|
|
||||||
const EdgeWeight to_weight = weight + edge_weight;
|
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if (!forward_heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
forward_heap.Insert(to, to_weight, node);
|
|
||||||
}
|
|
||||||
// Found a shorter Path -> Update weight
|
|
||||||
else if (to_weight < forward_heap.GetKey(to))
|
|
||||||
{
|
|
||||||
// new parent
|
|
||||||
forward_heap.GetData(to).parent = node;
|
|
||||||
// decreased weight
|
|
||||||
forward_heap.DecreaseKey(to, to_weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// conduct T-Test
|
|
||||||
bool ViaNodeCandidatePassesTTest(const FacadeT &facade,
|
|
||||||
QueryHeap &existing_forward_heap,
|
|
||||||
QueryHeap &existing_reverse_heap,
|
|
||||||
QueryHeap &new_forward_heap,
|
|
||||||
QueryHeap &new_reverse_heap,
|
|
||||||
const RankedCandidateNode &candidate,
|
|
||||||
const int length_of_shortest_path,
|
|
||||||
int *length_of_via_path,
|
|
||||||
NodeID *s_v_middle,
|
|
||||||
NodeID *v_t_middle,
|
|
||||||
const EdgeWeight min_edge_offset) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|
||||||
#endif /* ALTERNATIVE_PATH_ROUTING_HPP */
|
#endif
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#ifndef DIRECT_SHORTEST_PATH_HPP
|
#ifndef DIRECT_SHORTEST_PATH_HPP
|
||||||
#define DIRECT_SHORTEST_PATH_HPP
|
#define DIRECT_SHORTEST_PATH_HPP
|
||||||
|
|
||||||
#include "engine/routing_algorithms/routing_base.hpp"
|
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
|
#include "engine/internal_route_result.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -14,34 +15,16 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename AlgorithmT> class DirectShortestPathRouting;
|
|
||||||
|
|
||||||
/// 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
|
||||||
/// necessary in case of vias, where the directions of the start node is constrainted
|
/// necessary in case of vias, where the directions of the start node is constrainted
|
||||||
/// by the previous route.
|
/// by the previous route.
|
||||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||||
/// not fully contracted graphs.
|
/// not fully contracted graphs.
|
||||||
template <>
|
InternalRouteResult directShortestPathSearch(
|
||||||
class DirectShortestPathRouting<algorithm::CH> final : public BasicRouting<algorithm::CH>
|
SearchEngineData &engine_working_data,
|
||||||
{
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
using super = BasicRouting<algorithm::CH>;
|
const std::vector<PhantomNodes> &phantom_nodes_vector);
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
using QueryHeap = SearchEngineData::QueryHeap;
|
|
||||||
SearchEngineData &engine_working_data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DirectShortestPathRouting(SearchEngineData &engine_working_data)
|
|
||||||
: engine_working_data(engine_working_data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~DirectShortestPathRouting() {}
|
|
||||||
|
|
||||||
void operator()(const FacadeT &facade,
|
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
|
||||||
InternalRouteResult &raw_route_data) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -1,138 +1,28 @@
|
|||||||
#ifndef MANY_TO_MANY_ROUTING_HPP
|
#ifndef MANY_TO_MANY_ROUTING_HPP
|
||||||
#define MANY_TO_MANY_ROUTING_HPP
|
#define MANY_TO_MANY_ROUTING_HPP
|
||||||
|
|
||||||
#include "engine/routing_algorithms/routing_base.hpp"
|
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename AlgorithmT> class ManyToManyRouting;
|
std::vector<EdgeWeight>
|
||||||
|
manyToManySearch(SearchEngineData &engine_working_data,
|
||||||
template <> class ManyToManyRouting<algorithm::CH> final : public BasicRouting<algorithm::CH>
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
{
|
|
||||||
using super = BasicRouting<algorithm::CH>;
|
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
using QueryHeap = SearchEngineData::ManyToManyQueryHeap;
|
|
||||||
SearchEngineData &engine_working_data;
|
|
||||||
|
|
||||||
struct NodeBucket
|
|
||||||
{
|
|
||||||
unsigned target_id; // essentially a row in the weight matrix
|
|
||||||
EdgeWeight weight;
|
|
||||||
EdgeWeight duration;
|
|
||||||
NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration)
|
|
||||||
: target_id(target_id), weight(weight), duration(duration)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
|
|
||||||
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ManyToManyRouting(SearchEngineData &engine_working_data)
|
|
||||||
: engine_working_data(engine_working_data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<EdgeWeight> operator()(const FacadeT &facade,
|
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const;
|
const std::vector<std::size_t> &target_indices);
|
||||||
|
|
||||||
void ForwardRoutingStep(const FacadeT &facade,
|
|
||||||
const unsigned row_idx,
|
|
||||||
const unsigned number_of_targets,
|
|
||||||
QueryHeap &query_heap,
|
|
||||||
const SearchSpaceWithBuckets &search_space_with_buckets,
|
|
||||||
std::vector<EdgeWeight> &weights_table,
|
|
||||||
std::vector<EdgeWeight> &durations_table) const;
|
|
||||||
|
|
||||||
void BackwardRoutingStep(const FacadeT &facade,
|
|
||||||
const unsigned column_idx,
|
|
||||||
QueryHeap &query_heap,
|
|
||||||
SearchSpaceWithBuckets &search_space_with_buckets) const;
|
|
||||||
|
|
||||||
template <bool forward_direction>
|
|
||||||
inline void RelaxOutgoingEdges(const FacadeT &facade,
|
|
||||||
const NodeID node,
|
|
||||||
const EdgeWeight weight,
|
|
||||||
const EdgeWeight duration,
|
|
||||||
QueryHeap &query_heap) const
|
|
||||||
{
|
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
const bool direction_flag = (forward_direction ? data.forward : data.backward);
|
|
||||||
if (direction_flag)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
const EdgeWeight edge_duration = data.duration;
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
|
||||||
const EdgeWeight to_weight = weight + edge_weight;
|
|
||||||
const EdgeWeight to_duration = duration + edge_duration;
|
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if (!query_heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
query_heap.Insert(to, to_weight, {node, to_duration});
|
|
||||||
}
|
|
||||||
// Found a shorter Path -> Update weight
|
|
||||||
else if (to_weight < query_heap.GetKey(to))
|
|
||||||
{
|
|
||||||
// new parent
|
|
||||||
query_heap.GetData(to) = {node, to_duration};
|
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stalling
|
|
||||||
template <bool forward_direction>
|
|
||||||
inline bool StallAtNode(const FacadeT &facade,
|
|
||||||
const NodeID node,
|
|
||||||
const EdgeWeight weight,
|
|
||||||
QueryHeap &query_heap) const
|
|
||||||
{
|
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
|
||||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
|
||||||
if (reverse_flag)
|
|
||||||
{
|
|
||||||
const NodeID to = facade.GetTarget(edge);
|
|
||||||
const EdgeWeight edge_weight = data.weight;
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
|
||||||
if (query_heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
if (query_heap.GetKey(to) + edge_weight < weight)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -1,25 +1,11 @@
|
|||||||
#ifndef MAP_MATCHING_HPP
|
#ifndef MAP_MATCHING_HPP
|
||||||
#define MAP_MATCHING_HPP
|
#define MAP_MATCHING_HPP
|
||||||
|
|
||||||
#include "engine/routing_algorithms/routing_base.hpp"
|
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
#include "engine/map_matching/hidden_markov_model.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
#include "engine/map_matching/matching_confidence.hpp"
|
|
||||||
#include "engine/map_matching/sub_matching.hpp"
|
#include "engine/map_matching/sub_matching.hpp"
|
||||||
|
#include "engine/search_engine_data.hpp"
|
||||||
|
|
||||||
#include "extractor/profile_properties.hpp"
|
|
||||||
#include "util/coordinate_calculation.hpp"
|
|
||||||
#include "util/for_each_pair.hpp"
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <deque>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <memory>
|
|
||||||
#include <numeric>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -31,45 +17,16 @@ namespace routing_algorithms
|
|||||||
|
|
||||||
using CandidateList = std::vector<PhantomNodeWithDistance>;
|
using CandidateList = std::vector<PhantomNodeWithDistance>;
|
||||||
using CandidateLists = std::vector<CandidateList>;
|
using CandidateLists = std::vector<CandidateList>;
|
||||||
using HMM = map_matching::HiddenMarkovModel<CandidateLists>;
|
|
||||||
using SubMatchingList = std::vector<map_matching::SubMatching>;
|
using SubMatchingList = std::vector<map_matching::SubMatching>;
|
||||||
|
|
||||||
constexpr static const unsigned MAX_BROKEN_STATES = 10;
|
|
||||||
static const constexpr double MATCHING_BETA = 10;
|
|
||||||
constexpr static const double MAX_DISTANCE_DELTA = 2000.;
|
|
||||||
static const constexpr double DEFAULT_GPS_PRECISION = 5;
|
static const constexpr double DEFAULT_GPS_PRECISION = 5;
|
||||||
|
|
||||||
template <typename AlgorithmT> class MapMatching;
|
|
||||||
|
|
||||||
// implements a hidden markov model map matching algorithm
|
|
||||||
template <> class MapMatching<algorithm::CH> final : public BasicRouting<algorithm::CH>
|
|
||||||
{
|
|
||||||
using super = BasicRouting<algorithm::CH>;
|
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
using QueryHeap = SearchEngineData::QueryHeap;
|
|
||||||
SearchEngineData &engine_working_data;
|
|
||||||
map_matching::EmissionLogProbability default_emission_log_probability;
|
|
||||||
map_matching::TransitionLogProbability transition_log_probability;
|
|
||||||
map_matching::MatchingConfidence confidence;
|
|
||||||
extractor::ProfileProperties m_profile_properties;
|
|
||||||
|
|
||||||
unsigned GetMedianSampleTime(const std::vector<unsigned> ×tamps) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MapMatching(SearchEngineData &engine_working_data)
|
|
||||||
: engine_working_data(engine_working_data),
|
|
||||||
default_emission_log_probability(DEFAULT_GPS_PRECISION),
|
|
||||||
transition_log_probability(MATCHING_BETA)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SubMatchingList
|
SubMatchingList
|
||||||
operator()(const FacadeT &facade,
|
mapMatching(SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const CandidateLists &candidates_list,
|
const CandidateLists &candidates_list,
|
||||||
const std::vector<util::Coordinate> &trace_coordinates,
|
const std::vector<util::Coordinate> &trace_coordinates,
|
||||||
const std::vector<unsigned> &trace_timestamps,
|
const std::vector<unsigned> &trace_timestamps,
|
||||||
const std::vector<boost::optional<double>> &trace_gps_precision) const;
|
const std::vector<boost::optional<double>> &trace_gps_precision);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
#include "engine/edge_unpacker.hpp"
|
|
||||||
#include "engine/internal_route_result.hpp"
|
#include "engine/internal_route_result.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
|
|
||||||
@ -35,17 +34,6 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename AlgorithmT> class BasicRouting;
|
|
||||||
|
|
||||||
// TODO: There is no reason these functions are contained in a class other then for namespace
|
|
||||||
// purposes. This should be a namespace with free functions.
|
|
||||||
template <> class BasicRouting<algorithm::CH>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
using EdgeData = typename FacadeT::EdgeData;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
/*
|
||||||
min_edge_offset is needed in case we use multiple
|
min_edge_offset is needed in case we use multiple
|
||||||
nodes as start/target nodes with different (even negative) offsets.
|
nodes as start/target nodes with different (even negative) offsets.
|
||||||
@ -75,7 +63,7 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
Since we are dealing with a graph that contains _negative_ edges,
|
Since we are dealing with a graph that contains _negative_ edges,
|
||||||
we need to add an offset to the termination criterion.
|
we need to add an offset to the termination criterion.
|
||||||
*/
|
*/
|
||||||
void RoutingStep(const FacadeT &facade,
|
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
NodeID &middle_node_id,
|
NodeID &middle_node_id,
|
||||||
@ -84,9 +72,12 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
const bool forward_direction,
|
const bool forward_direction,
|
||||||
const bool stalling,
|
const bool stalling,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse) const;
|
const bool force_loop_reverse);
|
||||||
|
|
||||||
template <bool UseDuration> EdgeWeight GetLoopWeight(const FacadeT &facade, NodeID node) const
|
template <bool UseDuration>
|
||||||
|
EdgeWeight
|
||||||
|
getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
NodeID node)
|
||||||
{
|
{
|
||||||
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
@ -105,12 +96,97 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
return loop_weight;
|
return loop_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename RandomIter>
|
/**
|
||||||
void UnpackPath(const FacadeT &facade,
|
* 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.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, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_begin,
|
||||||
RandomIter packed_path_end,
|
RandomIter packed_path_end,
|
||||||
const PhantomNodes &phantom_node_pair,
|
const PhantomNodes &phantom_node_pair,
|
||||||
std::vector<PathData> &unpacked_path) const
|
std::vector<PathData> &unpacked_path)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0);
|
BOOST_ASSERT(std::distance(packed_path_begin, packed_path_end) > 0);
|
||||||
|
|
||||||
@ -125,17 +201,16 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
*std::prev(packed_path_end) == phantom_node_pair.target_phantom.forward_segment_id.id ||
|
*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);
|
*std::prev(packed_path_end) == phantom_node_pair.target_phantom.reverse_segment_id.id);
|
||||||
|
|
||||||
UnpackCHPath(
|
unpackPath(
|
||||||
facade,
|
facade,
|
||||||
packed_path_begin,
|
packed_path_begin,
|
||||||
packed_path_end,
|
packed_path_end,
|
||||||
[this,
|
[&facade,
|
||||||
&facade,
|
|
||||||
&unpacked_path,
|
&unpacked_path,
|
||||||
&phantom_node_pair,
|
&phantom_node_pair,
|
||||||
&start_traversed_in_reverse,
|
&start_traversed_in_reverse,
|
||||||
&target_traversed_in_reverse](std::pair<NodeID, NodeID> & /* edge */,
|
&target_traversed_in_reverse](std::pair<NodeID, NodeID> & /* edge */,
|
||||||
const EdgeData &edge_data) {
|
const auto &edge_data) {
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(!edge_data.shortcut, "original edge flagged as shortcut");
|
BOOST_ASSERT_MSG(!edge_data.shortcut, "original edge flagged as shortcut");
|
||||||
const auto name_index = facade.GetNameIndexFromEdgeID(edge_data.id);
|
const auto name_index = facade.GetNameIndexFromEdgeID(edge_data.id);
|
||||||
@ -184,8 +259,7 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
BOOST_ASSERT(start_index < end_index);
|
BOOST_ASSERT(start_index < end_index);
|
||||||
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
||||||
{
|
{
|
||||||
unpacked_path.push_back(
|
unpacked_path.push_back(PathData{id_vector[segment_idx + 1],
|
||||||
PathData{id_vector[segment_idx + 1],
|
|
||||||
name_index,
|
name_index,
|
||||||
weight_vector[segment_idx],
|
weight_vector[segment_idx],
|
||||||
duration_vector[segment_idx],
|
duration_vector[segment_idx],
|
||||||
@ -236,8 +310,8 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
|
|
||||||
if (is_local_path)
|
if (is_local_path)
|
||||||
{
|
{
|
||||||
start_index = weight_vector.size() -
|
start_index =
|
||||||
phantom_node_pair.source_phantom.fwd_segment_position - 1;
|
weight_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1;
|
||||||
}
|
}
|
||||||
end_index =
|
end_index =
|
||||||
weight_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
|
weight_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
|
||||||
@ -343,19 +417,19 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
* @param to the node the CH edge finishes 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
|
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
|
||||||
*/
|
*/
|
||||||
void UnpackEdge(const FacadeT &facade,
|
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const NodeID from,
|
const NodeID from,
|
||||||
const NodeID to,
|
const NodeID to,
|
||||||
std::vector<NodeID> &unpacked_path) const;
|
std::vector<NodeID> &unpacked_path);
|
||||||
|
|
||||||
void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
|
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
|
||||||
const SearchEngineData::QueryHeap &reverse_heap,
|
const SearchEngineData::QueryHeap &reverse_heap,
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> &packed_path) const;
|
std::vector<NodeID> &packed_path);
|
||||||
|
|
||||||
void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
|
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> &packed_path) const;
|
std::vector<NodeID> &packed_path);
|
||||||
|
|
||||||
// assumes that heaps are already setup correctly.
|
// assumes that heaps are already setup correctly.
|
||||||
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
|
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
|
||||||
@ -369,14 +443,14 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void Search(const FacadeT &facade,
|
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
std::int32_t &weight,
|
std::int32_t &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT) const;
|
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
// assumes that heaps are already setup correctly.
|
// assumes that heaps are already setup correctly.
|
||||||
// A forced loop might be necessary, if source and target are on the same segment.
|
// A forced loop might be necessary, if source and target are on the same segment.
|
||||||
@ -387,7 +461,7 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void SearchWithCore(const FacadeT &facade,
|
void searchWithCore(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
SearchEngineData::QueryHeap &forward_core_heap,
|
SearchEngineData::QueryHeap &forward_core_heap,
|
||||||
@ -396,41 +470,40 @@ template <> class BasicRouting<algorithm::CH>
|
|||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT) const;
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
bool NeedsLoopForward(const PhantomNode &source_phantom,
|
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
const PhantomNode &target_phantom) const;
|
|
||||||
|
|
||||||
bool NeedsLoopBackwards(const PhantomNode &source_phantom,
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
const PhantomNode &target_phantom) const;
|
|
||||||
|
|
||||||
double GetPathDistance(const FacadeT &facade,
|
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const std::vector<NodeID> &packed_path,
|
const std::vector<NodeID> &packed_path,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom) const;
|
const PhantomNode &target_phantom);
|
||||||
|
|
||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double GetNetworkDistanceWithCore(const FacadeT &facade,
|
double getNetworkDistanceWithCore(
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
SearchEngineData::QueryHeap &forward_core_heap,
|
SearchEngineData::QueryHeap &forward_core_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT) const;
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double GetNetworkDistance(const FacadeT &facade,
|
double
|
||||||
|
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT) const;
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -4,13 +4,8 @@
|
|||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
#include "engine/routing_algorithms/routing_base.hpp"
|
#include "engine/routing_algorithms/routing_base.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
#include "util/integer_range.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
@ -18,75 +13,12 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename AlgorithmT> class ShortestPathRouting;
|
InternalRouteResult
|
||||||
|
shortestPathSearch(SearchEngineData &engine_working_data,
|
||||||
template <> class ShortestPathRouting<algorithm::CH> final : public BasicRouting<algorithm::CH>
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
{
|
|
||||||
using super = BasicRouting<algorithm::CH>;
|
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
using QueryHeap = SearchEngineData::QueryHeap;
|
|
||||||
SearchEngineData &engine_working_data;
|
|
||||||
const static constexpr bool DO_NOT_FORCE_LOOP = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ShortestPathRouting(SearchEngineData &engine_working_data)
|
|
||||||
: engine_working_data(engine_working_data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~ShortestPathRouting() {}
|
|
||||||
|
|
||||||
// allows a uturn at the target_phantom
|
|
||||||
// searches source forward/reverse -> target forward/reverse
|
|
||||||
void SearchWithUTurn(const FacadeT &facade,
|
|
||||||
QueryHeap &forward_heap,
|
|
||||||
QueryHeap &reverse_heap,
|
|
||||||
QueryHeap &forward_core_heap,
|
|
||||||
QueryHeap &reverse_core_heap,
|
|
||||||
const bool search_from_forward_node,
|
|
||||||
const bool search_from_reverse_node,
|
|
||||||
const bool search_to_forward_node,
|
|
||||||
const bool search_to_reverse_node,
|
|
||||||
const PhantomNode &source_phantom,
|
|
||||||
const PhantomNode &target_phantom,
|
|
||||||
const int total_weight_to_forward,
|
|
||||||
const int total_weight_to_reverse,
|
|
||||||
int &new_total_weight,
|
|
||||||
std::vector<NodeID> &leg_packed_path) const;
|
|
||||||
|
|
||||||
// searches shortest path between:
|
|
||||||
// source forward/reverse -> target forward
|
|
||||||
// source forward/reverse -> target reverse
|
|
||||||
void Search(const FacadeT &facade,
|
|
||||||
QueryHeap &forward_heap,
|
|
||||||
QueryHeap &reverse_heap,
|
|
||||||
QueryHeap &forward_core_heap,
|
|
||||||
QueryHeap &reverse_core_heap,
|
|
||||||
const bool search_from_forward_node,
|
|
||||||
const bool search_from_reverse_node,
|
|
||||||
const bool search_to_forward_node,
|
|
||||||
const bool search_to_reverse_node,
|
|
||||||
const PhantomNode &source_phantom,
|
|
||||||
const PhantomNode &target_phantom,
|
|
||||||
const int total_weight_to_forward,
|
|
||||||
const int total_weight_to_reverse,
|
|
||||||
int &new_total_weight_to_forward,
|
|
||||||
int &new_total_weight_to_reverse,
|
|
||||||
std::vector<NodeID> &leg_packed_path_forward,
|
|
||||||
std::vector<NodeID> &leg_packed_path_reverse) const;
|
|
||||||
|
|
||||||
void UnpackLegs(const FacadeT &facade,
|
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const std::vector<NodeID> &total_packed_path,
|
const boost::optional<bool> continue_straight_at_waypoint);
|
||||||
const std::vector<std::size_t> &packed_leg_begin,
|
|
||||||
const int shortest_path_length,
|
|
||||||
InternalRouteResult &raw_route_data) const;
|
|
||||||
|
|
||||||
void operator()(const FacadeT &facade,
|
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
|
||||||
const boost::optional<bool> continue_straight_at_waypoint,
|
|
||||||
InternalRouteResult &raw_route_data) const;
|
|
||||||
};
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#ifndef OSRM_ENGINE_ROUTING_ALGORITHMS_TILE_TURNS_HPP
|
#ifndef OSRM_ENGINE_ROUTING_ALGORITHMS_TILE_TURNS_HPP
|
||||||
#define OSRM_ENGINE_ROUTING_ALGORITHMS_TILE_TURNS_HPP
|
#define OSRM_ENGINE_ROUTING_ALGORITHMS_TILE_TURNS_HPP
|
||||||
|
|
||||||
#include "engine/routing_algorithms/routing_base.hpp"
|
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
|
|
||||||
|
#include "util/coordinate.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
@ -14,8 +16,6 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename AlgorithmT> class TileTurns;
|
|
||||||
|
|
||||||
// Used to accumulate all the information we want in the tile about a turn.
|
// Used to accumulate all the information we want in the tile about a turn.
|
||||||
struct TurnData final
|
struct TurnData final
|
||||||
{
|
{
|
||||||
@ -25,19 +25,12 @@ struct TurnData final
|
|||||||
const int weight;
|
const int weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class is used to extract turn information for the tile plugin from a CH graph
|
|
||||||
template <> class TileTurns<algorithm::CH> final : public BasicRouting<algorithm::CH>
|
|
||||||
{
|
|
||||||
using super = BasicRouting<algorithm::CH>;
|
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>;
|
|
||||||
|
|
||||||
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
||||||
|
|
||||||
public:
|
std::vector<TurnData>
|
||||||
std::vector<TurnData> operator()(const FacadeT &facade,
|
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const std::vector<RTreeLeaf> &edges,
|
const std::vector<RTreeLeaf> &edges,
|
||||||
const std::vector<std::size_t> &sorted_edge_indexes) const;
|
const std::vector<std::size_t> &sorted_edge_indexes);
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -208,8 +208,8 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
|||||||
// force uturns to be on, since we split the phantom nodes anyway and only have
|
// force uturns to be on, since we split the phantom nodes anyway and only have
|
||||||
// bi-directional
|
// bi-directional
|
||||||
// phantom nodes for possible uturns
|
// phantom nodes for possible uturns
|
||||||
algorithms.ShortestRouting(
|
sub_routes[index] =
|
||||||
sub_routes[index].segment_end_coordinates, {false}, sub_routes[index]);
|
algorithms.ShortestRouting(sub_routes[index].segment_end_coordinates, {false});
|
||||||
BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT);
|
BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "engine/plugins/tile.hpp"
|
#include "engine/plugins/tile.hpp"
|
||||||
#include "engine/edge_unpacker.hpp"
|
|
||||||
#include "engine/plugins/plugin_base.hpp"
|
#include "engine/plugins/plugin_base.hpp"
|
||||||
|
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
@ -85,7 +85,7 @@ InternalRouteResult TripPlugin::ComputeRoute(const RoutingAlgorithmsInterface &a
|
|||||||
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size() - 1);
|
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
algorithms.ShortestRouting(min_route.segment_end_coordinates, {false}, min_route);
|
min_route = algorithms.ShortestRouting(min_route.segment_end_coordinates, {false});
|
||||||
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
|
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
|
||||||
return min_route;
|
return min_route;
|
||||||
}
|
}
|
||||||
|
@ -89,17 +89,17 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca
|
|||||||
{
|
{
|
||||||
if (route_parameters.alternatives && algorithms.HasAlternativeRouting())
|
if (route_parameters.alternatives && algorithms.HasAlternativeRouting())
|
||||||
{
|
{
|
||||||
algorithms.AlternativeRouting(raw_route.segment_end_coordinates.front(), raw_route);
|
raw_route = algorithms.AlternativeRouting(raw_route.segment_end_coordinates.front());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
algorithms.DirectShortestPathRouting(raw_route.segment_end_coordinates, raw_route);
|
raw_route = algorithms.DirectShortestPathRouting(raw_route.segment_end_coordinates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
algorithms.ShortestRouting(
|
raw_route = algorithms.ShortestRouting(raw_route.segment_end_coordinates,
|
||||||
raw_route.segment_end_coordinates, route_parameters.continue_straight, raw_route);
|
route_parameters.continue_straight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can only know this after the fact, different SCC ids still
|
// we can only know this after the fact, different SCC ids still
|
||||||
|
@ -1,4 +1,17 @@
|
|||||||
#include "engine/routing_algorithms/alternative_path.hpp"
|
#include "engine/routing_algorithms/alternative_path.hpp"
|
||||||
|
#include "engine/routing_algorithms/routing_base.hpp"
|
||||||
|
|
||||||
|
#include "util/integer_range.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -7,335 +20,131 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
void AlternativeRouting<algorithm::CH>::operator()(const FacadeT &facade,
|
namespace
|
||||||
const PhantomNodes &phantom_node_pair,
|
|
||||||
InternalRouteResult &raw_route_data)
|
|
||||||
{
|
{
|
||||||
std::vector<NodeID> alternative_path;
|
const double constexpr VIAPATH_ALPHA = 0.10;
|
||||||
std::vector<NodeID> via_node_candidate_list;
|
const double constexpr VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
|
||||||
std::vector<SearchSpaceEdge> forward_search_space;
|
const double constexpr VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
|
||||||
std::vector<SearchSpaceEdge> reverse_search_space;
|
|
||||||
|
|
||||||
// Init queues, semi-expensive because access to TSS invokes a sys-call
|
using QueryHeap = SearchEngineData::QueryHeap;
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
using SearchSpaceEdge = std::pair<NodeID, NodeID>;
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
|
||||||
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes());
|
|
||||||
|
|
||||||
QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1);
|
struct RankedCandidateNode
|
||||||
QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1);
|
|
||||||
QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2);
|
|
||||||
QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2);
|
|
||||||
|
|
||||||
EdgeWeight upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT;
|
|
||||||
NodeID middle_node = SPECIAL_NODEID;
|
|
||||||
const EdgeWeight min_edge_offset =
|
|
||||||
std::min(phantom_node_pair.source_phantom.forward_segment_id.enabled
|
|
||||||
? -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()
|
|
||||||
: 0,
|
|
||||||
phantom_node_pair.source_phantom.reverse_segment_id.enabled
|
|
||||||
? -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
if (phantom_node_pair.source_phantom.forward_segment_id.enabled)
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID);
|
RankedCandidateNode(const NodeID node, const int length, const int sharing)
|
||||||
forward_heap1.Insert(phantom_node_pair.source_phantom.forward_segment_id.id,
|
: node(node), length(length), sharing(sharing)
|
||||||
-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)
|
NodeID node;
|
||||||
{
|
int length;
|
||||||
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id != SPECIAL_SEGMENTID);
|
int sharing;
|
||||||
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
|
bool operator<(const RankedCandidateNode &other) const
|
||||||
while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
|
|
||||||
{
|
{
|
||||||
if (0 < forward_heap1.Size())
|
return (2 * length + sharing) < (2 * other.length + other.sharing);
|
||||||
{
|
|
||||||
AlternativeRoutingStep<true>(facade,
|
|
||||||
forward_heap1,
|
|
||||||
reverse_heap1,
|
|
||||||
&middle_node,
|
|
||||||
&upper_bound_to_shortest_path_weight,
|
|
||||||
via_node_candidate_list,
|
|
||||||
forward_search_space,
|
|
||||||
min_edge_offset);
|
|
||||||
}
|
|
||||||
if (0 < reverse_heap1.Size())
|
|
||||||
{
|
|
||||||
AlternativeRoutingStep<false>(facade,
|
|
||||||
forward_heap1,
|
|
||||||
reverse_heap1,
|
|
||||||
&middle_node,
|
|
||||||
&upper_bound_to_shortest_path_weight,
|
|
||||||
via_node_candidate_list,
|
|
||||||
reverse_search_space,
|
|
||||||
min_edge_offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_weight)
|
// todo: reorder parameters
|
||||||
|
template <bool is_forward_directed>
|
||||||
|
void alternativeRoutingStep(
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
QueryHeap &heap1,
|
||||||
|
QueryHeap &heap2,
|
||||||
|
NodeID *middle_node,
|
||||||
|
EdgeWeight *upper_bound_to_shortest_path_weight,
|
||||||
|
std::vector<NodeID> &search_space_intersection,
|
||||||
|
std::vector<SearchSpaceEdge> &search_space,
|
||||||
|
const EdgeWeight min_edge_offset)
|
||||||
{
|
{
|
||||||
|
QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2);
|
||||||
|
QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1);
|
||||||
|
|
||||||
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
|
const EdgeWeight weight = forward_heap.GetKey(node);
|
||||||
|
|
||||||
|
const auto scaled_weight =
|
||||||
|
static_cast<EdgeWeight>((weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
||||||
|
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
|
||||||
|
(scaled_weight > *upper_bound_to_shortest_path_weight))
|
||||||
|
{
|
||||||
|
forward_heap.DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(begin(via_node_candidate_list), end(via_node_candidate_list));
|
search_space.emplace_back(forward_heap.GetData(node).parent, node);
|
||||||
auto unique_end = std::unique(begin(via_node_candidate_list), end(via_node_candidate_list));
|
|
||||||
via_node_candidate_list.resize(unique_end - begin(via_node_candidate_list));
|
|
||||||
|
|
||||||
std::vector<NodeID> packed_forward_path;
|
if (reverse_heap.WasInserted(node))
|
||||||
std::vector<NodeID> packed_reverse_path;
|
|
||||||
|
|
||||||
const bool path_is_a_loop =
|
|
||||||
upper_bound_to_shortest_path_weight !=
|
|
||||||
forward_heap1.GetKey(middle_node) + reverse_heap1.GetKey(middle_node);
|
|
||||||
if (path_is_a_loop)
|
|
||||||
{
|
{
|
||||||
// Self Loop
|
search_space_intersection.emplace_back(node);
|
||||||
packed_forward_path.push_back(middle_node);
|
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
||||||
packed_forward_path.push_back(middle_node);
|
if (new_weight < *upper_bound_to_shortest_path_weight)
|
||||||
|
{
|
||||||
|
if (new_weight >= 0)
|
||||||
|
{
|
||||||
|
*middle_node = node;
|
||||||
|
*upper_bound_to_shortest_path_weight = new_weight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// check whether there is a loop present at the node
|
||||||
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
|
const auto loop_weight = getLoopWeight<false>(facade, node);
|
||||||
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
}
|
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
||||||
|
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
||||||
// this set is is used as an indicator if a node is on the shortest path
|
|
||||||
std::unordered_set<NodeID> nodes_in_path(packed_forward_path.size() +
|
|
||||||
packed_reverse_path.size());
|
|
||||||
nodes_in_path.insert(packed_forward_path.begin(), packed_forward_path.end());
|
|
||||||
nodes_in_path.insert(middle_node);
|
|
||||||
nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end());
|
|
||||||
|
|
||||||
std::unordered_map<NodeID, int> approximated_forward_sharing;
|
|
||||||
std::unordered_map<NodeID, int> approximated_reverse_sharing;
|
|
||||||
|
|
||||||
// sweep over search space, compute forward sharing for each current edge (u,v)
|
|
||||||
for (const SearchSpaceEdge ¤t_edge : forward_search_space)
|
|
||||||
{
|
{
|
||||||
const NodeID u = current_edge.first;
|
*middle_node = node;
|
||||||
const NodeID v = current_edge.second;
|
*upper_bound_to_shortest_path_weight = loop_weight;
|
||||||
|
|
||||||
if (nodes_in_path.find(v) != nodes_in_path.end())
|
|
||||||
{
|
|
||||||
// current_edge is on shortest path => sharing(v):=queue.GetKey(v);
|
|
||||||
approximated_forward_sharing.emplace(v, forward_heap1.GetKey(v));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// current edge is not on shortest path. Check if we know a value for the other
|
|
||||||
// endpoint
|
|
||||||
const auto sharing_of_u_iterator = approximated_forward_sharing.find(u);
|
|
||||||
if (sharing_of_u_iterator != approximated_forward_sharing.end())
|
|
||||||
{
|
|
||||||
approximated_forward_sharing.emplace(v, sharing_of_u_iterator->second);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sweep over search space, compute backward sharing
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
for (const SearchSpaceEdge ¤t_edge : reverse_search_space)
|
|
||||||
{
|
{
|
||||||
const NodeID u = current_edge.first;
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
const NodeID v = current_edge.second;
|
const bool edge_is_forward_directed = (is_forward_directed ? data.forward : data.backward);
|
||||||
if (nodes_in_path.find(v) != nodes_in_path.end())
|
if (edge_is_forward_directed)
|
||||||
{
|
{
|
||||||
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
approximated_reverse_sharing.emplace(v, reverse_heap1.GetKey(v));
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
|
BOOST_ASSERT(edge_weight > 0);
|
||||||
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
|
||||||
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if (!forward_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
forward_heap.Insert(to, to_weight, node);
|
||||||
}
|
}
|
||||||
else
|
// Found a shorter Path -> Update weight
|
||||||
|
else if (to_weight < forward_heap.GetKey(to))
|
||||||
{
|
{
|
||||||
// current edge is not on shortest path. Check if we know a value for the other
|
// new parent
|
||||||
// endpoint
|
forward_heap.GetData(to).parent = node;
|
||||||
const auto sharing_of_u_iterator = approximated_reverse_sharing.find(u);
|
// decreased weight
|
||||||
if (sharing_of_u_iterator != approximated_reverse_sharing.end())
|
forward_heap.DecreaseKey(to, to_weight);
|
||||||
{
|
}
|
||||||
approximated_reverse_sharing.emplace(v, sharing_of_u_iterator->second);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// util::Log(logDEBUG) << "fwd_search_space size: " <<
|
void retrievePackedAlternatePath(const QueryHeap &forward_heap1,
|
||||||
// forward_search_space.size() << ", marked " << approximated_forward_sharing.size() << "
|
|
||||||
// nodes";
|
|
||||||
// util::Log(logDEBUG) << "rev_search_space size: " <<
|
|
||||||
// reverse_search_space.size() << ", marked " << approximated_reverse_sharing.size() << "
|
|
||||||
// nodes";
|
|
||||||
|
|
||||||
std::vector<NodeID> preselected_node_list;
|
|
||||||
for (const NodeID node : via_node_candidate_list)
|
|
||||||
{
|
|
||||||
if (node == middle_node)
|
|
||||||
continue;
|
|
||||||
const auto fwd_iterator = approximated_forward_sharing.find(node);
|
|
||||||
const int fwd_sharing =
|
|
||||||
(fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
|
|
||||||
const auto rev_iterator = approximated_reverse_sharing.find(node);
|
|
||||||
const int rev_sharing =
|
|
||||||
(rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
|
|
||||||
|
|
||||||
const int approximated_sharing = fwd_sharing + rev_sharing;
|
|
||||||
const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
|
|
||||||
const bool length_passes =
|
|
||||||
(approximated_length < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON));
|
|
||||||
const bool sharing_passes =
|
|
||||||
(approximated_sharing <= upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
|
|
||||||
const bool stretch_passes =
|
|
||||||
(approximated_length - approximated_sharing) <
|
|
||||||
((1. + VIAPATH_ALPHA) * (upper_bound_to_shortest_path_weight - approximated_sharing));
|
|
||||||
|
|
||||||
if (length_passes && sharing_passes && stretch_passes)
|
|
||||||
{
|
|
||||||
preselected_node_list.emplace_back(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<NodeID> &packed_shortest_path = packed_forward_path;
|
|
||||||
if (!path_is_a_loop)
|
|
||||||
{
|
|
||||||
std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
|
|
||||||
packed_shortest_path.emplace_back(middle_node);
|
|
||||||
packed_shortest_path.insert(
|
|
||||||
packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end());
|
|
||||||
}
|
|
||||||
std::vector<RankedCandidateNode> ranked_candidates_list;
|
|
||||||
|
|
||||||
// prioritizing via nodes for deep inspection
|
|
||||||
for (const NodeID node : preselected_node_list)
|
|
||||||
{
|
|
||||||
int length_of_via_path = 0, sharing_of_via_path = 0;
|
|
||||||
ComputeLengthAndSharingOfViaPath(facade,
|
|
||||||
node,
|
|
||||||
&length_of_via_path,
|
|
||||||
&sharing_of_via_path,
|
|
||||||
packed_shortest_path,
|
|
||||||
min_edge_offset);
|
|
||||||
const int maximum_allowed_sharing =
|
|
||||||
static_cast<int>(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
|
|
||||||
if (sharing_of_via_path <= maximum_allowed_sharing &&
|
|
||||||
length_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON))
|
|
||||||
{
|
|
||||||
ranked_candidates_list.emplace_back(node, length_of_via_path, sharing_of_via_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(ranked_candidates_list.begin(), ranked_candidates_list.end());
|
|
||||||
|
|
||||||
NodeID selected_via_node = SPECIAL_NODEID;
|
|
||||||
int length_of_via_path = INVALID_EDGE_WEIGHT;
|
|
||||||
NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID;
|
|
||||||
for (const RankedCandidateNode &candidate : ranked_candidates_list)
|
|
||||||
{
|
|
||||||
if (ViaNodeCandidatePassesTTest(facade,
|
|
||||||
forward_heap1,
|
|
||||||
reverse_heap1,
|
|
||||||
forward_heap2,
|
|
||||||
reverse_heap2,
|
|
||||||
candidate,
|
|
||||||
upper_bound_to_shortest_path_weight,
|
|
||||||
&length_of_via_path,
|
|
||||||
&s_v_middle,
|
|
||||||
&v_t_middle,
|
|
||||||
min_edge_offset))
|
|
||||||
{
|
|
||||||
// select first admissable
|
|
||||||
selected_via_node = candidate.node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unpack shortest path and alternative, if they exist
|
|
||||||
if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_weight)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(!packed_shortest_path.empty());
|
|
||||||
raw_route_data.unpacked_path_segments.resize(1);
|
|
||||||
raw_route_data.source_traversed_in_reverse.push_back(
|
|
||||||
(packed_shortest_path.front() !=
|
|
||||||
phantom_node_pair.source_phantom.forward_segment_id.id));
|
|
||||||
raw_route_data.target_traversed_in_reverse.push_back((
|
|
||||||
packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
|
|
||||||
|
|
||||||
super::UnpackPath(facade,
|
|
||||||
// -- packed input
|
|
||||||
packed_shortest_path.begin(),
|
|
||||||
packed_shortest_path.end(),
|
|
||||||
// -- start of route
|
|
||||||
phantom_node_pair,
|
|
||||||
// -- unpacked output
|
|
||||||
raw_route_data.unpacked_path_segments.front());
|
|
||||||
raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SPECIAL_NODEID != selected_via_node)
|
|
||||||
{
|
|
||||||
std::vector<NodeID> packed_alternate_path;
|
|
||||||
// retrieve alternate path
|
|
||||||
RetrievePackedAlternatePath(forward_heap1,
|
|
||||||
reverse_heap1,
|
|
||||||
forward_heap2,
|
|
||||||
reverse_heap2,
|
|
||||||
s_v_middle,
|
|
||||||
v_t_middle,
|
|
||||||
packed_alternate_path);
|
|
||||||
|
|
||||||
raw_route_data.alt_source_traversed_in_reverse.push_back(
|
|
||||||
(packed_alternate_path.front() !=
|
|
||||||
phantom_node_pair.source_phantom.forward_segment_id.id));
|
|
||||||
raw_route_data.alt_target_traversed_in_reverse.push_back(
|
|
||||||
(packed_alternate_path.back() !=
|
|
||||||
phantom_node_pair.target_phantom.forward_segment_id.id));
|
|
||||||
|
|
||||||
// unpack the alternate path
|
|
||||||
super::UnpackPath(facade,
|
|
||||||
packed_alternate_path.begin(),
|
|
||||||
packed_alternate_path.end(),
|
|
||||||
phantom_node_pair,
|
|
||||||
raw_route_data.unpacked_alternative);
|
|
||||||
|
|
||||||
raw_route_data.alternative_path_length = length_of_via_path;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlternativeRouting<algorithm::CH>::RetrievePackedAlternatePath(
|
|
||||||
const QueryHeap &forward_heap1,
|
|
||||||
const QueryHeap &reverse_heap1,
|
const QueryHeap &reverse_heap1,
|
||||||
const QueryHeap &forward_heap2,
|
const QueryHeap &forward_heap2,
|
||||||
const QueryHeap &reverse_heap2,
|
const QueryHeap &reverse_heap2,
|
||||||
const NodeID s_v_middle,
|
const NodeID s_v_middle,
|
||||||
const NodeID v_t_middle,
|
const NodeID v_t_middle,
|
||||||
std::vector<NodeID> &packed_path) const
|
std::vector<NodeID> &packed_path)
|
||||||
{
|
{
|
||||||
// fetch packed path [s,v)
|
// fetch packed path [s,v)
|
||||||
std::vector<NodeID> packed_v_t_path;
|
std::vector<NodeID> packed_v_t_path;
|
||||||
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path);
|
retrievePackedPathFromHeap(forward_heap1, reverse_heap2, s_v_middle, packed_path);
|
||||||
packed_path.pop_back(); // remove middle node. It's in both half-paths
|
packed_path.pop_back(); // remove middle node. It's in both half-paths
|
||||||
|
|
||||||
// fetch patched path [v,t]
|
// fetch patched path [v,t]
|
||||||
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path);
|
retrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path);
|
||||||
|
|
||||||
packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end());
|
packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end());
|
||||||
}
|
}
|
||||||
@ -344,8 +153,9 @@ void AlternativeRouting<algorithm::CH>::RetrievePackedAlternatePath(
|
|||||||
// compute and unpack <s,..,v> and <v,..,t> by exploring search spaces
|
// compute and unpack <s,..,v> and <v,..,t> by exploring search spaces
|
||||||
// from v and intersecting against queues. only half-searches have to be
|
// from v and intersecting against queues. only half-searches have to be
|
||||||
// done at this stage
|
// done at this stage
|
||||||
void AlternativeRouting<algorithm::CH>::ComputeLengthAndSharingOfViaPath(
|
void computeLengthAndSharingOfViaPath(
|
||||||
const FacadeT &facade,
|
SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const NodeID via_node,
|
const NodeID via_node,
|
||||||
int *real_length_of_via_path,
|
int *real_length_of_via_path,
|
||||||
int *sharing_of_via_path,
|
int *sharing_of_via_path,
|
||||||
@ -373,7 +183,7 @@ void AlternativeRouting<algorithm::CH>::ComputeLengthAndSharingOfViaPath(
|
|||||||
const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
||||||
while (!new_reverse_heap.Empty())
|
while (!new_reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
super::RoutingStep(facade,
|
routingStep(facade,
|
||||||
new_reverse_heap,
|
new_reverse_heap,
|
||||||
existing_forward_heap,
|
existing_forward_heap,
|
||||||
s_v_middle,
|
s_v_middle,
|
||||||
@ -390,7 +200,7 @@ void AlternativeRouting<algorithm::CH>::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())
|
||||||
{
|
{
|
||||||
super::RoutingStep(facade,
|
routingStep(facade,
|
||||||
new_forward_heap,
|
new_forward_heap,
|
||||||
existing_reverse_heap,
|
existing_reverse_heap,
|
||||||
v_t_middle,
|
v_t_middle,
|
||||||
@ -409,9 +219,9 @@ void AlternativeRouting<algorithm::CH>::ComputeLengthAndSharingOfViaPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// retrieve packed paths
|
// retrieve packed paths
|
||||||
super::RetrievePackedPathFromHeap(
|
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);
|
||||||
super::RetrievePackedPathFromHeap(
|
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
|
||||||
@ -431,11 +241,11 @@ void AlternativeRouting<algorithm::CH>::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])
|
||||||
{
|
{
|
||||||
super::UnpackEdge(facade,
|
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);
|
||||||
super::UnpackEdge(facade,
|
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);
|
||||||
@ -477,11 +287,11 @@ void AlternativeRouting<algorithm::CH>::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])
|
||||||
{
|
{
|
||||||
super::UnpackEdge(facade,
|
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);
|
||||||
super::UnpackEdge(facade,
|
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);
|
||||||
@ -514,8 +324,9 @@ void AlternativeRouting<algorithm::CH>::ComputeLengthAndSharingOfViaPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// conduct T-Test
|
// conduct T-Test
|
||||||
bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
bool viaNodeCandidatePassesTTest(
|
||||||
const FacadeT &facade,
|
SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
QueryHeap &existing_forward_heap,
|
QueryHeap &existing_forward_heap,
|
||||||
QueryHeap &existing_reverse_heap,
|
QueryHeap &existing_reverse_heap,
|
||||||
QueryHeap &new_forward_heap,
|
QueryHeap &new_forward_heap,
|
||||||
@ -525,7 +336,7 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
int *length_of_via_path,
|
int *length_of_via_path,
|
||||||
NodeID *s_v_middle,
|
NodeID *s_v_middle,
|
||||||
NodeID *v_t_middle,
|
NodeID *v_t_middle,
|
||||||
const EdgeWeight min_edge_offset) const
|
const EdgeWeight min_edge_offset)
|
||||||
{
|
{
|
||||||
new_forward_heap.Clear();
|
new_forward_heap.Clear();
|
||||||
new_reverse_heap.Clear();
|
new_reverse_heap.Clear();
|
||||||
@ -540,7 +351,7 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
const bool constexpr DO_NOT_FORCE_LOOPS = false;
|
||||||
while (new_reverse_heap.Size() > 0)
|
while (new_reverse_heap.Size() > 0)
|
||||||
{
|
{
|
||||||
super::RoutingStep(facade,
|
routingStep(facade,
|
||||||
new_reverse_heap,
|
new_reverse_heap,
|
||||||
existing_forward_heap,
|
existing_forward_heap,
|
||||||
*s_v_middle,
|
*s_v_middle,
|
||||||
@ -563,7 +374,7 @@ bool AlternativeRouting<algorithm::CH>::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)
|
||||||
{
|
{
|
||||||
super::RoutingStep(facade,
|
routingStep(facade,
|
||||||
new_forward_heap,
|
new_forward_heap,
|
||||||
existing_reverse_heap,
|
existing_reverse_heap,
|
||||||
*v_t_middle,
|
*v_t_middle,
|
||||||
@ -583,10 +394,10 @@ bool AlternativeRouting<algorithm::CH>::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
|
||||||
super::RetrievePackedPathFromHeap(
|
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);
|
||||||
|
|
||||||
super::RetrievePackedPathFromHeap(
|
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;
|
||||||
@ -632,7 +443,7 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeData ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id);
|
const auto ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id);
|
||||||
const bool current_edge_is_shortcut = current_edge_data.shortcut;
|
const bool current_edge_is_shortcut = current_edge_data.shortcut;
|
||||||
if (current_edge_is_shortcut)
|
if (current_edge_is_shortcut)
|
||||||
{
|
{
|
||||||
@ -694,7 +505,7 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeData ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id);
|
const auto ¤t_edge_data = facade.GetEdgeData(edge_in_via_path_id);
|
||||||
const bool IsViaEdgeShortCut = current_edge_data.shortcut;
|
const bool IsViaEdgeShortCut = current_edge_data.shortcut;
|
||||||
if (IsViaEdgeShortCut)
|
if (IsViaEdgeShortCut)
|
||||||
{
|
{
|
||||||
@ -738,7 +549,7 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
{
|
{
|
||||||
if (!forward_heap3.Empty())
|
if (!forward_heap3.Empty())
|
||||||
{
|
{
|
||||||
super::RoutingStep(facade,
|
routingStep(facade,
|
||||||
forward_heap3,
|
forward_heap3,
|
||||||
reverse_heap3,
|
reverse_heap3,
|
||||||
middle,
|
middle,
|
||||||
@ -751,7 +562,7 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
}
|
}
|
||||||
if (!reverse_heap3.Empty())
|
if (!reverse_heap3.Empty())
|
||||||
{
|
{
|
||||||
super::RoutingStep(facade,
|
routingStep(facade,
|
||||||
reverse_heap3,
|
reverse_heap3,
|
||||||
forward_heap3,
|
forward_heap3,
|
||||||
middle,
|
middle,
|
||||||
@ -765,6 +576,319 @@ bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
|
|||||||
}
|
}
|
||||||
return (upper_bound <= t_test_path_length);
|
return (upper_bound <= t_test_path_length);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalRouteResult
|
||||||
|
alternativePathSearch(SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const PhantomNodes &phantom_node_pair)
|
||||||
|
{
|
||||||
|
InternalRouteResult raw_route_data;
|
||||||
|
std::vector<NodeID> alternative_path;
|
||||||
|
std::vector<NodeID> via_node_candidate_list;
|
||||||
|
std::vector<SearchSpaceEdge> forward_search_space;
|
||||||
|
std::vector<SearchSpaceEdge> reverse_search_space;
|
||||||
|
|
||||||
|
// Init queues, semi-expensive because access to TSS invokes a sys-call
|
||||||
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
|
||||||
|
QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1);
|
||||||
|
QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1);
|
||||||
|
QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2);
|
||||||
|
QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2);
|
||||||
|
|
||||||
|
EdgeWeight upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT;
|
||||||
|
NodeID middle_node = SPECIAL_NODEID;
|
||||||
|
const EdgeWeight min_edge_offset =
|
||||||
|
std::min(phantom_node_pair.source_phantom.forward_segment_id.enabled
|
||||||
|
? -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()
|
||||||
|
: 0,
|
||||||
|
phantom_node_pair.source_phantom.reverse_segment_id.enabled
|
||||||
|
? -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()
|
||||||
|
: 0);
|
||||||
|
|
||||||
|
if (phantom_node_pair.source_phantom.forward_segment_id.enabled)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID);
|
||||||
|
forward_heap1.Insert(phantom_node_pair.source_phantom.forward_segment_id.id,
|
||||||
|
-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||||
|
phantom_node_pair.source_phantom.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
if (phantom_node_pair.source_phantom.reverse_segment_id.enabled)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(phantom_node_pair.source_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID);
|
||||||
|
forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_segment_id.id,
|
||||||
|
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||||
|
phantom_node_pair.source_phantom.reverse_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phantom_node_pair.target_phantom.forward_segment_id.enabled)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id != SPECIAL_SEGMENTID);
|
||||||
|
reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_segment_id.id,
|
||||||
|
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
||||||
|
phantom_node_pair.target_phantom.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
if (phantom_node_pair.target_phantom.reverse_segment_id.enabled)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(phantom_node_pair.target_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID);
|
||||||
|
reverse_heap1.Insert(phantom_node_pair.target_phantom.reverse_segment_id.id,
|
||||||
|
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
|
||||||
|
phantom_node_pair.target_phantom.reverse_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// search from s and t till new_min/(1+epsilon) > length_of_shortest_path
|
||||||
|
while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
|
||||||
|
{
|
||||||
|
if (0 < forward_heap1.Size())
|
||||||
|
{
|
||||||
|
alternativeRoutingStep<true>(facade,
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
&middle_node,
|
||||||
|
&upper_bound_to_shortest_path_weight,
|
||||||
|
via_node_candidate_list,
|
||||||
|
forward_search_space,
|
||||||
|
min_edge_offset);
|
||||||
|
}
|
||||||
|
if (0 < reverse_heap1.Size())
|
||||||
|
{
|
||||||
|
alternativeRoutingStep<false>(facade,
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
&middle_node,
|
||||||
|
&upper_bound_to_shortest_path_weight,
|
||||||
|
via_node_candidate_list,
|
||||||
|
reverse_search_space,
|
||||||
|
min_edge_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_weight)
|
||||||
|
{
|
||||||
|
return raw_route_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(begin(via_node_candidate_list), end(via_node_candidate_list));
|
||||||
|
auto unique_end = std::unique(begin(via_node_candidate_list), end(via_node_candidate_list));
|
||||||
|
via_node_candidate_list.resize(unique_end - begin(via_node_candidate_list));
|
||||||
|
|
||||||
|
std::vector<NodeID> packed_forward_path;
|
||||||
|
std::vector<NodeID> packed_reverse_path;
|
||||||
|
|
||||||
|
const bool path_is_a_loop =
|
||||||
|
upper_bound_to_shortest_path_weight !=
|
||||||
|
forward_heap1.GetKey(middle_node) + reverse_heap1.GetKey(middle_node);
|
||||||
|
if (path_is_a_loop)
|
||||||
|
{
|
||||||
|
// Self Loop
|
||||||
|
packed_forward_path.push_back(middle_node);
|
||||||
|
packed_forward_path.push_back(middle_node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
retrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
|
||||||
|
retrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this set is is used as an indicator if a node is on the shortest path
|
||||||
|
std::unordered_set<NodeID> nodes_in_path(packed_forward_path.size() +
|
||||||
|
packed_reverse_path.size());
|
||||||
|
nodes_in_path.insert(packed_forward_path.begin(), packed_forward_path.end());
|
||||||
|
nodes_in_path.insert(middle_node);
|
||||||
|
nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end());
|
||||||
|
|
||||||
|
std::unordered_map<NodeID, int> approximated_forward_sharing;
|
||||||
|
std::unordered_map<NodeID, int> approximated_reverse_sharing;
|
||||||
|
|
||||||
|
// sweep over search space, compute forward sharing for each current edge (u,v)
|
||||||
|
for (const SearchSpaceEdge ¤t_edge : forward_search_space)
|
||||||
|
{
|
||||||
|
const NodeID u = current_edge.first;
|
||||||
|
const NodeID v = current_edge.second;
|
||||||
|
|
||||||
|
if (nodes_in_path.find(v) != nodes_in_path.end())
|
||||||
|
{
|
||||||
|
// current_edge is on shortest path => sharing(v):=queue.GetKey(v);
|
||||||
|
approximated_forward_sharing.emplace(v, forward_heap1.GetKey(v));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// current edge is not on shortest path. Check if we know a value for the other
|
||||||
|
// endpoint
|
||||||
|
const auto sharing_of_u_iterator = approximated_forward_sharing.find(u);
|
||||||
|
if (sharing_of_u_iterator != approximated_forward_sharing.end())
|
||||||
|
{
|
||||||
|
approximated_forward_sharing.emplace(v, sharing_of_u_iterator->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sweep over search space, compute backward sharing
|
||||||
|
for (const SearchSpaceEdge ¤t_edge : reverse_search_space)
|
||||||
|
{
|
||||||
|
const NodeID u = current_edge.first;
|
||||||
|
const NodeID v = current_edge.second;
|
||||||
|
if (nodes_in_path.find(v) != nodes_in_path.end())
|
||||||
|
{
|
||||||
|
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
||||||
|
approximated_reverse_sharing.emplace(v, reverse_heap1.GetKey(v));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// current edge is not on shortest path. Check if we know a value for the other
|
||||||
|
// endpoint
|
||||||
|
const auto sharing_of_u_iterator = approximated_reverse_sharing.find(u);
|
||||||
|
if (sharing_of_u_iterator != approximated_reverse_sharing.end())
|
||||||
|
{
|
||||||
|
approximated_reverse_sharing.emplace(v, sharing_of_u_iterator->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<NodeID> preselected_node_list;
|
||||||
|
for (const NodeID node : via_node_candidate_list)
|
||||||
|
{
|
||||||
|
if (node == middle_node)
|
||||||
|
continue;
|
||||||
|
const auto fwd_iterator = approximated_forward_sharing.find(node);
|
||||||
|
const int fwd_sharing =
|
||||||
|
(fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
|
||||||
|
const auto rev_iterator = approximated_reverse_sharing.find(node);
|
||||||
|
const int rev_sharing =
|
||||||
|
(rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
|
||||||
|
|
||||||
|
const int approximated_sharing = fwd_sharing + rev_sharing;
|
||||||
|
const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
|
||||||
|
const bool length_passes =
|
||||||
|
(approximated_length < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON));
|
||||||
|
const bool sharing_passes =
|
||||||
|
(approximated_sharing <= upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
|
||||||
|
const bool stretch_passes =
|
||||||
|
(approximated_length - approximated_sharing) <
|
||||||
|
((1. + VIAPATH_ALPHA) * (upper_bound_to_shortest_path_weight - approximated_sharing));
|
||||||
|
|
||||||
|
if (length_passes && sharing_passes && stretch_passes)
|
||||||
|
{
|
||||||
|
preselected_node_list.emplace_back(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<NodeID> &packed_shortest_path = packed_forward_path;
|
||||||
|
if (!path_is_a_loop)
|
||||||
|
{
|
||||||
|
std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
|
||||||
|
packed_shortest_path.emplace_back(middle_node);
|
||||||
|
packed_shortest_path.insert(
|
||||||
|
packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end());
|
||||||
|
}
|
||||||
|
std::vector<RankedCandidateNode> ranked_candidates_list;
|
||||||
|
|
||||||
|
// prioritizing via nodes for deep inspection
|
||||||
|
for (const NodeID node : preselected_node_list)
|
||||||
|
{
|
||||||
|
int length_of_via_path = 0, sharing_of_via_path = 0;
|
||||||
|
computeLengthAndSharingOfViaPath(engine_working_data,
|
||||||
|
facade,
|
||||||
|
node,
|
||||||
|
&length_of_via_path,
|
||||||
|
&sharing_of_via_path,
|
||||||
|
packed_shortest_path,
|
||||||
|
min_edge_offset);
|
||||||
|
const int maximum_allowed_sharing =
|
||||||
|
static_cast<int>(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
|
||||||
|
if (sharing_of_via_path <= maximum_allowed_sharing &&
|
||||||
|
length_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON))
|
||||||
|
{
|
||||||
|
ranked_candidates_list.emplace_back(node, length_of_via_path, sharing_of_via_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(ranked_candidates_list.begin(), ranked_candidates_list.end());
|
||||||
|
|
||||||
|
NodeID selected_via_node = SPECIAL_NODEID;
|
||||||
|
int length_of_via_path = INVALID_EDGE_WEIGHT;
|
||||||
|
NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID;
|
||||||
|
for (const RankedCandidateNode &candidate : ranked_candidates_list)
|
||||||
|
{
|
||||||
|
if (viaNodeCandidatePassesTTest(engine_working_data,
|
||||||
|
facade,
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
forward_heap2,
|
||||||
|
reverse_heap2,
|
||||||
|
candidate,
|
||||||
|
upper_bound_to_shortest_path_weight,
|
||||||
|
&length_of_via_path,
|
||||||
|
&s_v_middle,
|
||||||
|
&v_t_middle,
|
||||||
|
min_edge_offset))
|
||||||
|
{
|
||||||
|
// select first admissable
|
||||||
|
selected_via_node = candidate.node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpack shortest path and alternative, if they exist
|
||||||
|
if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_weight)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!packed_shortest_path.empty());
|
||||||
|
raw_route_data.unpacked_path_segments.resize(1);
|
||||||
|
raw_route_data.source_traversed_in_reverse.push_back(
|
||||||
|
(packed_shortest_path.front() !=
|
||||||
|
phantom_node_pair.source_phantom.forward_segment_id.id));
|
||||||
|
raw_route_data.target_traversed_in_reverse.push_back((
|
||||||
|
packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
|
||||||
|
|
||||||
|
unpackPath(facade,
|
||||||
|
// -- packed input
|
||||||
|
packed_shortest_path.begin(),
|
||||||
|
packed_shortest_path.end(),
|
||||||
|
// -- start of route
|
||||||
|
phantom_node_pair,
|
||||||
|
// -- unpacked output
|
||||||
|
raw_route_data.unpacked_path_segments.front());
|
||||||
|
raw_route_data.shortest_path_length = upper_bound_to_shortest_path_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SPECIAL_NODEID != selected_via_node)
|
||||||
|
{
|
||||||
|
std::vector<NodeID> packed_alternate_path;
|
||||||
|
// retrieve alternate path
|
||||||
|
retrievePackedAlternatePath(forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
forward_heap2,
|
||||||
|
reverse_heap2,
|
||||||
|
s_v_middle,
|
||||||
|
v_t_middle,
|
||||||
|
packed_alternate_path);
|
||||||
|
|
||||||
|
raw_route_data.alt_source_traversed_in_reverse.push_back(
|
||||||
|
(packed_alternate_path.front() !=
|
||||||
|
phantom_node_pair.source_phantom.forward_segment_id.id));
|
||||||
|
raw_route_data.alt_target_traversed_in_reverse.push_back(
|
||||||
|
(packed_alternate_path.back() !=
|
||||||
|
phantom_node_pair.target_phantom.forward_segment_id.id));
|
||||||
|
|
||||||
|
// unpack the alternate path
|
||||||
|
unpackPath(facade,
|
||||||
|
packed_alternate_path.begin(),
|
||||||
|
packed_alternate_path.end(),
|
||||||
|
phantom_node_pair,
|
||||||
|
raw_route_data.unpacked_alternative);
|
||||||
|
|
||||||
|
raw_route_data.alternative_path_length = length_of_via_path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw_route_data;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -1,5 +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"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
@ -13,11 +15,12 @@ namespace routing_algorithms
|
|||||||
/// by the previous route.
|
/// by the previous route.
|
||||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||||
/// not fully contracted graphs.
|
/// not fully contracted graphs.
|
||||||
void DirectShortestPathRouting<algorithm::CH>::
|
InternalRouteResult directShortestPathSearch(
|
||||||
operator()(const FacadeT &facade,
|
SearchEngineData &engine_working_data,
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
InternalRouteResult &raw_route_data) const
|
const std::vector<PhantomNodes> &phantom_nodes_vector)
|
||||||
{
|
{
|
||||||
|
InternalRouteResult raw_route_data;
|
||||||
// Get weight to next pair of target nodes.
|
// Get weight to next pair of target nodes.
|
||||||
BOOST_ASSERT_MSG(1 == phantom_nodes_vector.size(),
|
BOOST_ASSERT_MSG(1 == phantom_nodes_vector.size(),
|
||||||
"Direct Shortest Path Query only accepts a single source and target pair. "
|
"Direct Shortest Path Query only accepts a single source and target pair. "
|
||||||
@ -27,8 +30,8 @@ operator()(const FacadeT &facade,
|
|||||||
const auto &target_phantom = phantom_node_pair.target_phantom;
|
const auto &target_phantom = phantom_node_pair.target_phantom;
|
||||||
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
|
auto &forward_heap = *(engine_working_data.forward_heap_1);
|
||||||
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);
|
auto &reverse_heap = *(engine_working_data.reverse_heap_1);
|
||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
|
|
||||||
@ -71,12 +74,12 @@ operator()(const FacadeT &facade,
|
|||||||
if (facade.GetCoreSize() > 0)
|
if (facade.GetCoreSize() > 0)
|
||||||
{
|
{
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2);
|
auto &forward_core_heap = *(engine_working_data.forward_heap_2);
|
||||||
QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2);
|
auto &reverse_core_heap = *(engine_working_data.reverse_heap_2);
|
||||||
forward_core_heap.Clear();
|
forward_core_heap.Clear();
|
||||||
reverse_core_heap.Clear();
|
reverse_core_heap.Clear();
|
||||||
|
|
||||||
super::SearchWithCore(facade,
|
searchWithCore(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
@ -88,7 +91,7 @@ operator()(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
super::Search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
weight,
|
weight,
|
||||||
@ -102,7 +105,7 @@ operator()(const FacadeT &facade,
|
|||||||
{
|
{
|
||||||
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
|
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
|
||||||
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
|
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
|
||||||
return;
|
return raw_route_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty");
|
BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty");
|
||||||
@ -114,11 +117,13 @@ operator()(const FacadeT &facade,
|
|||||||
raw_route_data.target_traversed_in_reverse.push_back(
|
raw_route_data.target_traversed_in_reverse.push_back(
|
||||||
(packed_leg.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
|
(packed_leg.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
|
||||||
|
|
||||||
super::UnpackPath(facade,
|
unpackPath(facade,
|
||||||
packed_leg.begin(),
|
packed_leg.begin(),
|
||||||
packed_leg.end(),
|
packed_leg.end(),
|
||||||
phantom_node_pair,
|
phantom_node_pair,
|
||||||
raw_route_data.unpacked_path_segments.front());
|
raw_route_data.unpacked_path_segments.front());
|
||||||
|
|
||||||
|
return raw_route_data;
|
||||||
}
|
}
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
#include "engine/routing_algorithms/many_to_many.hpp"
|
#include "engine/routing_algorithms/many_to_many.hpp"
|
||||||
|
#include "engine/routing_algorithms/routing_base.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -7,11 +15,172 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<EdgeWeight> ManyToManyRouting<algorithm::CH>::
|
using QueryHeap = SearchEngineData::ManyToManyQueryHeap;
|
||||||
operator()(const FacadeT &facade,
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct NodeBucket
|
||||||
|
{
|
||||||
|
unsigned target_id; // essentially a row in the weight matrix
|
||||||
|
EdgeWeight weight;
|
||||||
|
EdgeWeight duration;
|
||||||
|
NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration)
|
||||||
|
: target_id(target_id), weight(weight), duration(duration)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
|
||||||
|
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
||||||
|
|
||||||
|
template <bool forward_direction>
|
||||||
|
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const NodeID node,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
QueryHeap &query_heap)
|
||||||
|
{
|
||||||
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
|
const bool direction_flag = (forward_direction ? data.forward : data.backward);
|
||||||
|
if (direction_flag)
|
||||||
|
{
|
||||||
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
const EdgeWeight edge_duration = data.duration;
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
const EdgeWeight to_duration = duration + edge_duration;
|
||||||
|
|
||||||
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if (!query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
query_heap.Insert(to, to_weight, {node, to_duration});
|
||||||
|
}
|
||||||
|
// Found a shorter Path -> Update weight
|
||||||
|
else if (to_weight < query_heap.GetKey(to))
|
||||||
|
{
|
||||||
|
// new parent
|
||||||
|
query_heap.GetData(to) = {node, to_duration};
|
||||||
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stalling
|
||||||
|
template <bool forward_direction>
|
||||||
|
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const NodeID node,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
QueryHeap &query_heap)
|
||||||
|
{
|
||||||
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
|
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||||
|
if (reverse_flag)
|
||||||
|
{
|
||||||
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
if (query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
if (query_heap.GetKey(to) + edge_weight < weight)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const unsigned row_idx,
|
||||||
|
const unsigned number_of_targets,
|
||||||
|
QueryHeap &query_heap,
|
||||||
|
const SearchSpaceWithBuckets &search_space_with_buckets,
|
||||||
|
std::vector<EdgeWeight> &weights_table,
|
||||||
|
std::vector<EdgeWeight> &durations_table)
|
||||||
|
{
|
||||||
|
const NodeID node = query_heap.DeleteMin();
|
||||||
|
const EdgeWeight source_weight = query_heap.GetKey(node);
|
||||||
|
const EdgeWeight source_duration = query_heap.GetData(node).duration;
|
||||||
|
|
||||||
|
// check if each encountered node has an entry
|
||||||
|
const auto bucket_iterator = search_space_with_buckets.find(node);
|
||||||
|
// iterate bucket if there exists one
|
||||||
|
if (bucket_iterator != search_space_with_buckets.end())
|
||||||
|
{
|
||||||
|
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
|
||||||
|
for (const NodeBucket ¤t_bucket : bucket_list)
|
||||||
|
{
|
||||||
|
// get target id from bucket entry
|
||||||
|
const unsigned column_idx = current_bucket.target_id;
|
||||||
|
const EdgeWeight target_weight = current_bucket.weight;
|
||||||
|
const EdgeWeight target_duration = current_bucket.duration;
|
||||||
|
|
||||||
|
auto ¤t_weight = weights_table[row_idx * number_of_targets + column_idx];
|
||||||
|
auto ¤t_duration = durations_table[row_idx * number_of_targets + column_idx];
|
||||||
|
|
||||||
|
// check if new weight is better
|
||||||
|
const EdgeWeight new_weight = source_weight + target_weight;
|
||||||
|
if (new_weight < 0)
|
||||||
|
{
|
||||||
|
const EdgeWeight loop_weight = getLoopWeight<false>(facade, node);
|
||||||
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
|
if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0)
|
||||||
|
{
|
||||||
|
current_weight = std::min(current_weight, new_weight_with_loop);
|
||||||
|
current_duration = std::min(current_duration,
|
||||||
|
source_duration + target_duration +
|
||||||
|
getLoopWeight<true>(facade, node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (new_weight < current_weight)
|
||||||
|
{
|
||||||
|
current_weight = new_weight;
|
||||||
|
current_duration = source_duration + target_duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stallAtNode<true>(facade, node, source_weight, query_heap))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
relaxOutgoingEdges<true>(facade, node, source_weight, source_duration, query_heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backwardRoutingStep(
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
|
const unsigned column_idx,
|
||||||
|
QueryHeap &query_heap,
|
||||||
|
SearchSpaceWithBuckets &search_space_with_buckets)
|
||||||
|
{
|
||||||
|
const NodeID node = query_heap.DeleteMin();
|
||||||
|
const EdgeWeight target_weight = query_heap.GetKey(node);
|
||||||
|
const EdgeWeight target_duration = query_heap.GetData(node).duration;
|
||||||
|
|
||||||
|
// store settled nodes in search space bucket
|
||||||
|
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
|
||||||
|
|
||||||
|
if (stallAtNode<false>(facade, node, target_weight, query_heap))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
relaxOutgoingEdges<false>(facade, node, target_weight, target_duration, query_heap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<EdgeWeight>
|
||||||
|
manyToManySearch(SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const
|
const std::vector<std::size_t> &target_indices)
|
||||||
{
|
{
|
||||||
const auto number_of_sources =
|
const auto number_of_sources =
|
||||||
source_indices.empty() ? phantom_nodes.size() : source_indices.size();
|
source_indices.empty() ? phantom_nodes.size() : source_indices.size();
|
||||||
@ -24,7 +193,7 @@ operator()(const FacadeT &facade,
|
|||||||
|
|
||||||
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
|
||||||
QueryHeap &query_heap = *(engine_working_data.many_to_many_heap);
|
auto &query_heap = *(engine_working_data.many_to_many_heap);
|
||||||
|
|
||||||
SearchSpaceWithBuckets search_space_with_buckets;
|
SearchSpaceWithBuckets search_space_with_buckets;
|
||||||
|
|
||||||
@ -49,7 +218,7 @@ operator()(const FacadeT &facade,
|
|||||||
// explore search space
|
// explore search space
|
||||||
while (!query_heap.Empty())
|
while (!query_heap.Empty())
|
||||||
{
|
{
|
||||||
BackwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets);
|
backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets);
|
||||||
}
|
}
|
||||||
++column_idx;
|
++column_idx;
|
||||||
};
|
};
|
||||||
@ -122,84 +291,6 @@ operator()(const FacadeT &facade,
|
|||||||
return durations_table;
|
return durations_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManyToManyRouting<algorithm::CH>::ForwardRoutingStep(
|
|
||||||
const FacadeT &facade,
|
|
||||||
const unsigned row_idx,
|
|
||||||
const unsigned number_of_targets,
|
|
||||||
QueryHeap &query_heap,
|
|
||||||
const SearchSpaceWithBuckets &search_space_with_buckets,
|
|
||||||
std::vector<EdgeWeight> &weights_table,
|
|
||||||
std::vector<EdgeWeight> &durations_table) const
|
|
||||||
{
|
|
||||||
const NodeID node = query_heap.DeleteMin();
|
|
||||||
const EdgeWeight source_weight = query_heap.GetKey(node);
|
|
||||||
const EdgeWeight source_duration = query_heap.GetData(node).duration;
|
|
||||||
|
|
||||||
// check if each encountered node has an entry
|
|
||||||
const auto bucket_iterator = search_space_with_buckets.find(node);
|
|
||||||
// iterate bucket if there exists one
|
|
||||||
if (bucket_iterator != search_space_with_buckets.end())
|
|
||||||
{
|
|
||||||
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
|
|
||||||
for (const NodeBucket ¤t_bucket : bucket_list)
|
|
||||||
{
|
|
||||||
// get target id from bucket entry
|
|
||||||
const unsigned column_idx = current_bucket.target_id;
|
|
||||||
const EdgeWeight target_weight = current_bucket.weight;
|
|
||||||
const EdgeWeight target_duration = current_bucket.duration;
|
|
||||||
|
|
||||||
auto ¤t_weight = weights_table[row_idx * number_of_targets + column_idx];
|
|
||||||
auto ¤t_duration = durations_table[row_idx * number_of_targets + column_idx];
|
|
||||||
|
|
||||||
// check if new weight is better
|
|
||||||
const EdgeWeight new_weight = source_weight + target_weight;
|
|
||||||
if (new_weight < 0)
|
|
||||||
{
|
|
||||||
const EdgeWeight loop_weight = super::GetLoopWeight<false>(facade, node);
|
|
||||||
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0)
|
|
||||||
{
|
|
||||||
current_weight = std::min(current_weight, new_weight_with_loop);
|
|
||||||
current_duration = std::min(current_duration,
|
|
||||||
source_duration + target_duration +
|
|
||||||
super::GetLoopWeight<true>(facade, node));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (new_weight < current_weight)
|
|
||||||
{
|
|
||||||
current_weight = new_weight;
|
|
||||||
current_duration = source_duration + target_duration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (StallAtNode<true>(facade, node, source_weight, query_heap))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RelaxOutgoingEdges<true>(facade, node, source_weight, source_duration, query_heap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManyToManyRouting<algorithm::CH>::BackwardRoutingStep(
|
|
||||||
const FacadeT &facade,
|
|
||||||
const unsigned column_idx,
|
|
||||||
QueryHeap &query_heap,
|
|
||||||
SearchSpaceWithBuckets &search_space_with_buckets) const
|
|
||||||
{
|
|
||||||
const NodeID node = query_heap.DeleteMin();
|
|
||||||
const EdgeWeight target_weight = query_heap.GetKey(node);
|
|
||||||
const EdgeWeight target_duration = query_heap.GetData(node).duration;
|
|
||||||
|
|
||||||
// store settled nodes in search space bucket
|
|
||||||
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
|
|
||||||
|
|
||||||
if (StallAtNode<false>(facade, node, target_weight, query_heap))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaxOutgoingEdges<false>(facade, node, target_weight, target_duration, query_heap);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -1,4 +1,20 @@
|
|||||||
#include "engine/routing_algorithms/map_matching.hpp"
|
#include "engine/routing_algorithms/map_matching.hpp"
|
||||||
|
#include "engine/routing_algorithms/routing_base.hpp"
|
||||||
|
|
||||||
|
#include "engine/map_matching/hidden_markov_model.hpp"
|
||||||
|
#include "engine/map_matching/matching_confidence.hpp"
|
||||||
|
#include "engine/map_matching/sub_matching.hpp"
|
||||||
|
|
||||||
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
#include "util/for_each_pair.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <deque>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <memory>
|
||||||
|
#include <numeric>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -7,8 +23,15 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned
|
namespace
|
||||||
MapMatching<algorithm::CH>::GetMedianSampleTime(const std::vector<unsigned> ×tamps) const
|
{
|
||||||
|
using HMM = map_matching::HiddenMarkovModel<CandidateLists>;
|
||||||
|
|
||||||
|
constexpr static const unsigned MAX_BROKEN_STATES = 10;
|
||||||
|
constexpr static const double MATCHING_BETA = 10;
|
||||||
|
constexpr static const double MAX_DISTANCE_DELTA = 2000.;
|
||||||
|
|
||||||
|
unsigned getMedianSampleTime(const std::vector<unsigned> ×tamps)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(timestamps.size() > 1);
|
BOOST_ASSERT(timestamps.size() > 1);
|
||||||
|
|
||||||
@ -22,14 +45,20 @@ MapMatching<algorithm::CH>::GetMedianSampleTime(const std::vector<unsigned> &tim
|
|||||||
std::nth_element(first_elem, median, sample_times.end());
|
std::nth_element(first_elem, median, sample_times.end());
|
||||||
return *median;
|
return *median;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SubMatchingList MapMatching<algorithm::CH>::
|
SubMatchingList
|
||||||
operator()(const FacadeT &facade,
|
mapMatching(SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const CandidateLists &candidates_list,
|
const CandidateLists &candidates_list,
|
||||||
const std::vector<util::Coordinate> &trace_coordinates,
|
const std::vector<util::Coordinate> &trace_coordinates,
|
||||||
const std::vector<unsigned> &trace_timestamps,
|
const std::vector<unsigned> &trace_timestamps,
|
||||||
const std::vector<boost::optional<double>> &trace_gps_precision) const
|
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||||
{
|
{
|
||||||
|
map_matching::MatchingConfidence confidence;
|
||||||
|
map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION);
|
||||||
|
map_matching::TransitionLogProbability transition_log_probability(MATCHING_BETA);
|
||||||
|
|
||||||
SubMatchingList sub_matchings;
|
SubMatchingList sub_matchings;
|
||||||
|
|
||||||
BOOST_ASSERT(candidates_list.size() == trace_coordinates.size());
|
BOOST_ASSERT(candidates_list.size() == trace_coordinates.size());
|
||||||
@ -40,7 +69,7 @@ operator()(const FacadeT &facade,
|
|||||||
const auto median_sample_time = [&] {
|
const auto median_sample_time = [&] {
|
||||||
if (use_timestamps)
|
if (use_timestamps)
|
||||||
{
|
{
|
||||||
return std::max(1u, GetMedianSampleTime(trace_timestamps));
|
return std::max(1u, getMedianSampleTime(trace_timestamps));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -68,7 +97,7 @@ operator()(const FacadeT &facade,
|
|||||||
std::transform(candidates_list[t].begin(),
|
std::transform(candidates_list[t].begin(),
|
||||||
candidates_list[t].end(),
|
candidates_list[t].end(),
|
||||||
emission_log_probabilities[t].begin(),
|
emission_log_probabilities[t].begin(),
|
||||||
[this](const PhantomNodeWithDistance &candidate) {
|
[&](const PhantomNodeWithDistance &candidate) {
|
||||||
return default_emission_log_probability(candidate.distance);
|
return default_emission_log_probability(candidate.distance);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -95,7 +124,7 @@ operator()(const FacadeT &facade,
|
|||||||
std::transform(candidates_list[t].begin(),
|
std::transform(candidates_list[t].begin(),
|
||||||
candidates_list[t].end(),
|
candidates_list[t].end(),
|
||||||
emission_log_probabilities[t].begin(),
|
emission_log_probabilities[t].begin(),
|
||||||
[this](const PhantomNodeWithDistance &candidate) {
|
[&](const PhantomNodeWithDistance &candidate) {
|
||||||
return default_emission_log_probability(candidate.distance);
|
return default_emission_log_probability(candidate.distance);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -113,10 +142,10 @@ operator()(const FacadeT &facade,
|
|||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
|
||||||
QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
|
auto &forward_heap = *(engine_working_data.forward_heap_1);
|
||||||
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);
|
auto &reverse_heap = *(engine_working_data.reverse_heap_1);
|
||||||
QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2);
|
auto &forward_core_heap = *(engine_working_data.forward_heap_2);
|
||||||
QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2);
|
auto &reverse_core_heap = *(engine_working_data.reverse_heap_2);
|
||||||
|
|
||||||
std::size_t breakage_begin = map_matching::INVALID_STATE;
|
std::size_t breakage_begin = map_matching::INVALID_STATE;
|
||||||
std::vector<std::size_t> split_points;
|
std::vector<std::size_t> split_points;
|
||||||
@ -187,7 +216,7 @@ operator()(const FacadeT &facade,
|
|||||||
{
|
{
|
||||||
forward_core_heap.Clear();
|
forward_core_heap.Clear();
|
||||||
reverse_core_heap.Clear();
|
reverse_core_heap.Clear();
|
||||||
network_distance = super::GetNetworkDistanceWithCore(
|
network_distance = getNetworkDistanceWithCore(
|
||||||
facade,
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
@ -199,8 +228,8 @@ operator()(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
network_distance = super::GetNetworkDistance(
|
network_distance =
|
||||||
facade,
|
getNetworkDistance(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
prev_unbroken_timestamps_list[s].phantom_node,
|
prev_unbroken_timestamps_list[s].phantom_node,
|
||||||
|
@ -7,7 +7,7 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
|
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
NodeID &middle_node_id,
|
NodeID &middle_node_id,
|
||||||
@ -16,7 +16,7 @@ void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
|
|||||||
const bool forward_direction,
|
const bool forward_direction,
|
||||||
const bool stalling,
|
const bool stalling,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse) const
|
const bool force_loop_reverse)
|
||||||
{
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const EdgeWeight weight = forward_heap.GetKey(node);
|
const EdgeWeight weight = forward_heap.GetKey(node);
|
||||||
@ -36,7 +36,7 @@ void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
|
|||||||
// check whether there is a loop present at the node
|
// check whether there is a loop present at the node
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const EdgeData &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
||||||
if (forward_directionFlag)
|
if (forward_directionFlag)
|
||||||
{
|
{
|
||||||
@ -78,7 +78,7 @@ void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
|
|||||||
{
|
{
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const EdgeData &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||||
if (reverse_flag)
|
if (reverse_flag)
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
|
|||||||
|
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const EdgeData &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
||||||
if (forward_directionFlag)
|
if (forward_directionFlag)
|
||||||
{
|
{
|
||||||
@ -133,38 +133,35 @@ void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
|
|||||||
* @param to the node the CH edge finishes 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
|
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
|
||||||
*/
|
*/
|
||||||
void BasicRouting<algorithm::CH>::UnpackEdge(const FacadeT &facade,
|
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const NodeID from,
|
const NodeID from,
|
||||||
const NodeID to,
|
const NodeID to,
|
||||||
std::vector<NodeID> &unpacked_path) const
|
std::vector<NodeID> &unpacked_path)
|
||||||
{
|
{
|
||||||
std::array<NodeID, 2> path{{from, to}};
|
std::array<NodeID, 2> path{{from, to}};
|
||||||
UnpackCHPath(
|
unpackPath(facade,
|
||||||
facade,
|
|
||||||
path.begin(),
|
path.begin(),
|
||||||
path.end(),
|
path.end(),
|
||||||
[&unpacked_path](const std::pair<NodeID, NodeID> &edge, const EdgeData & /* data */) {
|
[&unpacked_path](const std::pair<NodeID, NodeID> &edge, const auto & /* data */) {
|
||||||
unpacked_path.emplace_back(edge.first);
|
unpacked_path.emplace_back(edge.first);
|
||||||
});
|
});
|
||||||
unpacked_path.emplace_back(to);
|
unpacked_path.emplace_back(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicRouting<algorithm::CH>::RetrievePackedPathFromHeap(
|
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
|
||||||
const SearchEngineData::QueryHeap &forward_heap,
|
|
||||||
const SearchEngineData::QueryHeap &reverse_heap,
|
const SearchEngineData::QueryHeap &reverse_heap,
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> &packed_path) const
|
std::vector<NodeID> &packed_path)
|
||||||
{
|
{
|
||||||
RetrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path);
|
retrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path);
|
||||||
std::reverse(packed_path.begin(), packed_path.end());
|
std::reverse(packed_path.begin(), packed_path.end());
|
||||||
packed_path.emplace_back(middle_node_id);
|
packed_path.emplace_back(middle_node_id);
|
||||||
RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path);
|
retrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicRouting<algorithm::CH>::RetrievePackedPathFromSingleHeap(
|
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
|
||||||
const SearchEngineData::QueryHeap &search_heap,
|
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> &packed_path) const
|
std::vector<NodeID> &packed_path)
|
||||||
{
|
{
|
||||||
NodeID current_node_id = middle_node_id;
|
NodeID current_node_id = middle_node_id;
|
||||||
// all initial nodes will have itself as parent, or a node not in the heap
|
// all initial nodes will have itself as parent, or a node not in the heap
|
||||||
@ -191,14 +188,14 @@ void BasicRouting<algorithm::CH>::RetrievePackedPathFromSingleHeap(
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void BasicRouting<algorithm::CH>::Search(const FacadeT &facade,
|
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
const EdgeWeight weight_upper_bound) const
|
const EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
weight = weight_upper_bound;
|
weight = weight_upper_bound;
|
||||||
@ -215,7 +212,7 @@ void BasicRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
{
|
{
|
||||||
if (!forward_heap.Empty())
|
if (!forward_heap.Empty())
|
||||||
{
|
{
|
||||||
RoutingStep(facade,
|
routingStep(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
middle,
|
middle,
|
||||||
@ -228,7 +225,7 @@ void BasicRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
if (!reverse_heap.Empty())
|
if (!reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
RoutingStep(facade,
|
routingStep(facade,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
middle,
|
middle,
|
||||||
@ -260,7 +257,7 @@ void BasicRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);
|
retrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +270,7 @@ void BasicRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
void searchWithCore(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
SearchEngineData::QueryHeap &forward_core_heap,
|
SearchEngineData::QueryHeap &forward_core_heap,
|
||||||
@ -282,7 +279,7 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
EdgeWeight weight_upper_bound) const
|
EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
weight = weight_upper_bound;
|
weight = weight_upper_bound;
|
||||||
@ -310,7 +307,7 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RoutingStep(facade,
|
routingStep(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
middle,
|
middle,
|
||||||
@ -332,7 +329,7 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RoutingStep(facade,
|
routingStep(facade,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
middle,
|
middle,
|
||||||
@ -385,7 +382,7 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
while (0 < forward_core_heap.Size() && 0 < reverse_core_heap.Size() &&
|
while (0 < forward_core_heap.Size() && 0 < reverse_core_heap.Size() &&
|
||||||
weight > (forward_core_heap.MinKey() + reverse_core_heap.MinKey()))
|
weight > (forward_core_heap.MinKey() + reverse_core_heap.MinKey()))
|
||||||
{
|
{
|
||||||
RoutingStep(facade,
|
routingStep(facade,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
middle,
|
middle,
|
||||||
@ -396,7 +393,7 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
force_loop_forward,
|
force_loop_forward,
|
||||||
force_loop_reverse);
|
force_loop_reverse);
|
||||||
|
|
||||||
RoutingStep(facade,
|
routingStep(facade,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
middle,
|
middle,
|
||||||
@ -432,13 +429,13 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<NodeID> packed_core_leg;
|
std::vector<NodeID> packed_core_leg;
|
||||||
RetrievePackedPathFromHeap(
|
retrievePackedPathFromHeap(
|
||||||
forward_core_heap, reverse_core_heap, middle, packed_core_leg);
|
forward_core_heap, reverse_core_heap, middle, packed_core_leg);
|
||||||
BOOST_ASSERT(packed_core_leg.size() > 0);
|
BOOST_ASSERT(packed_core_leg.size() > 0);
|
||||||
RetrievePackedPathFromSingleHeap(forward_heap, packed_core_leg.front(), packed_leg);
|
retrievePackedPathFromSingleHeap(forward_heap, packed_core_leg.front(), packed_leg);
|
||||||
std::reverse(packed_leg.begin(), packed_leg.end());
|
std::reverse(packed_leg.begin(), packed_leg.end());
|
||||||
packed_leg.insert(packed_leg.end(), packed_core_leg.begin(), packed_core_leg.end());
|
packed_leg.insert(packed_leg.end(), packed_core_leg.begin(), packed_core_leg.end());
|
||||||
RetrievePackedPathFromSingleHeap(reverse_heap, packed_core_leg.back(), packed_leg);
|
retrievePackedPathFromSingleHeap(reverse_heap, packed_core_leg.back(), packed_leg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -453,13 +450,12 @@ void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);
|
retrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BasicRouting<algorithm::CH>::NeedsLoopForward(const PhantomNode &source_phantom,
|
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
const PhantomNode &target_phantom) const
|
|
||||||
{
|
{
|
||||||
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
||||||
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
||||||
@ -467,8 +463,7 @@ bool BasicRouting<algorithm::CH>::NeedsLoopForward(const PhantomNode &source_pha
|
|||||||
target_phantom.GetForwardWeightPlusOffset();
|
target_phantom.GetForwardWeightPlusOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BasicRouting<algorithm::CH>::NeedsLoopBackwards(const PhantomNode &source_phantom,
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
const PhantomNode &target_phantom) const
|
|
||||||
{
|
{
|
||||||
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
||||||
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
||||||
@ -476,16 +471,16 @@ bool BasicRouting<algorithm::CH>::NeedsLoopBackwards(const PhantomNode &source_p
|
|||||||
target_phantom.GetReverseWeightPlusOffset();
|
target_phantom.GetReverseWeightPlusOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
double BasicRouting<algorithm::CH>::GetPathDistance(const FacadeT &facade,
|
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const std::vector<NodeID> &packed_path,
|
const std::vector<NodeID> &packed_path,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom) const
|
const PhantomNode &target_phantom)
|
||||||
{
|
{
|
||||||
std::vector<PathData> unpacked_path;
|
std::vector<PathData> unpacked_path;
|
||||||
PhantomNodes nodes;
|
PhantomNodes nodes;
|
||||||
nodes.source_phantom = source_phantom;
|
nodes.source_phantom = source_phantom;
|
||||||
nodes.target_phantom = target_phantom;
|
nodes.target_phantom = target_phantom;
|
||||||
UnpackPath(facade, packed_path.begin(), packed_path.end(), nodes, unpacked_path);
|
unpackPath(facade, packed_path.begin(), packed_path.end(), nodes, unpacked_path);
|
||||||
|
|
||||||
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
|
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
|
||||||
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
||||||
@ -535,15 +530,15 @@ double BasicRouting<algorithm::CH>::GetPathDistance(const FacadeT &facade,
|
|||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double BasicRouting<algorithm::CH>::GetNetworkDistanceWithCore(
|
double getNetworkDistanceWithCore(
|
||||||
const FacadeT &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
SearchEngineData::QueryHeap &forward_core_heap,
|
SearchEngineData::QueryHeap &forward_core_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
EdgeWeight weight_upper_bound) const
|
EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(forward_heap.Empty());
|
BOOST_ASSERT(forward_heap.Empty());
|
||||||
BOOST_ASSERT(reverse_heap.Empty());
|
BOOST_ASSERT(reverse_heap.Empty());
|
||||||
@ -579,7 +574,7 @@ double BasicRouting<algorithm::CH>::GetNetworkDistanceWithCore(
|
|||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
SearchWithCore(facade,
|
searchWithCore(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
@ -593,7 +588,7 @@ double BasicRouting<algorithm::CH>::GetNetworkDistanceWithCore(
|
|||||||
double distance = std::numeric_limits<double>::max();
|
double distance = std::numeric_limits<double>::max();
|
||||||
if (weight != INVALID_EDGE_WEIGHT)
|
if (weight != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
return GetPathDistance(facade, packed_path, source_phantom, target_phantom);
|
return getPathDistance(facade, packed_path, source_phantom, target_phantom);
|
||||||
}
|
}
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
@ -601,12 +596,13 @@ double BasicRouting<algorithm::CH>::GetNetworkDistanceWithCore(
|
|||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double BasicRouting<algorithm::CH>::GetNetworkDistance(const FacadeT &facade,
|
double
|
||||||
|
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
EdgeWeight weight_upper_bound) const
|
EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(forward_heap.Empty());
|
BOOST_ASSERT(forward_heap.Empty());
|
||||||
BOOST_ASSERT(reverse_heap.Empty());
|
BOOST_ASSERT(reverse_heap.Empty());
|
||||||
@ -642,7 +638,7 @@ double BasicRouting<algorithm::CH>::GetNetworkDistance(const FacadeT &facade,
|
|||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
Search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
weight,
|
weight,
|
||||||
@ -656,7 +652,7 @@ double BasicRouting<algorithm::CH>::GetNetworkDistance(const FacadeT &facade,
|
|||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetPathDistance(facade, packed_path, source_phantom, target_phantom);
|
return getPathDistance(facade, packed_path, source_phantom, target_phantom);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
#include "engine/routing_algorithms/shortest_path.hpp"
|
#include "engine/routing_algorithms/shortest_path.hpp"
|
||||||
|
#include "engine/routing_algorithms/routing_base.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -7,9 +12,12 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const static constexpr bool DO_NOT_FORCE_LOOP = false;
|
||||||
|
using QueryHeap = SearchEngineData::QueryHeap;
|
||||||
|
|
||||||
// allows a uturn at the target_phantom
|
// allows a uturn at the target_phantom
|
||||||
// searches source forward/reverse -> target forward/reverse
|
// searches source forward/reverse -> target forward/reverse
|
||||||
void ShortestPathRouting<algorithm::CH>::SearchWithUTurn(const FacadeT &facade,
|
void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
QueryHeap &forward_heap,
|
QueryHeap &forward_heap,
|
||||||
QueryHeap &reverse_heap,
|
QueryHeap &reverse_heap,
|
||||||
QueryHeap &forward_core_heap,
|
QueryHeap &forward_core_heap,
|
||||||
@ -23,7 +31,7 @@ void ShortestPathRouting<algorithm::CH>::SearchWithUTurn(const FacadeT &facade,
|
|||||||
const int total_weight_to_forward,
|
const int total_weight_to_forward,
|
||||||
const int total_weight_to_reverse,
|
const int total_weight_to_reverse,
|
||||||
int &new_total_weight,
|
int &new_total_weight,
|
||||||
std::vector<NodeID> &leg_packed_path) const
|
std::vector<NodeID> &leg_packed_path)
|
||||||
{
|
{
|
||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
@ -59,17 +67,16 @@ void ShortestPathRouting<algorithm::CH>::SearchWithUTurn(const FacadeT &facade,
|
|||||||
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 =
|
auto needs_loop_forwad = is_oneway_source && needsLoopForward(source_phantom, target_phantom);
|
||||||
is_oneway_source && super::NeedsLoopForward(source_phantom, target_phantom);
|
|
||||||
auto needs_loop_backwards =
|
auto needs_loop_backwards =
|
||||||
is_oneway_target && super::NeedsLoopBackwards(source_phantom, target_phantom);
|
is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
|
||||||
if (facade.GetCoreSize() > 0)
|
if (facade.GetCoreSize() > 0)
|
||||||
{
|
{
|
||||||
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);
|
||||||
super::SearchWithCore(facade,
|
searchWithCore(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
@ -81,7 +88,7 @@ void ShortestPathRouting<algorithm::CH>::SearchWithUTurn(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
super::Search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
new_total_weight,
|
new_total_weight,
|
||||||
@ -99,7 +106,7 @@ void ShortestPathRouting<algorithm::CH>::SearchWithUTurn(const FacadeT &facade,
|
|||||||
// searches shortest path between:
|
// searches shortest path between:
|
||||||
// source forward/reverse -> target forward
|
// source forward/reverse -> target forward
|
||||||
// source forward/reverse -> target reverse
|
// source forward/reverse -> target reverse
|
||||||
void ShortestPathRouting<algorithm::CH>::Search(const FacadeT &facade,
|
void Search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
QueryHeap &forward_heap,
|
QueryHeap &forward_heap,
|
||||||
QueryHeap &reverse_heap,
|
QueryHeap &reverse_heap,
|
||||||
QueryHeap &forward_core_heap,
|
QueryHeap &forward_core_heap,
|
||||||
@ -115,7 +122,7 @@ void ShortestPathRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
int &new_total_weight_to_forward,
|
int &new_total_weight_to_forward,
|
||||||
int &new_total_weight_to_reverse,
|
int &new_total_weight_to_reverse,
|
||||||
std::vector<NodeID> &leg_packed_path_forward,
|
std::vector<NodeID> &leg_packed_path_forward,
|
||||||
std::vector<NodeID> &leg_packed_path_reverse) const
|
std::vector<NodeID> &leg_packed_path_reverse)
|
||||||
{
|
{
|
||||||
if (search_to_forward_node)
|
if (search_to_forward_node)
|
||||||
{
|
{
|
||||||
@ -148,24 +155,24 @@ void ShortestPathRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
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);
|
||||||
super::SearchWithCore(facade,
|
searchWithCore(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,
|
||||||
super::NeedsLoopForward(source_phantom, target_phantom),
|
needsLoopForward(source_phantom, target_phantom),
|
||||||
DO_NOT_FORCE_LOOP);
|
DO_NOT_FORCE_LOOP);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
super::Search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
new_total_weight_to_forward,
|
new_total_weight_to_forward,
|
||||||
leg_packed_path_forward,
|
leg_packed_path_forward,
|
||||||
super::NeedsLoopForward(source_phantom, target_phantom),
|
needsLoopForward(source_phantom, target_phantom),
|
||||||
DO_NOT_FORCE_LOOP);
|
DO_NOT_FORCE_LOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +206,7 @@ void ShortestPathRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
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);
|
||||||
super::SearchWithCore(facade,
|
searchWithCore(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
@ -207,28 +214,27 @@ void ShortestPathRouting<algorithm::CH>::Search(const FacadeT &facade,
|
|||||||
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,
|
||||||
super::NeedsLoopBackwards(source_phantom, target_phantom));
|
needsLoopBackwards(source_phantom, target_phantom));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
super::Search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_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,
|
||||||
super::NeedsLoopBackwards(source_phantom, target_phantom));
|
needsLoopBackwards(source_phantom, target_phantom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortestPathRouting<algorithm::CH>::UnpackLegs(
|
void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const FacadeT &facade,
|
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const std::vector<NodeID> &total_packed_path,
|
const std::vector<NodeID> &total_packed_path,
|
||||||
const std::vector<std::size_t> &packed_leg_begin,
|
const std::vector<std::size_t> &packed_leg_begin,
|
||||||
const int shortest_path_length,
|
const int shortest_path_length,
|
||||||
InternalRouteResult &raw_route_data) const
|
InternalRouteResult &raw_route_data)
|
||||||
{
|
{
|
||||||
raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1);
|
raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1);
|
||||||
|
|
||||||
@ -239,7 +245,7 @@ void ShortestPathRouting<algorithm::CH>::UnpackLegs(
|
|||||||
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];
|
||||||
super::UnpackPath(facade,
|
unpackPath(facade,
|
||||||
leg_begin,
|
leg_begin,
|
||||||
leg_end,
|
leg_end,
|
||||||
unpack_phantom_node_pair,
|
unpack_phantom_node_pair,
|
||||||
@ -253,12 +259,13 @@ void ShortestPathRouting<algorithm::CH>::UnpackLegs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortestPathRouting<algorithm::CH>::
|
InternalRouteResult
|
||||||
operator()(const FacadeT &facade,
|
shortestPathSearch(SearchEngineData &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const boost::optional<bool> continue_straight_at_waypoint,
|
const boost::optional<bool> continue_straight_at_waypoint)
|
||||||
InternalRouteResult &raw_route_data) const
|
|
||||||
{
|
{
|
||||||
|
InternalRouteResult raw_route_data;
|
||||||
const bool allow_uturn_at_waypoint =
|
const bool allow_uturn_at_waypoint =
|
||||||
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
|
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
|
||||||
: facade.GetContinueStraightDefault());
|
: facade.GetContinueStraightDefault());
|
||||||
@ -312,7 +319,7 @@ operator()(const FacadeT &facade,
|
|||||||
{
|
{
|
||||||
if (allow_uturn_at_waypoint)
|
if (allow_uturn_at_waypoint)
|
||||||
{
|
{
|
||||||
SearchWithUTurn(facade,
|
searchWithUTurn(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
@ -370,7 +377,7 @@ operator()(const FacadeT &facade,
|
|||||||
{
|
{
|
||||||
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
|
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
|
||||||
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
|
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
|
||||||
return;
|
return raw_route_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to figure out how the new legs connect to the previous ones
|
// we need to figure out how the new legs connect to the previous ones
|
||||||
@ -473,7 +480,7 @@ operator()(const FacadeT &facade,
|
|||||||
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
|
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
|
||||||
BOOST_ASSERT(packed_leg_to_reverse_begin.size() == phantom_nodes_vector.size() + 1);
|
BOOST_ASSERT(packed_leg_to_reverse_begin.size() == phantom_nodes_vector.size() + 1);
|
||||||
|
|
||||||
UnpackLegs(facade,
|
unpackLegs(facade,
|
||||||
phantom_nodes_vector,
|
phantom_nodes_vector,
|
||||||
total_packed_path_to_reverse,
|
total_packed_path_to_reverse,
|
||||||
packed_leg_to_reverse_begin,
|
packed_leg_to_reverse_begin,
|
||||||
@ -486,13 +493,15 @@ operator()(const FacadeT &facade,
|
|||||||
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
|
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
|
||||||
BOOST_ASSERT(packed_leg_to_forward_begin.size() == phantom_nodes_vector.size() + 1);
|
BOOST_ASSERT(packed_leg_to_forward_begin.size() == phantom_nodes_vector.size() + 1);
|
||||||
|
|
||||||
UnpackLegs(facade,
|
unpackLegs(facade,
|
||||||
phantom_nodes_vector,
|
phantom_nodes_vector,
|
||||||
total_packed_path_to_forward,
|
total_packed_path_to_forward,
|
||||||
packed_leg_to_forward_begin,
|
packed_leg_to_forward_begin,
|
||||||
total_weight_to_forward,
|
total_weight_to_forward,
|
||||||
raw_route_data);
|
raw_route_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return raw_route_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
|
@ -7,10 +7,10 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<TurnData> TileTurns<algorithm::CH>::
|
std::vector<TurnData>
|
||||||
operator()(const FacadeT &facade,
|
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||||
const std::vector<RTreeLeaf> &edges,
|
const std::vector<RTreeLeaf> &edges,
|
||||||
const std::vector<std::size_t> &sorted_edge_indexes) const
|
const std::vector<std::size_t> &sorted_edge_indexes)
|
||||||
{
|
{
|
||||||
std::vector<TurnData> all_turn_data;
|
std::vector<TurnData> all_turn_data;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user