11
11
#include < boost/assert.hpp>
12
12
13
13
#include < algorithm>
14
+ #include < boost/core/ignore_unused.hpp>
14
15
#include < iterator>
15
16
#include < limits>
16
17
#include < tuple>
@@ -269,10 +270,29 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
269
270
return packed_path;
270
271
}
271
272
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>
273
293
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,
276
296
const Args &...args)
277
297
{
278
298
const auto &partition = facade.GetMultiLevelPartition ();
@@ -281,14 +301,31 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
281
301
282
302
const auto level = getNodeQueryLevel (partition, heapNode.node , args...);
283
303
304
+ static constexpr auto IS_MAP_MATCHING =
305
+ std::is_same_v<typename SearchEngineData<mld::Algorithm>::MapMatchingQueryHeap, Heap>;
306
+
284
307
if (level >= 1 && !heapNode.data .from_clique_arc )
285
308
{
286
- if (DIRECTION == FORWARD_DIRECTION)
309
+ if constexpr (DIRECTION == FORWARD_DIRECTION)
287
310
{
288
311
// Shortcuts in forward direction
289
312
const auto &cell =
290
313
cells.GetCell (metric, level, partition.GetCell (level, heapNode.node ));
291
314
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
+ ();
292
329
for (auto shortcut_weight : cell.GetOutWeight (heapNode.node ))
293
330
{
294
331
BOOST_ASSERT (destination != cell.GetDestinationNodes ().end ());
@@ -298,19 +335,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
298
335
{
299
336
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
300
337
BOOST_ASSERT (to_weight >= heapNode.weight );
301
- const auto toHeapNode = forward_heap. GetHeapNodeIfWasInserted (to);
302
- if (!toHeapNode )
338
+
339
+ if constexpr (IS_MAP_MATCHING )
303
340
{
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});
305
344
}
306
- else if (to_weight < toHeapNode-> weight )
345
+ else
307
346
{
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 });
311
348
}
312
349
}
313
350
++destination;
351
+ if constexpr (IS_MAP_MATCHING)
352
+ {
353
+ ++distance;
354
+ }
314
355
}
315
356
}
316
357
else
@@ -319,6 +360,20 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
319
360
const auto &cell =
320
361
cells.GetCell (metric, level, partition.GetCell (level, heapNode.node ));
321
362
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
+ ();
322
377
for (auto shortcut_weight : cell.GetInWeight (heapNode.node ))
323
378
{
324
379
BOOST_ASSERT (source != cell.GetSourceNodes ().end ());
@@ -328,19 +383,22 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
328
383
{
329
384
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
330
385
BOOST_ASSERT (to_weight >= heapNode.weight );
331
- const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted (to);
332
- if (!toHeapNode)
386
+ if constexpr (IS_MAP_MATCHING)
333
387
{
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});
335
391
}
336
- else if (to_weight < toHeapNode-> weight )
392
+ else
337
393
{
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 });
341
395
}
342
396
}
343
397
++source;
398
+ if constexpr (IS_MAP_MATCHING)
399
+ {
400
+ ++distance;
401
+ }
344
402
}
345
403
}
346
404
}
@@ -367,26 +425,28 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
367
425
const EdgeWeight to_weight =
368
426
heapNode.weight + node_weight + alias_cast<EdgeWeight>(turn_penalty);
369
427
370
- const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted (to);
371
- if (!toHeapNode)
428
+ if constexpr (IS_MAP_MATCHING)
372
429
{
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});
374
436
}
375
- else if (to_weight < toHeapNode-> weight )
437
+ else
376
438
{
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 });
380
440
}
381
441
}
382
442
}
383
443
}
384
444
}
385
445
386
- template <bool DIRECTION, typename Algorithm, typename ... Args>
446
+ template <bool DIRECTION, typename Algorithm, typename Heap, typename ... Args>
387
447
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,
390
450
NodeID &middle_node,
391
451
EdgeWeight &path_upper_bound,
392
452
const std::vector<NodeID> &force_step_nodes,
@@ -429,22 +489,19 @@ using UnpackedNodes = std::vector<NodeID>;
429
489
using UnpackedEdges = std::vector<EdgeID>;
430
490
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
431
491
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)
440
499
{
441
500
if (forward_heap.Empty () || reverse_heap.Empty ())
442
501
{
443
- return std::make_tuple (INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>()) ;
502
+ return {} ;
444
503
}
445
504
446
- const auto &partition = facade.GetMultiLevelPartition ();
447
-
448
505
BOOST_ASSERT (!forward_heap.Empty () && forward_heap.MinKey () < INVALID_EDGE_WEIGHT);
449
506
BOOST_ASSERT (!reverse_heap.Empty () && reverse_heap.MinKey () < INVALID_EDGE_WEIGHT);
450
507
@@ -474,10 +531,33 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
474
531
475
532
// No path found for both target nodes?
476
533
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)
477
553
{
478
554
return std::make_tuple (INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
479
555
}
480
556
557
+ auto [middle, weight] = *searchResult;
558
+
559
+ const auto &partition = facade.GetMultiLevelPartition ();
560
+
481
561
// Get packed path as edges {from node ID, to node ID, from_clique_arc}
482
562
auto packed_path = retrievePackedPathFromHeap (forward_heap, reverse_heap, middle);
483
563
@@ -536,6 +616,31 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
536
616
return std::make_tuple (weight, std::move (unpacked_nodes), std::move (unpacked_edges));
537
617
}
538
618
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
+
539
644
// Alias to be compatible with the CH-based search
540
645
template <typename Algorithm, typename PhantomEndpointT>
541
646
inline void search (SearchEngineData<Algorithm> &engine_working_data,
@@ -593,57 +698,58 @@ void unpackPath(const FacadeT &facade,
593
698
template <typename Algorithm>
594
699
double getNetworkDistance (SearchEngineData<Algorithm> &engine_working_data,
595
700
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,
598
703
const PhantomNode &source_phantom,
599
704
const PhantomNode &target_phantom,
600
705
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
601
706
{
602
707
forward_heap.Clear ();
603
708
reverse_heap.Clear ();
604
709
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 ())
612
711
{
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 ()});
614
717
}
615
718
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 ())
626
720
{
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 ()});
629
726
}
630
727
631
- for ( size_t index = 0 ; index < unpacked_nodes. size () - 1 ; ++index )
728
+ if (target_phantom. IsValidForwardTarget () )
632
729
{
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 ()});
634
734
}
635
735
636
- if (target_phantom.forward_segment_id . id == unpacked_nodes. back ())
736
+ if (target_phantom.IsValidReverseTarget ())
637
737
{
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 ()});
640
742
}
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)
642
750
{
643
- BOOST_ASSERT (target_phantom.reverse_segment_id .enabled );
644
- distance += target_phantom.GetReverseDistance ();
751
+ return std::numeric_limits<double >::max ();
645
752
}
646
-
647
753
return from_alias<double >(distance);
648
754
}
649
755
0 commit comments