From e0ad6d09d6971ab52ac9378b3adb92c179a07762 Mon Sep 17 00:00:00 2001 From: mitchellri Date: Sat, 21 Sep 2019 17:07:15 -0700 Subject: [PATCH 1/2] AStar add --- src/Dijkstra.NET/ShortestPath/AStar.cs | 60 +++++++++++++++++++ .../ShortestPath/DijkstraExtensions.cs | 23 +++++++ src/Dijkstra.NET/ShortestPath/NodeComparer.cs | 15 ++++- 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/Dijkstra.NET/ShortestPath/AStar.cs diff --git a/src/Dijkstra.NET/ShortestPath/AStar.cs b/src/Dijkstra.NET/ShortestPath/AStar.cs new file mode 100644 index 0000000..a2bbb50 --- /dev/null +++ b/src/Dijkstra.NET/ShortestPath/AStar.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using Dijkstra.NET.Graph; + +namespace Dijkstra.NET.ShortestPath +{ + internal static class AStar + { + public static ShortestPathResult GetShortestPath(IDijkstraGraph graph, uint from, uint to, Func heuristic, int depth) + { + var path = new Dictionary(); + var distance = new Dictionary {[from] = 0}; + var d = new Dictionary {[from] = 0}; + var q = new SortedSet(new[] {from}, new NodeComparer(distance, heuristic)); + var current = new HashSet(); + + int Distance(uint key) + { + return distance.ContainsKey(key) ? distance[key] : Int32.MaxValue; + } + + do + { + uint u = q.Deque(); + + if (u == to) + { + return new ShortestPathResult(from, to, distance[u], path); + } + + current.Remove(u); + + if (depth == d[u]) + { + continue; + } + + graph[u]((node, cost) => + { + if (Distance(node) > Distance(u) + cost) + { + if (current.Contains(node)) + { + q.Remove(node); + } + + distance[node] = Distance(u) + cost; + q.Add(node); + current.Add(node); + path[node] = u; + d[node] = d[u] + 1; + } + }); + + } while (q.Count > 0 && depth > 0); + + return new ShortestPathResult(from, to); + } + } +} \ No newline at end of file diff --git a/src/Dijkstra.NET/ShortestPath/DijkstraExtensions.cs b/src/Dijkstra.NET/ShortestPath/DijkstraExtensions.cs index 3fc200a..ba1730b 100644 --- a/src/Dijkstra.NET/ShortestPath/DijkstraExtensions.cs +++ b/src/Dijkstra.NET/ShortestPath/DijkstraExtensions.cs @@ -17,6 +17,16 @@ public static class DijkstraExtensions public static ShortestPathResult Dijkstra(this IDijkstraGraph graph, uint from, uint to) => Dijkstra(graph, from, to, Int32.MaxValue); + /// + /// Get path from @from to @to + /// + /// Source graph + /// Start node + /// End node + /// Value with path + public static ShortestPathResult AStar(this IDijkstraGraph graph, uint from, uint to, Func heuristic) + => AStar(graph, from, to, heuristic, Int32.MaxValue); + /// /// Get path from @from to @to /// @@ -29,5 +39,18 @@ public static ShortestPathResult Dijkstra(this IDijkstraGraph graph, uint from, { return ShortestPath.Dijkstra.GetShortestPath(graph, from, to, depth); } + + /// + /// Get path from @from to @to + /// + /// Source graph + /// Start node + /// End node + /// Depth of path + /// Value with path + public static ShortestPathResult AStar(this IDijkstraGraph graph, uint from, uint to, Func heuristic, int depth) + { + return ShortestPath.AStar.GetShortestPath(graph, from, to, heuristic, depth); + } } } \ No newline at end of file diff --git a/src/Dijkstra.NET/ShortestPath/NodeComparer.cs b/src/Dijkstra.NET/ShortestPath/NodeComparer.cs index 57de565..519f515 100644 --- a/src/Dijkstra.NET/ShortestPath/NodeComparer.cs +++ b/src/Dijkstra.NET/ShortestPath/NodeComparer.cs @@ -6,16 +6,27 @@ namespace Dijkstra.NET.ShortestPath internal class NodeComparer : IComparer { private readonly IDictionary _distance; + private readonly Func _heuristic; public NodeComparer(IDictionary distance) { _distance = distance; + _heuristic = null; + } + public NodeComparer(IDictionary distance, Func heuristic) + { + _distance = distance; + _heuristic = heuristic; } public int Compare(uint x, uint y) { - int xDistance = _distance.ContainsKey(x) ? _distance[x] : Int32.MaxValue; - int yDistance = _distance.ContainsKey(y) ? _distance[y] : Int32.MaxValue; + int xDistance = _distance.ContainsKey(x) ? + _heuristic is null ? _distance[x] : _distance[x] + _heuristic(x, y) + : Int32.MaxValue; + int yDistance = _distance.ContainsKey(y) ? + _heuristic is null ? _distance[y] : _distance[y] + _heuristic(y, x) + : Int32.MaxValue; int comparer = xDistance.CompareTo(yDistance); From 5097f23e05f7b01aee27290ca809667590883467 Mon Sep 17 00:00:00 2001 From: mitchellri Date: Sun, 22 Mar 2020 22:25:47 -0700 Subject: [PATCH 2/2] Refactor heuristic node comparing --- src/Dijkstra.NET/ShortestPath/AStar.cs | 2 +- .../ShortestPath/HeuristicNodeComparer.cs | 30 +++++++++++++++++++ src/Dijkstra.NET/ShortestPath/NodeComparer.cs | 21 ++++--------- 3 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 src/Dijkstra.NET/ShortestPath/HeuristicNodeComparer.cs diff --git a/src/Dijkstra.NET/ShortestPath/AStar.cs b/src/Dijkstra.NET/ShortestPath/AStar.cs index a2bbb50..e1b7d5a 100644 --- a/src/Dijkstra.NET/ShortestPath/AStar.cs +++ b/src/Dijkstra.NET/ShortestPath/AStar.cs @@ -11,7 +11,7 @@ public static ShortestPathResult GetShortestPath(IDijkstraGraph graph, uint from var path = new Dictionary(); var distance = new Dictionary {[from] = 0}; var d = new Dictionary {[from] = 0}; - var q = new SortedSet(new[] {from}, new NodeComparer(distance, heuristic)); + var q = new SortedSet(new[] {from}, new HeuristicNodeComparer(distance, heuristic)); var current = new HashSet(); int Distance(uint key) diff --git a/src/Dijkstra.NET/ShortestPath/HeuristicNodeComparer.cs b/src/Dijkstra.NET/ShortestPath/HeuristicNodeComparer.cs new file mode 100644 index 0000000..03ca151 --- /dev/null +++ b/src/Dijkstra.NET/ShortestPath/HeuristicNodeComparer.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace Dijkstra.NET.ShortestPath +{ + internal class HeuristicNodeComparer : NodeComparer + { + private readonly Func _heuristic; + + public HeuristicNodeComparer(IDictionary distance, Func heuristic) : base(distance) + { + _heuristic = heuristic; + } + + public override int Compare(uint x, uint y) + { + int xDistance = _distance.ContainsKey(x) ? _distance[x] + _heuristic(x, y) : Int32.MaxValue; + int yDistance = _distance.ContainsKey(y) ? _distance[y] + _heuristic(y, x) : Int32.MaxValue; + + int comparer = xDistance.CompareTo(yDistance); + + if (comparer == 0) + { + return x.CompareTo(y); + } + + return comparer; + } + } +} diff --git a/src/Dijkstra.NET/ShortestPath/NodeComparer.cs b/src/Dijkstra.NET/ShortestPath/NodeComparer.cs index 519f515..6400311 100644 --- a/src/Dijkstra.NET/ShortestPath/NodeComparer.cs +++ b/src/Dijkstra.NET/ShortestPath/NodeComparer.cs @@ -5,28 +5,17 @@ namespace Dijkstra.NET.ShortestPath { internal class NodeComparer : IComparer { - private readonly IDictionary _distance; - private readonly Func _heuristic; + protected readonly IDictionary _distance; public NodeComparer(IDictionary distance) { _distance = distance; - _heuristic = null; - } - public NodeComparer(IDictionary distance, Func heuristic) - { - _distance = distance; - _heuristic = heuristic; } - public int Compare(uint x, uint y) + public virtual int Compare(uint x, uint y) { - int xDistance = _distance.ContainsKey(x) ? - _heuristic is null ? _distance[x] : _distance[x] + _heuristic(x, y) - : Int32.MaxValue; - int yDistance = _distance.ContainsKey(y) ? - _heuristic is null ? _distance[y] : _distance[y] + _heuristic(y, x) - : Int32.MaxValue; + int xDistance = _distance.ContainsKey(x) ? _distance[x] : Int32.MaxValue; + int yDistance = _distance.ContainsKey(y) ? _distance[y] : Int32.MaxValue; int comparer = xDistance.CompareTo(yDistance); @@ -38,4 +27,4 @@ public int Compare(uint x, uint y) return comparer; } } -} +} \ No newline at end of file