Split MLD many-to-many method
This commit is contained in:
parent
454487dd41
commit
2715e5758b
@ -11,7 +11,7 @@ module.exports = function () {
|
|||||||
var waypoints = [],
|
var waypoints = [],
|
||||||
columnHeaders = tableRows[0].slice(1),
|
columnHeaders = tableRows[0].slice(1),
|
||||||
rowHeaders = tableRows.map((h) => h[0]).slice(1),
|
rowHeaders = tableRows.map((h) => h[0]).slice(1),
|
||||||
symmetric = columnHeaders.every((ele, i) => ele === rowHeaders[i]);
|
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
|
||||||
|
|
||||||
if (symmetric) {
|
if (symmetric) {
|
||||||
columnHeaders.forEach((nodeName) => {
|
columnHeaders.forEach((nodeName) => {
|
||||||
|
@ -41,6 +41,17 @@ Feature: Basic Distance Matrix
|
|||||||
| c | 30 | 20 | 0 | 30 |
|
| c | 30 | 20 | 0 | 30 |
|
||||||
| d | 60 | 50 | 30 | 0 |
|
| d | 60 | 50 | 30 | 0 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 10 | 30 | 60 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 10 |
|
||||||
|
| c | 30 |
|
||||||
|
| d | 60 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix with fuzzy match
|
Scenario: Testbot - Travel time matrix with fuzzy match
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@ -132,6 +143,13 @@ Feature: Basic Distance Matrix
|
|||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 10 |
|
||||||
|
| e | 20 |
|
||||||
|
| f | 30 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time 3x2 matrix
|
Scenario: Testbot - Travel time 3x2 matrix
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
|
@ -30,7 +30,7 @@ class RoutingAlgorithmsInterface
|
|||||||
virtual InternalRouteResult
|
virtual InternalRouteResult
|
||||||
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
virtual std::vector<EdgeDuration>
|
||||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManySearch(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 = 0;
|
const std::vector<std::size_t> &target_indices) const = 0;
|
||||||
@ -81,7 +81,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
InternalRouteResult
|
InternalRouteResult
|
||||||
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
||||||
|
|
||||||
std::vector<EdgeWeight>
|
std::vector<EdgeDuration>
|
||||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManySearch(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 final override;
|
const std::vector<std::size_t> &target_indices) const final override;
|
||||||
@ -166,16 +166,6 @@ RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phant
|
|||||||
return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes);
|
return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
|
||||||
std::vector<EdgeWeight>
|
|
||||||
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
|
||||||
const std::vector<std::size_t> &source_indices,
|
|
||||||
const std::vector<std::size_t> &target_indices) const
|
|
||||||
{
|
|
||||||
return routing_algorithms::manyToManySearch(
|
|
||||||
heaps, *facade, phantom_nodes, source_indices, target_indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
|
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
|
||||||
const routing_algorithms::CandidateLists &candidates_list,
|
const routing_algorithms::CandidateLists &candidates_list,
|
||||||
@ -211,7 +201,7 @@ InternalManyRoutesResult inline RoutingAlgorithms<
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline std::vector<EdgeWeight>
|
inline std::vector<EdgeDuration>
|
||||||
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
||||||
const std::vector<PhantomNode> &,
|
const std::vector<PhantomNode> &,
|
||||||
const std::vector<std::size_t> &,
|
const std::vector<std::size_t> &,
|
||||||
|
@ -17,11 +17,23 @@ namespace routing_algorithms
|
|||||||
{
|
{
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
std::vector<std::size_t> source_indices,
|
std::vector<std::size_t> source_indices,
|
||||||
std::vector<std::size_t> target_indices);
|
std::vector<std::size_t> target_indices);
|
||||||
|
|
||||||
|
namespace mld
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool DIRECTION>
|
||||||
|
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade,
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
std::size_t phantom_index,
|
||||||
|
std::vector<std::size_t> phantom_indices);
|
||||||
|
|
||||||
|
} // mld
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
56
src/engine/routing_algorithms.cpp
Normal file
56
src/engine/routing_algorithms.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "engine/routing_algorithms.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace engine
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Algorithm>
|
||||||
|
std::vector<EdgeDuration>
|
||||||
|
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
const std::vector<std::size_t> &source_indices,
|
||||||
|
const std::vector<std::size_t> &target_indices) const
|
||||||
|
{
|
||||||
|
return routing_algorithms::manyToManySearch(
|
||||||
|
heaps, *facade, phantom_nodes, source_indices, target_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
template std::vector<EdgeDuration>
|
||||||
|
RoutingAlgorithms<routing_algorithms::ch::Algorithm>::ManyToManySearch(
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
const std::vector<std::size_t> &source_indices,
|
||||||
|
const std::vector<std::size_t> &target_indices) const;
|
||||||
|
|
||||||
|
template std::vector<EdgeDuration>
|
||||||
|
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
const std::vector<std::size_t> &source_indices,
|
||||||
|
const std::vector<std::size_t> &target_indices) const;
|
||||||
|
|
||||||
|
// One-to-many and many-to-one can be handled with MLD separately from many-to-many search.
|
||||||
|
// One-to-many (many-to-one) search is a unidirectional forward (backward) Dijkstra search
|
||||||
|
// with the candidate node level min(GetQueryLevel(phantom_node, phantom_nodes, node)
|
||||||
|
template <>
|
||||||
|
std::vector<EdgeDuration> RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
const std::vector<std::size_t> &source_indices,
|
||||||
|
const std::vector<std::size_t> &target_indices) const
|
||||||
|
{
|
||||||
|
if (source_indices.size() == 1)
|
||||||
|
{ // TODO: check if target_indices.size() == 1 and do a bi-directional search
|
||||||
|
return routing_algorithms::mld::oneToManySearch<routing_algorithms::FORWARD_DIRECTION>(
|
||||||
|
heaps, *facade, phantom_nodes, source_indices.front(), target_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_indices.size() == 1)
|
||||||
|
{
|
||||||
|
return routing_algorithms::mld::oneToManySearch<routing_algorithms::REVERSE_DIRECTION>(
|
||||||
|
heaps, *facade, phantom_nodes, target_indices.front(), source_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
return routing_algorithms::manyToManySearch(
|
||||||
|
heaps, *facade, phantom_nodes, source_indices, target_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace engine
|
||||||
|
} // namespace osrm
|
@ -322,11 +322,11 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
std::vector<std::size_t> source_indices,
|
std::vector<std::size_t> source_indices,
|
||||||
std::vector<std::size_t> target_indices)
|
std::vector<std::size_t> target_indices)
|
||||||
{
|
{
|
||||||
if (source_indices.empty())
|
if (source_indices.empty())
|
||||||
{
|
{
|
||||||
@ -415,20 +415,57 @@ std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_wor
|
|||||||
return durations_table;
|
return durations_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
template std::vector<EdgeWeight>
|
template std::vector<EdgeDuration>
|
||||||
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
const DataFacade<ch::Algorithm> &facade,
|
const DataFacade<ch::Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
std::vector<std::size_t> source_indices,
|
std::vector<std::size_t> source_indices,
|
||||||
std::vector<std::size_t> target_indices);
|
std::vector<std::size_t> target_indices);
|
||||||
|
|
||||||
template std::vector<EdgeWeight>
|
template std::vector<EdgeDuration>
|
||||||
manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||||
const DataFacade<mld::Algorithm> &facade,
|
const DataFacade<mld::Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
std::vector<std::size_t> source_indices,
|
std::vector<std::size_t> source_indices,
|
||||||
std::vector<std::size_t> target_indices);
|
std::vector<std::size_t> target_indices);
|
||||||
|
|
||||||
|
namespace mld
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool DIRECTION>
|
||||||
|
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade,
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
std::size_t phantom_index,
|
||||||
|
std::vector<std::size_t> phantom_indices)
|
||||||
|
{
|
||||||
|
if (phantom_indices.empty())
|
||||||
|
{
|
||||||
|
phantom_indices.resize(phantom_nodes.size());
|
||||||
|
std::iota(phantom_indices.begin(), phantom_indices.end(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<EdgeWeight> weights(phantom_nodes.size(), INVALID_EDGE_WEIGHT);
|
||||||
|
std::vector<EdgeDuration> durations(phantom_nodes.size(), MAXIMAL_EDGE_DURATION);
|
||||||
|
|
||||||
|
return durations;
|
||||||
|
}
|
||||||
|
|
||||||
|
template std::vector<EdgeDuration>
|
||||||
|
oneToManySearch<FORWARD_DIRECTION>(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade,
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
std::size_t phantom_index,
|
||||||
|
std::vector<std::size_t> phantom_indices);
|
||||||
|
|
||||||
|
template std::vector<EdgeDuration>
|
||||||
|
oneToManySearch<REVERSE_DIRECTION>(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade,
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
std::size_t phantom_index,
|
||||||
|
std::vector<std::size_t> phantom_indices);
|
||||||
|
} // mld
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
Loading…
Reference in New Issue
Block a user