Skip to content

Commit 21607e0

Browse files
Optimise getNetworkDistance in MLD even more (#6884)
1 parent 24646aa commit 21607e0

File tree

5 files changed

+261
-74
lines changed

5 files changed

+261
-74
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
- FIXED: Remove force-loop checks for routes with u-turns [#6858](https://github.com/Project-OSRM/osrm-backend/pull/6858)
5454
- FIXED: Correctly check runtime search conditions for forcing routing steps [#6866](https://github.com/Project-OSRM/osrm-backend/pull/6866)
5555
- Map Matching:
56+
- CHANGED: Optimise path distance calculation in MLD map matching even more. [#6884](https://github.com/Project-OSRM/osrm-backend/pull/6884)
5657
- CHANGED: Optimise path distance calculation in MLD map matching. [#6876](https://github.com/Project-OSRM/osrm-backend/pull/6876)
5758
- CHANGED: Optimise R-tree queries in the case of map matching. [#6881](https://github.com/Project-OSRM/osrm-backend/pull/6876)
5859
- Debug tiles:

include/engine/routing_algorithms/routing_base_mld.hpp

Lines changed: 176 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <boost/assert.hpp>
1212

1313
#include <algorithm>
14+
#include <boost/core/ignore_unused.hpp>
1415
#include <iterator>
1516
#include <limits>
1617
#include <tuple>
@@ -269,10 +270,29 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
269270
return packed_path;
270271
}
271272

272-
template <bool DIRECTION, typename Algorithm, typename... Args>
273+
template <typename Heap>
274+
void insertOrUpdate(Heap &heap,
275+
const NodeID node,
276+
const EdgeWeight weight,
277+
const typename Heap::DataType &data)
278+
{
279+
const auto heapNode = heap.GetHeapNodeIfWasInserted(node);
280+
if (!heapNode)
281+
{
282+
heap.Insert(node, weight, data);
283+
}
284+
else if (weight < heapNode->weight)
285+
{
286+
heapNode->data = data;
287+
heapNode->weight = weight;
288+
heap.DecreaseKey(*heapNode);
289+
}
290+
}
291+
292+
template <bool DIRECTION, typename Algorithm, typename Heap, typename... Args>
273293
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
274-
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
275-
const typename SearchEngineData<Algorithm>::QueryHeap::HeapNode &heapNode,
294+
Heap &forward_heap,
295+
const typename Heap::HeapNode &heapNode,
276296
const Args &...args)
277297
{
278298
const auto &partition = facade.GetMultiLevelPartition();
@@ -281,14 +301,31 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
281301

282302
const auto level = getNodeQueryLevel(partition, heapNode.node, args...);
283303

304+
static constexpr auto IS_MAP_MATCHING =
305+
std::is_same_v<typename SearchEngineData<mld::Algorithm>::MapMatchingQueryHeap, Heap>;
306+
284307
if (level >= 1 && !heapNode.data.from_clique_arc)
285308
{
286-
if (DIRECTION == FORWARD_DIRECTION)
309+
if constexpr (DIRECTION == FORWARD_DIRECTION)
287310
{
288311
// Shortcuts in forward direction
289312
const auto &cell =
290313
cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
291314
auto destination = cell.GetDestinationNodes().begin();
315+
auto distance = [&cell, node = heapNode.node ]() -> auto
316+
{
317+
if constexpr (IS_MAP_MATCHING)
318+
{
319+
320+
return cell.GetOutDistance(node).begin();
321+
}
322+
else
323+
{
324+
boost::ignore_unused(cell, node);
325+
return 0;
326+
}
327+
}
328+
();
292329
for (auto shortcut_weight : cell.GetOutWeight(heapNode.node))
293330
{
294331
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
@@ -298,19 +335,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
298335
{
299336
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
300337
BOOST_ASSERT(to_weight >= heapNode.weight);
301-
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
302-
if (!toHeapNode)
338+
339+
if constexpr (IS_MAP_MATCHING)
303340
{
304-
forward_heap.Insert(to, to_weight, {heapNode.node, true});
341+
const EdgeDistance to_distance = heapNode.data.distance + *distance;
342+
insertOrUpdate(
343+
forward_heap, to, to_weight, {heapNode.node, true, to_distance});
305344
}
306-
else if (to_weight < toHeapNode->weight)
345+
else
307346
{
308-
toHeapNode->data = {heapNode.node, true};
309-
toHeapNode->weight = to_weight;
310-
forward_heap.DecreaseKey(*toHeapNode);
347+
insertOrUpdate(forward_heap, to, to_weight, {heapNode.node, true});
311348
}
312349
}
313350
++destination;
351+
if constexpr (IS_MAP_MATCHING)
352+
{
353+
++distance;
354+
}
314355
}
315356
}
316357
else
@@ -319,6 +360,20 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
319360
const auto &cell =
320361
cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
321362
auto source = cell.GetSourceNodes().begin();
363+
auto distance = [&cell, node = heapNode.node ]() -> auto
364+
{
365+
if constexpr (IS_MAP_MATCHING)
366+
{
367+
368+
return cell.GetInDistance(node).begin();
369+
}
370+
else
371+
{
372+
boost::ignore_unused(cell, node);
373+
return 0;
374+
}
375+
}
376+
();
322377
for (auto shortcut_weight : cell.GetInWeight(heapNode.node))
323378
{
324379
BOOST_ASSERT(source != cell.GetSourceNodes().end());
@@ -328,19 +383,22 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
328383
{
329384
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
330385
BOOST_ASSERT(to_weight >= heapNode.weight);
331-
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
332-
if (!toHeapNode)
386+
if constexpr (IS_MAP_MATCHING)
333387
{
334-
forward_heap.Insert(to, to_weight, {heapNode.node, true});
388+
const EdgeDistance to_distance = heapNode.data.distance + *distance;
389+
insertOrUpdate(
390+
forward_heap, to, to_weight, {heapNode.node, true, to_distance});
335391
}
336-
else if (to_weight < toHeapNode->weight)
392+
else
337393
{
338-
toHeapNode->data = {heapNode.node, true};
339-
toHeapNode->weight = to_weight;
340-
forward_heap.DecreaseKey(*toHeapNode);
394+
insertOrUpdate(forward_heap, to, to_weight, {heapNode.node, true});
341395
}
342396
}
343397
++source;
398+
if constexpr (IS_MAP_MATCHING)
399+
{
400+
++distance;
401+
}
344402
}
345403
}
346404
}
@@ -367,26 +425,28 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
367425
const EdgeWeight to_weight =
368426
heapNode.weight + node_weight + alias_cast<EdgeWeight>(turn_penalty);
369427

370-
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
371-
if (!toHeapNode)
428+
if constexpr (IS_MAP_MATCHING)
372429
{
373-
forward_heap.Insert(to, to_weight, {heapNode.node, false});
430+
const auto node_distance =
431+
facade.GetNodeDistance(DIRECTION == FORWARD_DIRECTION ? heapNode.node : to);
432+
433+
const EdgeDistance to_distance = heapNode.data.distance + node_distance;
434+
insertOrUpdate(
435+
forward_heap, to, to_weight, {heapNode.node, false, to_distance});
374436
}
375-
else if (to_weight < toHeapNode->weight)
437+
else
376438
{
377-
toHeapNode->data = {heapNode.node, false};
378-
toHeapNode->weight = to_weight;
379-
forward_heap.DecreaseKey(*toHeapNode);
439+
insertOrUpdate(forward_heap, to, to_weight, {heapNode.node, false});
380440
}
381441
}
382442
}
383443
}
384444
}
385445

386-
template <bool DIRECTION, typename Algorithm, typename... Args>
446+
template <bool DIRECTION, typename Algorithm, typename Heap, typename... Args>
387447
void routingStep(const DataFacade<Algorithm> &facade,
388-
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
389-
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
448+
Heap &forward_heap,
449+
Heap &reverse_heap,
390450
NodeID &middle_node,
391451
EdgeWeight &path_upper_bound,
392452
const std::vector<NodeID> &force_step_nodes,
@@ -429,22 +489,19 @@ using UnpackedNodes = std::vector<NodeID>;
429489
using UnpackedEdges = std::vector<EdgeID>;
430490
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
431491

432-
template <typename Algorithm, typename... Args>
433-
UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
434-
const DataFacade<Algorithm> &facade,
435-
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
436-
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
437-
const std::vector<NodeID> &force_step_nodes,
438-
EdgeWeight weight_upper_bound,
439-
const Args &...args)
492+
template <typename Algorithm, typename Heap, typename... Args>
493+
std::optional<std::pair<NodeID, EdgeWeight>> runSearch(const DataFacade<Algorithm> &facade,
494+
Heap &forward_heap,
495+
Heap &reverse_heap,
496+
const std::vector<NodeID> &force_step_nodes,
497+
EdgeWeight weight_upper_bound,
498+
const Args &...args)
440499
{
441500
if (forward_heap.Empty() || reverse_heap.Empty())
442501
{
443-
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
502+
return {};
444503
}
445504

446-
const auto &partition = facade.GetMultiLevelPartition();
447-
448505
BOOST_ASSERT(!forward_heap.Empty() && forward_heap.MinKey() < INVALID_EDGE_WEIGHT);
449506
BOOST_ASSERT(!reverse_heap.Empty() && reverse_heap.MinKey() < INVALID_EDGE_WEIGHT);
450507

@@ -474,10 +531,33 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
474531

475532
// No path found for both target nodes?
476533
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
534+
{
535+
return {};
536+
}
537+
538+
return {{middle, weight}};
539+
}
540+
541+
template <typename Algorithm, typename... Args>
542+
UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
543+
const DataFacade<Algorithm> &facade,
544+
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
545+
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
546+
const std::vector<NodeID> &force_step_nodes,
547+
EdgeWeight weight_upper_bound,
548+
const Args &...args)
549+
{
550+
auto searchResult = runSearch(
551+
facade, forward_heap, reverse_heap, force_step_nodes, weight_upper_bound, args...);
552+
if (!searchResult)
477553
{
478554
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
479555
}
480556

557+
auto [middle, weight] = *searchResult;
558+
559+
const auto &partition = facade.GetMultiLevelPartition();
560+
481561
// Get packed path as edges {from node ID, to node ID, from_clique_arc}
482562
auto packed_path = retrievePackedPathFromHeap(forward_heap, reverse_heap, middle);
483563

@@ -536,6 +616,31 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
536616
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
537617
}
538618

619+
template <typename Algorithm, typename... Args>
620+
EdgeDistance
621+
searchDistance(SearchEngineData<Algorithm> &,
622+
const DataFacade<Algorithm> &facade,
623+
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &forward_heap,
624+
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &reverse_heap,
625+
const std::vector<NodeID> &force_step_nodes,
626+
EdgeWeight weight_upper_bound,
627+
const Args &...args)
628+
{
629+
630+
auto searchResult = runSearch(
631+
facade, forward_heap, reverse_heap, force_step_nodes, weight_upper_bound, args...);
632+
if (!searchResult)
633+
{
634+
return INVALID_EDGE_DISTANCE;
635+
}
636+
637+
auto [middle, _] = *searchResult;
638+
639+
auto distance = forward_heap.GetData(middle).distance + reverse_heap.GetData(middle).distance;
640+
641+
return distance;
642+
}
643+
539644
// Alias to be compatible with the CH-based search
540645
template <typename Algorithm, typename PhantomEndpointT>
541646
inline void search(SearchEngineData<Algorithm> &engine_working_data,
@@ -593,57 +698,58 @@ void unpackPath(const FacadeT &facade,
593698
template <typename Algorithm>
594699
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
595700
const DataFacade<Algorithm> &facade,
596-
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
597-
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
701+
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &forward_heap,
702+
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &reverse_heap,
598703
const PhantomNode &source_phantom,
599704
const PhantomNode &target_phantom,
600705
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
601706
{
602707
forward_heap.Clear();
603708
reverse_heap.Clear();
604709

605-
const PhantomEndpoints endpoints{source_phantom, target_phantom};
606-
insertNodesInHeaps(forward_heap, reverse_heap, endpoints);
607-
608-
auto [weight, unpacked_nodes, unpacked_edges] = search(
609-
engine_working_data, facade, forward_heap, reverse_heap, {}, weight_upper_bound, endpoints);
610-
611-
if (weight == INVALID_EDGE_WEIGHT)
710+
if (source_phantom.IsValidForwardSource())
612711
{
613-
return std::numeric_limits<double>::max();
712+
forward_heap.Insert(source_phantom.forward_segment_id.id,
713+
EdgeWeight{0} - source_phantom.GetForwardWeightPlusOffset(),
714+
{source_phantom.forward_segment_id.id,
715+
false,
716+
EdgeDistance{0} - source_phantom.GetForwardDistance()});
614717
}
615718

616-
BOOST_ASSERT(unpacked_nodes.size() >= 1);
617-
618-
EdgeDistance distance = {0.0};
619-
620-
if (source_phantom.forward_segment_id.id == unpacked_nodes.front())
621-
{
622-
BOOST_ASSERT(source_phantom.forward_segment_id.enabled);
623-
distance = EdgeDistance{0} - source_phantom.GetForwardDistance();
624-
}
625-
else if (source_phantom.reverse_segment_id.id == unpacked_nodes.front())
719+
if (source_phantom.IsValidReverseSource())
626720
{
627-
BOOST_ASSERT(source_phantom.reverse_segment_id.enabled);
628-
distance = EdgeDistance{0} - source_phantom.GetReverseDistance();
721+
forward_heap.Insert(source_phantom.reverse_segment_id.id,
722+
EdgeWeight{0} - source_phantom.GetReverseWeightPlusOffset(),
723+
{source_phantom.reverse_segment_id.id,
724+
false,
725+
EdgeDistance{0} - source_phantom.GetReverseDistance()});
629726
}
630727

631-
for (size_t index = 0; index < unpacked_nodes.size() - 1; ++index)
728+
if (target_phantom.IsValidForwardTarget())
632729
{
633-
distance += facade.GetNodeDistance(unpacked_nodes[index]);
730+
reverse_heap.Insert(
731+
target_phantom.forward_segment_id.id,
732+
target_phantom.GetForwardWeightPlusOffset(),
733+
{target_phantom.forward_segment_id.id, false, target_phantom.GetForwardDistance()});
634734
}
635735

636-
if (target_phantom.forward_segment_id.id == unpacked_nodes.back())
736+
if (target_phantom.IsValidReverseTarget())
637737
{
638-
BOOST_ASSERT(target_phantom.forward_segment_id.enabled);
639-
distance += target_phantom.GetForwardDistance();
738+
reverse_heap.Insert(
739+
target_phantom.reverse_segment_id.id,
740+
target_phantom.GetReverseWeightPlusOffset(),
741+
{target_phantom.reverse_segment_id.id, false, target_phantom.GetReverseDistance()});
640742
}
641-
else if (target_phantom.reverse_segment_id.id == unpacked_nodes.back())
743+
744+
const PhantomEndpoints endpoints{source_phantom, target_phantom};
745+
746+
auto distance = searchDistance(
747+
engine_working_data, facade, forward_heap, reverse_heap, {}, weight_upper_bound, endpoints);
748+
749+
if (distance == INVALID_EDGE_DISTANCE)
642750
{
643-
BOOST_ASSERT(target_phantom.reverse_segment_id.enabled);
644-
distance += target_phantom.GetReverseDistance();
751+
return std::numeric_limits<double>::max();
645752
}
646-
647753
return from_alias<double>(distance);
648754
}
649755

0 commit comments

Comments
 (0)