< Summary

Class:Itinero.Routing.Flavours.Dijkstra.Bidirectional.DijkstraAlgorithm
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Routing/Flavours/Dijkstra/Bidirectional/DijkstraAlgorithm.cs
Covered lines:82
Uncovered lines:9
Coverable lines:91
Total lines:170
Line coverage:90.1% (82 of 91)
Covered branches:43
Total branches:56
Branch coverage:76.7% (43 of 56)
Tag:238_19435726042

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor(...)100%1100%
get_RoutingNetwork()100%1100%
TryGetVisit(...)100%1100%
Clear()100%10%
GetVisit(...)100%1100%
Push(...)50%2100%
Pop()75%475%
GetPreviousEdges()75%4100%
CanTurn(...)75%2496.29%
Step(...)81.81%22100%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Routing/Flavours/Dijkstra/Bidirectional/DijkstraAlgorithm.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using Itinero.Network;
 5using Itinero.Network.Enumerators.Edges;
 6using Itinero.Routing.DataStructures;
 7
 8namespace Itinero.Routing.Flavours.Dijkstra.Bidirectional;
 9
 10internal abstract class DijkstraAlgorithm
 11{
 2812    private readonly PathTree _tree = new();
 2813    private readonly Dictionary<VertexId, (uint p, double cost)> _settled = [];
 2814    private readonly BinaryHeap<uint> _heap = new();
 15    protected readonly RoutingNetworkEdgeEnumerator _enumerator;
 16    protected readonly RoutingNetwork _network;
 17
 2818    protected DijkstraAlgorithm(RoutingNetwork network)
 2819    {
 2820        _network = network;
 21
 2822        _enumerator = network.GetEdgeEnumerator();
 2823    }
 24
 3425    internal RoutingNetwork RoutingNetwork => _network;
 26
 27    protected abstract bool OnQueued(uint visit, EdgeId edge, (double cost, double turnCost) edgeCost, VertexId vertex, 
 28
 29    protected abstract bool OnSettled(uint visit, VertexId vertex, double cost);
 30
 31    protected abstract (double cost, double turnCost) GetCost(RoutingNetworkEdgeEnumerator edgeEnumerator,
 32        IEnumerable<(EdgeId edge, byte? turn)> previousEdges);
 33
 34    internal bool TryGetVisit(VertexId vertex, out (uint p, double cost) visit)
 7035    {
 7036        return _settled.TryGetValue(vertex, out visit);
 7037    }
 38
 39    internal void Clear()
 040    {
 041        _heap.Clear();
 042        _tree.Clear();
 043        _settled.Clear();
 044    }
 45
 46    internal (VertexId vertex, EdgeId edge, bool forward, byte? head, uint previousPointer) GetVisit(uint pointer)
 1547    {
 1548        return _tree.GetVisit(pointer);
 1549    }
 50
 51    internal uint Push(EdgeId edgeId, bool forward, double cost)
 5652    {
 5653        if (!_enumerator.MoveTo(edgeId, forward)) throw new Exception($"Edge not found!");
 54
 5655        var v = _tree.AddVisit(_enumerator, uint.MaxValue);
 5656        _heap.Push(v, cost);
 5657        return v;
 5658    }
 59
 60    internal (uint pointer, (VertexId vertex, EdgeId edge, bool forward, byte? head, uint previousPointer) visit, double
 7861    {
 7862        var currentPointer = _heap.Pop(out var currentCost);
 7863        var currentVisit = _tree.GetVisit(currentPointer);
 7864        while (!_settled.TryAdd(currentVisit.vertex, (currentPointer, currentCost)))
 865        {
 866            currentPointer = uint.MaxValue;
 1667            if (_heap.Count == 0) break;
 68
 069            currentPointer = _heap.Pop(out currentCost);
 070            currentVisit = _tree.GetVisit(currentPointer);
 071        }
 72
 7873        return (currentPointer, currentVisit, currentCost);
 7874    }
 75
 76    internal IEnumerable<(EdgeId edge, byte? turn)> GetPreviousEdges(uint pointer, int maxCount = 16)
 1477    {
 1478        using var previous = _tree.GetPreviousEdges(pointer).GetEnumerator();
 3679        while (previous.MoveNext())
 2280        {
 2281            if (maxCount <= 0) yield break;
 2282            maxCount--;
 83
 2284            yield return previous.Current;
 2285        }
 1486    }
 87
 88    internal bool CanTurn(VertexId vertex,
 89        IReadOnlyList<(EdgeId edge, byte? turn)> previousEdges, IReadOnlyList<EdgeId> nextEdges)
 790    {
 791        if (nextEdges.Count == 0) throw new Exception("Not a turn");
 792        if (previousEdges.Count == 0) throw new Exception("Not a turn");
 93
 94        // no U-turns
 795        if (nextEdges[0] == previousEdges[0].edge) return false;
 96
 97        // check neighbours.
 798        var nextChecked = 0;
 799        var edges = previousEdges.ToList();
 11100        while (nextChecked < nextEdges.Count)
 8101        {
 8102            var nextEdge = nextEdges[nextChecked];
 8103            var edgeFound = false;
 104
 8105            if (!_enumerator.MoveTo(vertex)) return false;
 8106            while (_enumerator.MoveNext())
 8107            {
 108                // filter out if U-turns or visits on the same edge.
 8109                var neighbourEdge = _enumerator.EdgeId;
 8110                if (neighbourEdge != nextEdge) continue;
 111
 112                // gets the cost of the current edge.
 8113                var (_, turnCost) = this.GetCost(_enumerator, edges);
 114
 12115                if (turnCost is >= double.MaxValue or < 0) return false;
 116
 4117                edges.Add((_enumerator.EdgeId, _enumerator.HeadOrder));
 4118                vertex = _enumerator.Head;
 4119                edgeFound = true;
 4120                break;
 121            }
 122
 4123            if (!edgeFound) return false;
 124
 4125            nextChecked++;
 4126        }
 127
 128        // if all edges are checked, the turn is possible.
 6129        if (nextChecked >= nextEdges.Count) return true;
 130
 131        // target edge not found as neighbour.
 0132        return false;
 7133    }
 134
 135    internal bool Step(uint pointer, (VertexId vertex, EdgeId edge, bool forward, byte? head, uint previousPointer) visi
 70136    {
 137        // log settled and see if we need to continue.
 70138        if (!this.OnSettled(pointer, visit.vertex, cost)) return false;
 139
 140        // check neighbours.
 70141        if (!_enumerator.MoveTo(visit.vertex)) return true;
 164142        while (_enumerator.MoveNext())
 94143        {
 144            // filter out if U-turns or visits on the same edge.
 94145            var neighbourEdge = _enumerator.EdgeId;
 164146            if (neighbourEdge == visit.edge) continue;
 147
 148            // gets the cost of the current edge.
 24149            var (neighbourCost, turnCost) = this.GetCost(_enumerator, _tree.GetPreviousEdges(pointer));
 150
 151            // ignore if cost is 0 or infinite.
 24152            if (neighbourCost is >= double.MaxValue or <= 0) continue;
 32153            if (turnCost is >= double.MaxValue or < 0) continue;
 154
 155            // check if the vertex has to be queued.
 16156            var totalCost = neighbourCost + cost + turnCost;
 157
 158            // add visit if not added yet.
 16159            var neighbourPointer = _tree.AddVisit(_enumerator, pointer);
 160
 161            // call the on queued method and allow checking for stopping conditions.
 16162            if (!this.OnQueued(neighbourPointer, _enumerator.EdgeId, (neighbourCost, turnCost), _enumerator.Head, totalC
 163
 164            // add visit to heap.
 16165            _heap.Push(neighbourPointer, totalCost);
 16166        }
 167
 70168        return true;
 70169    }
 170}