/// <summary> /// Get shortest distance to target /// </summary> /// <param name="graph"></param> /// <param name="source"></param> /// <param name="destination"></param> /// <returns></returns> public ShortestPathResult <T, W> GetShortestPath(WeightedDiGraph <T, W> graph, T source, T destination) { //regular argument checks if (graph == null || graph.FindVertex(source) == null || graph.FindVertex(destination) == null) { throw new ArgumentException(); } var progress = new Dictionary <T, W>(); var parentMap = new Dictionary <T, T>(); foreach (var vertex in graph.Vertices) { parentMap.Add(vertex.Key, default(T)); progress.Add(vertex.Key, operators.MaxValue); } progress[source] = operators.DefaultValue; var iterations = graph.Vertices.Count - 1; var updated = true; while (iterations > 0 && updated) { updated = false; foreach (var vertex in graph.Vertices) { //skip not discovered nodes if (progress[vertex.Key].Equals(operators.MaxValue)) { continue; } foreach (var edge in vertex.Value.OutEdges) { var currentDistance = progress[edge.Key.Value]; var newDistance = operators.Sum(progress[vertex.Key], vertex.Value.OutEdges[edge.Key]); if (newDistance.CompareTo(currentDistance) < 0) { updated = true; progress[edge.Key.Value] = newDistance; parentMap[edge.Key.Value] = vertex.Key; } } } iterations--; if (iterations < 0) { throw new Exception("Negative cycle exists in this graph."); } } return(tracePath(graph, parentMap, source, destination)); }
private W findMinWeight(IGraphVertex <T> sourceVertex, IGraphVertex <T> tgtVertex, int remainingVertexCount, HashSet <IGraphVertex <T> > visited, Dictionary <string, W> cache) { var cacheKey = $"{sourceVertex.Key}-{remainingVertexCount}"; if (cache.ContainsKey(cacheKey)) { return(cache[cacheKey]); } visited.Add(sourceVertex); var results = new List <W>(); foreach (var edge in sourceVertex.Edges) { //base case if (edge.TargetVertex.Equals(tgtVertex) && remainingVertexCount == 1) { results.Add(edge.Weight <W>()); break; } if (!visited.Contains(edge.TargetVertex)) { var result = findMinWeight(edge.TargetVertex, tgtVertex, remainingVertexCount - 1, visited, cache); if (!result.Equals(@operator.MaxValue)) { results.Add(@operator.Sum(result, edge.Weight <W>())); } } } visited.Remove(sourceVertex); if (results.Count == 0) { return(@operator.MaxValue); } var min = results.Min(); cache.Add(cacheKey, min); return(min); }
public List <AllPairShortestPathResult <T, W> > GetAllPairShortestPaths(WeightedGraph <T, W> graph) { //we need this vertex array index for generics //since array indices are int and T is unknown type var vertexIndex = new Dictionary <int, T>(); var reverseVertexIndex = new Dictionary <T, int>(); var i = 0; foreach (var vertex in graph.Vertices) { vertexIndex.Add(i, vertex.Key); reverseVertexIndex.Add(vertex.Key, i); i++; } //init all distance to default Weight var result = new W[graph.Vertices.Count, graph.Vertices.Count]; //to trace the path var parent = new T[graph.Vertices.Count, graph.Vertices.Count]; for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { result[i, j] = operators.MaxValue; } } for (i = 0; i < graph.VerticesCount; i++) { result[i, i] = operators.DefaultValue; } //now set the known edge weights to neighbours for (i = 0; i < graph.VerticesCount; i++) { foreach (var edge in graph.Vertices[vertexIndex[i]].Edges) { result[i, reverseVertexIndex[edge.Key.Value]] = edge.Value; parent[i, reverseVertexIndex[edge.Key.Value]] = graph.Vertices[vertexIndex[i]].Value; result[reverseVertexIndex[edge.Key.Value], i] = edge.Value; parent[reverseVertexIndex[edge.Key.Value], i] = edge.Key.Value; } } //here is the meat of this algorithm //if we can reach node i to j via node k and if it is shorter pick that Distance for (int k = 0; k < graph.VerticesCount; k++) { for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { //no path if (result[i, k].Equals(operators.MaxValue) || result[k, j].Equals(operators.MaxValue)) { continue; } var sum = operators.Sum(result[i, k], result[k, j]); if (sum.CompareTo(result[i, j]) >= 0) { continue; } result[i, j] = sum; parent[i, j] = parent[k, j]; } } } //trace path var finalResult = new List <AllPairShortestPathResult <T, W> >(); for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { var source = vertexIndex[i]; var dest = vertexIndex[j]; var distance = result[i, j]; var path = tracePath(result, parent, i, j, vertexIndex, reverseVertexIndex); finalResult.Add(new AllPairShortestPathResult <T, W>(source, dest, distance, path)); } } return(finalResult); }
/// <summary> /// Get shortest distance to target. /// </summary> public ShortestPathResult <T, W> FindShortestPath(IGraph <T> graph, T source, T destination) { //regular argument checks if (graph?.GetVertex(source) == null || graph.GetVertex(destination) == null) { throw new ArgumentException(); } if (this.@operator == null) { throw new ArgumentException("Provide an operator implementation for generic type W during initialization."); } if (!graph.IsWeightedGraph) { if ([email protected]() != typeof(int)) { throw new ArgumentException("Edges of unweighted graphs are assigned an imaginary weight of one (1)." + "Provide an appropriate IShortestPathOperators<int> operator implementation during initialization."); } } //track progress for distance to each Vertex from source var progress = new Dictionary <T, W>(); //trace our current path by mapping current vertex to its Parent var parentMap = new Dictionary <T, T>(); //min heap to pick next closest vertex var minHeap = new FibonacciHeap <MinHeapWrap <T, W> >(); //keep references of heap Node for decrement key operation var heapMapping = new Dictionary <T, MinHeapWrap <T, W> >(); //add vertices to min heap and progress map foreach (var vertex in graph.VerticesAsEnumberable) { //init parent parentMap.Add(vertex.Key, default(T)); //init to max value progress.Add(vertex.Key, @operator.MaxValue); if (vertex.Key.Equals(source)) { continue; } } //start from source vertex as current var current = new MinHeapWrap <T, W>() { Distance = @operator.DefaultValue, Vertex = source }; minHeap.Insert(current); heapMapping.Add(current.Vertex, current); //until heap is empty while (minHeap.Count > 0) { //next min vertex to visit current = minHeap.Extract(); heapMapping.Remove(current.Vertex); //no path exists, so return max value if (current.Distance.Equals(@operator.MaxValue)) { return(new ShortestPathResult <T, W>(null, @operator.MaxValue)); } //visit neighbours of current foreach (var neighbour in graph.GetVertex(current.Vertex).Edges.Where(x => !x.TargetVertexKey.Equals(source))) { //new distance to neighbour var newDistance = @operator.Sum(current.Distance, graph.GetVertex(current.Vertex).GetEdge(neighbour.TargetVertex).Weight <W>()); //current distance to neighbour var existingDistance = progress[neighbour.TargetVertexKey]; //update distance if new is better if (newDistance.CompareTo(existingDistance) < 0) { progress[neighbour.TargetVertexKey] = newDistance; if (!heapMapping.ContainsKey(neighbour.TargetVertexKey)) { var wrap = new MinHeapWrap <T, W>() { Distance = newDistance, Vertex = neighbour.TargetVertexKey }; minHeap.Insert(wrap); heapMapping.Add(neighbour.TargetVertexKey, wrap); } else { //decrement distance to neighbour in heap var decremented = new MinHeapWrap <T, W>() { Distance = newDistance, Vertex = neighbour.TargetVertexKey }; minHeap.UpdateKey(heapMapping[neighbour.TargetVertexKey], decremented); heapMapping[neighbour.TargetVertexKey] = decremented; } //trace parent parentMap[neighbour.TargetVertexKey] = current.Vertex; } } } return(tracePath(graph, parentMap, source, destination)); }
/// <summary> /// Search path to target using the heuristic. /// </summary> public ShortestPathResult <T, W> FindShortestPath(WeightedDiGraph <T, W> graph, T source, T destination) { //regular argument checks if (graph?.FindVertex(source) == null || graph.FindVertex(destination) == null) { throw new ArgumentException(); } //track progress for distance to each Vertex from source var progress = new Dictionary <T, W>(); //trace our current path by mapping current vertex to its Parent var parentMap = new Dictionary <T, T>(); //min heap to pick next closest vertex var minHeap = new FibonacciHeap <AStarWrap <T, W> >(); //keep references of heap Node for decrement key operation var heapMapping = new Dictionary <T, AStarWrap <T, W> >(); //add vertices to min heap and progress map foreach (var vertex in graph.Vertices) { //init parent parentMap.Add(vertex.Key, default(T)); //init to max value progress.Add(vertex.Key, operators.MaxValue); if (vertex.Key.Equals(source)) { continue; } } //start from source vertex as current var current = new AStarWrap <T, W>(heuristic, destination) { Distance = operators.DefaultValue, Vertex = source }; //insert neighbour in heap minHeap.Insert(current); heapMapping[source] = current; //until heap is empty while (minHeap.Count > 0) { //next min vertex to visit current = minHeap.Extract(); heapMapping.Remove(current.Vertex); //no path exists, so return max value if (current.Distance.Equals(operators.MaxValue)) { return(new ShortestPathResult <T, W>(null, operators.MaxValue)); } //visit neighbours of current foreach (var neighbour in graph.Vertices[current.Vertex].OutEdges.Where(x => !x.Key.Value.Equals(source))) { //new distance to neighbour var newDistance = operators.Sum(current.Distance, graph.Vertices[current.Vertex].OutEdges[neighbour.Key]); //current distance to neighbour var existingDistance = progress[neighbour.Key.Value]; //update distance if new is better if (newDistance.CompareTo(existingDistance) < 0) { progress[neighbour.Key.Value] = newDistance; if (heapMapping.ContainsKey(neighbour.Key.Value)) { //decrement distance to neighbour in heap var decremented = new AStarWrap <T, W>(heuristic, destination) { Distance = newDistance, Vertex = neighbour.Key.Value }; minHeap.UpdateKey(heapMapping[neighbour.Key.Value], decremented); heapMapping[neighbour.Key.Value] = decremented; } else { //insert neighbour in heap var discovered = new AStarWrap <T, W>(heuristic, destination) { Distance = newDistance, Vertex = neighbour.Key.Value }; minHeap.Insert(discovered); heapMapping[neighbour.Key.Value] = discovered; } //trace parent parentMap[neighbour.Key.Value] = current.Vertex; } } } return(tracePath(graph, parentMap, source, destination)); }
/// <summary> /// Get shortest distance to target /// </summary> /// <param name="graph"></param> /// <param name="source"></param> /// <param name="destination"></param> /// <returns></returns> public ShortestPathResult <T, W> GetShortestPath(WeightedDiGraph <T, W> graph, T source, T destination) { //regular argument checks if (graph == null || graph.FindVertex(source) == null || graph.FindVertex(destination) == null) { throw new ArgumentException(); } //track progress for distance to each Vertex from source var progress = new Dictionary <T, W>(); //trace our current path by mapping current vertex to its Parent var parentMap = new Dictionary <T, T>(); //min heap to pick next closest vertex var minHeap = new FibornacciMinHeap <MinHeapWrap <T, W> >(); //keep references of heap Node for decrement key operation var heapMapping = new Dictionary <T, FibornacciHeapNode <MinHeapWrap <T, W> > >(); //add vertices to min heap and progress map foreach (var vertex in graph.Vertices) { //init parent parentMap.Add(vertex.Key, default(T)); //init to max value progress.Add(vertex.Key, operators.MaxValue); if (vertex.Key.Equals(source)) { continue; } //construct heap for all vertices with Max Distance as default var wrap = new MinHeapWrap <T, W>() { Distance = operators.MaxValue, Target = vertex.Key }; var heapNode = minHeap.Insert(wrap); heapMapping.Add(vertex.Key, heapNode); } //start from source vertex as current var sourceVertex = graph.Vertices[source]; var current = new MinHeapWrap <T, W>() { Distance = operators.DefaultValue, Target = source }; //until heap is empty while (minHeap.Count > 0) { //no path exists, so return max value if (current.Distance.Equals(operators.MaxValue)) { return(new ShortestPathResult <T, W>(null, operators.MaxValue)); } //visit neighbours of current foreach (var neighbour in graph.Vertices[current.Target].OutEdges) { //new distance to neighbour var newDistance = operators.Sum(current.Distance, graph.Vertices[current.Target].OutEdges[neighbour.Key]); //current distance to neighbour var existingDistance = progress[neighbour.Key.Value]; //update distance if new is better if (newDistance.CompareTo(existingDistance) < 0) { progress[neighbour.Key.Value] = newDistance; heapMapping[neighbour.Key.Value].Value.Distance = newDistance; //decrement distance to neighbour in heap minHeap.DecrementKey(heapMapping[neighbour.Key.Value]); //trace parent parentMap[neighbour.Key.Value] = current.Target; } } //next min vertex to visit current = minHeap.ExtractMin(); } return(tracePath(graph, parentMap, source, destination)); }
public List <AllPairShortestPathResult <T, W> > FindAllPairShortestPaths(IGraph <T> graph) { if (this.@operator == null) { throw new ArgumentException("Provide an operator implementation for generic type W during initialization."); } if (!graph.IsWeightedGraph) { if ([email protected]() != typeof(int)) { throw new ArgumentException("Edges of unweighted graphs are assigned an imaginary weight of one (1)." + "Provide an appropriate IShortestPathOperators<int> operator implementation during initialization."); } } //we need this vertex array index for generics //since array indices are int and T is unknown type var vertexIndex = new Dictionary <int, T>(); var reverseVertexIndex = new Dictionary <T, int>(); var i = 0; foreach (var vertex in graph.VerticesAsEnumberable) { vertexIndex.Add(i, vertex.Key); reverseVertexIndex.Add(vertex.Key, i); i++; } //init all distance to default Weight var result = new W[graph.VerticesCount, graph.VerticesCount]; //to trace the path var parent = new T[graph.VerticesCount, graph.VerticesCount]; for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { result[i, j] = @operator.MaxValue; } } for (i = 0; i < graph.VerticesCount; i++) { result[i, i] = @operator.DefaultValue; } //now set the known edge weights to neighbours for (i = 0; i < graph.VerticesCount; i++) { foreach (var edge in graph.GetVertex(vertexIndex[i]).Edges) { result[i, reverseVertexIndex[edge.TargetVertexKey]] = edge.Weight <W>(); parent[i, reverseVertexIndex[edge.TargetVertexKey]] = graph.GetVertex(vertexIndex[i]).Key; result[reverseVertexIndex[edge.TargetVertexKey], i] = edge.Weight <W>(); parent[reverseVertexIndex[edge.TargetVertexKey], i] = edge.TargetVertexKey; } } //here is the meat of this algorithm //if we can reach node i to j via node k and if it is shorter pick that Distance for (int k = 0; k < graph.VerticesCount; k++) { for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { //no path if (result[i, k].Equals(@operator.MaxValue) || result[k, j].Equals(@operator.MaxValue)) { continue; } var sum = @operator.Sum(result[i, k], result[k, j]); if (sum.CompareTo(result[i, j]) >= 0) { continue; } result[i, j] = sum; parent[i, j] = parent[k, j]; } } } //trace path var finalResult = new List <AllPairShortestPathResult <T, W> >(); for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { var source = vertexIndex[i]; var dest = vertexIndex[j]; var distance = result[i, j]; var path = tracePath(result, parent, i, j, vertexIndex, reverseVertexIndex); finalResult.Add(new AllPairShortestPathResult <T, W>(source, dest, distance, path)); } } return(finalResult); }
/// <summary> /// Find shortest distance to target. /// </summary> public ShortestPathResult <T, W> FindShortestPath(IDiGraph <T> graph, T source, T destination) { //regular argument checks if (graph == null || graph.GetVertex(source) == null || graph.GetVertex(destination) == null) { throw new ArgumentException("Empty Graph or invalid source/destination."); } if (this.@operator == null) { throw new ArgumentException("Provide an operator implementation for generic type W during initialization."); } if (!graph.IsWeightedGraph) { if ([email protected]() != typeof(int)) { throw new ArgumentException("Edges of unweighted graphs are assigned an imaginary weight of one (1)." + "Provide an appropriate IShortestPathOperators<int> operator implementation during initialization."); } } var progress = new Dictionary <T, W>(); var parentMap = new Dictionary <T, T>(); foreach (var vertex in graph.VerticesAsEnumberable) { parentMap.Add(vertex.Key, default(T)); progress.Add(vertex.Key, @operator.MaxValue); } progress[source] = @operator.DefaultValue; var iterations = graph.VerticesCount - 1; var updated = true; while (iterations > 0 && updated) { updated = false; foreach (var vertex in graph.VerticesAsEnumberable) { //skip not discovered nodes if (progress[vertex.Key].Equals(@operator.MaxValue)) { continue; } foreach (var edge in vertex.OutEdges) { var currentDistance = progress[edge.TargetVertexKey]; var newDistance = @operator.Sum(progress[vertex.Key], vertex.GetOutEdge(edge.TargetVertex).Weight <W>()); if (newDistance.CompareTo(currentDistance) < 0) { updated = true; progress[edge.TargetVertexKey] = newDistance; parentMap[edge.TargetVertexKey] = vertex.Key; } } } iterations--; if (iterations < 0) { throw new Exception("Negative cycle exists in this graph."); } } return(tracePath(graph, parentMap, source, destination)); }
public ShortestPathResult <T, W> GetShortestPath(WeightedDiGraph <T, W> graph, T source, T destination) { if (graph == null || graph.FindVertex(source) == null || graph.FindVertex(destination) == null) { throw new ArgumentException(); } var progress = new Dictionary <T, W>(); var parentMap = new Dictionary <T, T>(); var minHeap = new FibornacciMinHeap <MinHeapWrap <T, W> >(); var heapMapping = new Dictionary <T, FibornacciHeapNode <MinHeapWrap <T, W> > >(); foreach (var vertex in graph.Vertices) { parentMap.Add(vertex.Key, default(T)); progress.Add(vertex.Key, operators.MaxValue); if (vertex.Key.Equals(source)) { continue; } var wrap = new MinHeapWrap <T, W>() { Distance = operators.MaxValue, Target = vertex.Key }; var heapNode = minHeap.Insert(wrap); heapMapping.Add(vertex.Key, heapNode); } var sourceVertex = graph.Vertices[source]; var current = new MinHeapWrap <T, W>() { Distance = operators.DefaultValue, Target = source }; while (minHeap.Count > 0) { if (current.Distance.Equals(operators.MaxValue)) { return(new ShortestPathResult <T, W>(null, operators.MaxValue)); } foreach (var neighbour in graph.Vertices[current.Target].OutEdges) { var newDistance = operators.Sum(current.Distance, graph.Vertices[current.Target].OutEdges[neighbour.Key]); var existingDistance = progress[neighbour.Key.Value]; if (newDistance.CompareTo(existingDistance) < 0) { progress[neighbour.Key.Value] = newDistance; heapMapping[neighbour.Key.Value].Value.Distance = newDistance; minHeap.DecrementKey(heapMapping[neighbour.Key.Value]); parentMap[neighbour.Key.Value] = current.Target; } } current = minHeap.ExtractMin(); } return(tracePath(graph, parentMap, source, destination)); }
public List <AllPairShortestPathResult <T, W> > GetAllPairShortestPaths(WeightedGraph <T, W> graph) { var vertexIndex = new Dictionary <int, T>(); var reverseVertexIndex = new Dictionary <T, int>(); int i = 0; foreach (var vertex in graph.Vertices) { vertexIndex.Add(i, vertex.Key); reverseVertexIndex.Add(vertex.Key, i); i++; } var result = new W[graph.Vertices.Count, graph.Vertices.Count]; var parent = new T[graph.Vertices.Count, graph.Vertices.Count]; for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { result[i, j] = operators.MaxValue; } } for (i = 0; i < graph.VerticesCount; i++) { result[i, i] = operators.DefaultValue; } for (i = 0; i < graph.VerticesCount; i++) { foreach (var edge in graph.Vertices[vertexIndex[i]].Edges) { result[i, reverseVertexIndex[edge.Key.Value]] = edge.Value; parent[i, reverseVertexIndex[edge.Key.Value]] = graph.Vertices[vertexIndex[i]].Value; result[reverseVertexIndex[edge.Key.Value], i] = edge.Value; parent[reverseVertexIndex[edge.Key.Value], i] = edge.Key.Value; } } for (int k = 0; k < graph.VerticesCount; k++) { for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { if (result[i, k].Equals(operators.MaxValue) || result[k, j].Equals(operators.MaxValue)) { continue; } var sum = operators.Sum(result[i, k], result[k, j]); if (sum.CompareTo(result[i, j]) < 0) { result[i, j] = sum; parent[i, j] = parent[k, j]; } } } } var finalResult = new List <AllPairShortestPathResult <T, W> >(); for (i = 0; i < graph.VerticesCount; i++) { for (int j = 0; j < graph.VerticesCount; j++) { var source = vertexIndex[i]; var dest = vertexIndex[j]; var distance = result[i, j]; var path = tracePath(result, parent, i, j, vertexIndex, reverseVertexIndex); finalResult.Add(new AllPairShortestPathResult <T, W>(source, dest, distance, path)); } } return(finalResult); }