/// <summary> /// Trace back path from destination to source using parent map. /// </summary> private ShortestPathResult <T, W> tracePath(IDiGraph <T> graph, Dictionary <T, T> parentMap, T source, T destination) { //trace the path var pathStack = new Stack <T>(); pathStack.Push(destination); var currentV = destination; while (!Equals(currentV, default(T)) && !Equals(parentMap[currentV], default(T))) { pathStack.Push(parentMap[currentV]); currentV = parentMap[currentV]; } //return result var resultPath = new List <T>(); var resultLength = @operator.DefaultValue; while (pathStack.Count > 0) { resultPath.Add(pathStack.Pop()); } for (var i = 0; i < resultPath.Count - 1; i++) { resultLength = @operator.Sum(resultLength, graph.GetVertex(resultPath[i]).GetOutEdge(graph.GetVertex(resultPath[i + 1])).Weight <W>()); } return(new ShortestPathResult <T, W>(resultPath, resultLength)); }
/// <summary> /// Returns the vertices in Topologically Sorted Order. /// </summary> public List <T> GetTopSort(IDiGraph <T> graph) { var inEdgeMap = new Dictionary <T, int>(); var kahnQueue = new Queue <T>(); foreach (var vertex in graph.VerticesAsEnumberable) { inEdgeMap.Add(vertex.Key, vertex.InEdgeCount); //init queue with vertices having not in edges if (vertex.InEdgeCount == 0) { kahnQueue.Enqueue(vertex.Key); } } //no vertices with zero number of in edges if (kahnQueue.Count == 0) { throw new Exception("Graph has a cycle."); } var result = new List <T>(); int visitCount = 0; //until queue is empty while (kahnQueue.Count > 0) { //cannot exceed vertex number of iterations if (visitCount > graph.VerticesCount) { throw new Exception("Graph has a cycle."); } //pick a neighbour var nextPick = graph.GetVertex(kahnQueue.Dequeue()); //if in edge count is 0 then ready for result if (inEdgeMap[nextPick.Key] == 0) { result.Add(nextPick.Key); } //decrement in edge count for neighbours foreach (var edge in nextPick.OutEdges) { inEdgeMap[edge.TargetVertexKey]--; kahnQueue.Enqueue(edge.TargetVertexKey); } visitCount++; } return(result); }
public List <MinCutEdge <T> > ComputeMinCut(IDiGraph <T> graph, T source, T sink) { 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 IFlowOperators<int> operator implementation during initialization."); } } var edmondsKarpMaxFlow = new EdmondKarpMaxFlow <T, W>(@operator); var maxFlowResidualGraph = edmondsKarpMaxFlow .computeMaxFlowAndReturnResidualGraph(graph, source, sink); //according to Min Max theory //the Min Cut can be obtained by Finding edges //from Reachable Vertices from Source //to unreachable vertices in residual graph var reachableVertices = getReachable(maxFlowResidualGraph, source); var result = new List <MinCutEdge <T> >(); foreach (var vertex in reachableVertices) { foreach (var edge in graph.GetVertex(vertex).OutEdges) { //if unreachable if (!reachableVertices.Contains(edge.TargetVertexKey)) { result.Add(new MinCutEdge <T>(vertex, edge.TargetVertexKey)); } } } return(result); }
/// <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)); }