FindStronglyConnectedComponents(IDiGraph <T> graph) { var visited = new HashSet <T>(); var finishStack = new Stack <T>(); //step one - create DFS finish visit stack foreach (var vertex in graph.VerticesAsEnumberable) { if (!visited.Contains(vertex.Key)) { kosarajuStep1(vertex, visited, finishStack); } } //reverse edges var reverseGraph = reverseEdges(graph); visited.Clear(); var result = new List <List <T> >(); //now pop finish stack and gather the components while (finishStack.Count > 0) { var currentVertex = reverseGraph.GetVertex(finishStack.Pop()); if (!visited.Contains(currentVertex.Key)) { result.Add(kosarajuStep2(currentVertex, visited, finishStack, new List <T>())); } } return(result); }
private void Dfs(IDiGraph g, int v) { onStack[v] = true; marked[v] = true; foreach (int w in g.Adj(v)) { if (HasCycle()) { return; } else if (!marked[w]) { edgeTo[w] = v; Dfs(g, w); } else if (onStack[w]) { cycle = new Chapter1.Stack <int>(); for (int x = v; x != w; x = edgeTo[x]) { cycle.Push(x); } cycle.Push(w); cycle.Push(v); } onStack[v] = false; } }
/// <summary> /// Clones this graph and creates a residual graph. /// </summary> private WeightedDiGraph <T, W> createResidualGraph(IDiGraph <T> graph) { var newGraph = new WeightedDiGraph <T, W>(); //clone graph vertices foreach (var vertex in graph.VerticesAsEnumberable) { newGraph.AddVertex(vertex.Key); } //clone edges foreach (var vertex in graph.VerticesAsEnumberable) { //Use either OutEdges or InEdges for cloning //here we use OutEdges foreach (var edge in vertex.OutEdges) { //original edge newGraph.AddEdge(vertex.Key, edge.TargetVertexKey, edge.Weight <W>()); //add a backward edge for residual graph with edge value as default(W) newGraph.AddEdge(edge.TargetVertexKey, vertex.Key, default(W)); } } return(newGraph); }
/// <summary> /// Augment current Path to residual Graph. /// </summary> private W augmentResidualGraph(IDiGraph <T> graph, WeightedDiGraph <T, W> residualGraph, List <T> path) { var min = @operator.MaxWeight; for (int i = 0; i < path.Count - 1; i++) { var vertex1 = residualGraph.FindVertex(path[i]); var vertex2 = residualGraph.FindVertex(path[i + 1]); var edgeValue = vertex1.OutEdges[vertex2]; if (@operator.Comparer(min, edgeValue) > 0) { min = edgeValue; } } //augment path for (int i = 0; i < path.Count - 1; i++) { var vertex_1 = residualGraph.FindVertex(path[i]); var vertex_2 = residualGraph.FindVertex(path[i + 1]); //substract from forward paths vertex_1.OutEdges[vertex_2] = @operator.SubstractWeights(vertex_1.OutEdges[vertex_2], min); //add for backward paths vertex_2.OutEdges[vertex_1] = @operator.AddWeights(vertex_2.OutEdges[vertex_1], min); } return(min); }
} //图 public SymbolDiGraph(string filename, string delim, SearchTableOptions options = SearchTableOptions.SequantialST) { st = SearchTableExamples.CreateSearchTable <string, int?>(options); Scanner scanner = new Scanner(new StreamReader(File.OpenRead(filename))); while (scanner.HasNextLine()) //构造索引 { string[] a = scanner.ReadLine().Split(delim); //为每个不同的字符串关联一个索引 for (int i = 0; i < a.Length; i++) { if (!st.Contains(a[i])) { st.Put(a[i], st.Size); } } } keys = new string[st.Size]; //用来获得顶点名反向索引 foreach (string name in st.Keys()) { keys[st.Get(name) ?? -1] = name; } G = new DiGraph(st.Size); scanner = new Scanner(new StreamReader(File.OpenRead(filename))); //第二遍 while (scanner.HasNextLine()) { string[] a = scanner.ReadLine().Split(delim); //将每一行的第一个顶点和该行的其他顶点相连 int v = st.Get(a[0]) ?? -1; for (int i = 1; i < a.Length; i++) { G.AddEdge(v, st.Get(a[i]) ?? -1); } } }
/// <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> /// Creates a new <see cref="DiGraph{T,TWeight}"/> using an existing graph. /// </summary> /// <param name="graph">the existing graph</param> public DiGraph(IDiGraph <T, TWeight> graph) : this(graph.DefaultEdgeWeight) { _vertices = new HashSet <T>(graph.Vertices); foreach (var edge in graph.Edges) { AddEdge(edge.SourceVertex, edge.TargetVertex, edge.Weight); } }
public TransitiveClosure(IDiGraph G) { all = new DirectedDFS[G.V]; for (int v = 0; v < G.V; v++) { all[v] = new DirectedDFS(G, v); } }
public Algorithm(IDiGraph <T, TWeight> graph) { _graph = graph; _metadataLookup = graph.Vertices.ToDictionary(n => n, n => new Metadata(-1, -1, false)); _index = 0; _stack = new Stack <T>(); }
/// <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); }
private Chapter1.Stack <int> Init(IDiGraph G) { DirectedCycle cyclefinder = new DirectedCycle(G); if (!cyclefinder.HasCycle()) { DepthFirstOrder dfs = new DepthFirstOrder(G); return(dfs.ReversePost); } return(null); }
private void Dfs(IDiGraph g, int s) { marked[s] = true; foreach (int w in g.Adj(s)) { if (!marked[w]) { Dfs(g, w); } } }
//在G中找到从source中的所有顶点可达的所有顶点 public DirectedDFS(IDiGraph G, IEnumerable <int> sources) { marked = new bool[G.V]; foreach (int s in sources) { if (!marked[s]) { Dfs(G, s); } } }
private bool[] onStack; //递归调用的栈上的所有顶点 public DirectedCycle(IDiGraph G) { onStack = new bool[G.V]; edgeTo = new int[G.V]; marked = new bool[G.V]; for (int v = 0; v < G.V; v++) { if (!marked[v]) { Dfs(G, v); } } }
private void Dfs(IDiGraph g, int v) { Pre.Enqueue(v); marked[v] = true; foreach (int w in g.Adj(v)) { if (!marked[w]) { Dfs(g, w); } } Post.Enqueue(v); ReversePost.Push(v); }
} //顶点的逆后续 public DepthFirstOrder(IDiGraph G) { Pre = new Queue <int>(); Post = new Queue <int>(); ReversePost = new Stack <int>(); marked = new bool[G.V]; for (int v = 0; v < G.V; v++) { if (!marked[v]) { Dfs(G, v); } } }
private void validateOperator(IDiGraph <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 IFlowOperators<int> operator implementation during initialization."); } } }
public KosarajuSCC(IDiGraph G) { this.G = G; marked = new bool[G.V]; id = new int[G.V]; DepthFirstOrder order = new DepthFirstOrder(G.Reverse()); foreach (int s in order.ReversePost) { if (!marked[s]) { Dfs(G, s); Count++; } } }
/// <summary> /// Returns true if a cycle exists /// </summary> public bool HasCycle(IDiGraph <T> graph) { var visiting = new HashSet <T>(); var visited = new HashSet <T>(); foreach (var vertex in graph.VerticesAsEnumberable) { if (!visited.Contains(vertex.Key)) { if (dfs(vertex, visited, visiting)) { return(true); } } } return(false); }
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); }
private WeightedDiGraph <T, W> clone(IDiGraph <T> graph) { var newGraph = new WeightedDiGraph <T, W>(); foreach (var vertex in graph.VerticesAsEnumberable) { newGraph.AddVertex(vertex.Key); } foreach (var vertex in graph.VerticesAsEnumberable) { foreach (var edge in vertex.OutEdges) { newGraph.AddEdge(vertex.Key, edge.TargetVertexKey, edge.Weight <W>()); } } return(newGraph); }
/// <summary> /// Compute max flow by searching a path /// and then augmenting the residual graph until /// no more path exists in residual graph with possible flow. /// </summary> public W ComputeMaxFlow(IDiGraph <T> graph, T source, T sink) { validateOperator(graph); var residualGraph = createResidualGraph(graph); var path = DFS(residualGraph, source, sink); var result = @operator.defaultWeight; while (path != null) { result = @operator.AddWeights(result, augmentResidualGraph(residualGraph, path)); path = DFS(residualGraph, source, sink); } return(result); }
/// <summary> /// Create a clone graph with reverse edge directions. /// </summary> private IDiGraph <T> reverseEdges(IDiGraph <T> graph) { var newGraph = new DiGraph <T>(); foreach (var vertex in graph.VerticesAsEnumberable) { newGraph.AddVertex(vertex.Key); } foreach (var vertex in graph.VerticesAsEnumberable) { foreach (var edge in vertex.OutEdges) { //reverse edge newGraph.AddEdge(edge.TargetVertexKey, vertex.Key); } } return(newGraph); }
/// <summary> /// Return all flow Paths. /// </summary> public List <List <T> > ComputeMaxFlowAndReturnFlowPath(IDiGraph <T> graph, T source, T sink) { validateOperator(graph); var residualGraph = createResidualGraph(graph); List <T> path = DFS(residualGraph, source, sink); var flow = @operator.defaultWeight; var result = new List <List <T> >(); while (path != null) { result.Add(path); flow = @operator.AddWeights(flow, augmentResidualGraph(residualGraph, path)); path = DFS(residualGraph, source, sink); } return(result); }
/// <summary> /// Rreturns a list of Strongly Connected components in this graph. /// </summary> public List <List <T> > FindStronglyConnectedComponents(IDiGraph <T> graph) { var result = new List <List <T> >(); var discoveryTimeMap = new Dictionary <T, int>(); var lowTimeMap = new Dictionary <T, int>(); var pathStack = new Stack <T>(); var pathStackMap = new HashSet <T>(); var discoveryTime = 0; foreach (var vertex in graph.VerticesAsEnumberable) { if (!discoveryTimeMap.ContainsKey(vertex.Key)) { DFS(vertex, result, discoveryTimeMap, lowTimeMap, pathStack, pathStackMap, ref discoveryTime); } } return(result); }
/// <summary> /// Returns the vertices in Topologically Sorted Order. /// </summary> public List <T> GetTopSort(IDiGraph <T> graph) { var pathStack = new Stack <T>(); var visited = new HashSet <T>(); //we need a loop so that we can reach all vertices foreach (var vertex in graph.VerticesAsEnumberable) { if (!visited.Contains(vertex.Key)) { dfs(vertex, visited, pathStack); } } //now just pop the stack to result var result = new List <T>(); while (pathStack.Count > 0) { result.Add(pathStack.Pop()); } return(result); }
FindAllPairShortestPaths(IDiGraph <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 IJohnsonsShortestPathOperators<T, int> operator implementation during initialization."); } } var workGraph = clone(graph); //add an extra vertex with zero weight edge to all nodes var randomVetex = @operator.RandomVertex(); if (workGraph.Vertices.ContainsKey(randomVetex)) { throw new Exception("Random Vertex is not unique for given graph."); } workGraph.AddVertex(randomVetex); foreach (var vertex in workGraph.Vertices) { workGraph.AddEdge(randomVetex, vertex.Key, @operator.DefaultValue); } //now compute shortest path from random vertex to all other vertices var bellmanFordSp = new BellmanFordShortestPath <T, W>(@operator); var bellFordResult = new Dictionary <T, W>(); foreach (var vertex in workGraph.Vertices) { var result = bellmanFordSp.FindShortestPath(workGraph, randomVetex, vertex.Key); bellFordResult.Add(vertex.Key, result.Length); } //adjust edges so that all edge values are now +ive foreach (var vertex in workGraph.Vertices) { foreach (var edge in vertex.Value.OutEdges.ToList()) { vertex.Value.OutEdges[edge.Key] = @operator.Substract( @operator.Sum(bellFordResult[vertex.Key], edge.Value), bellFordResult[edge.Key.Key]); } } workGraph.RemoveVertex(randomVetex); //now run dijikstra for all pairs of vertices //trace path var dijikstras = new DijikstraShortestPath <T, W>(@operator); var finalResult = new List <AllPairShortestPathResult <T, W> >(); foreach (var vertexA in workGraph.Vertices) { foreach (var vertexB in workGraph.Vertices) { var source = vertexA.Key; var dest = vertexB.Key; var sp = dijikstras.FindShortestPath(workGraph, source, dest); //no path exists if (sp.Length.Equals(@operator.MaxValue)) { continue; } var distance = sp.Length; var path = sp.Path; finalResult.Add(new AllPairShortestPathResult <T, W>(source, dest, distance, path)); } } return(finalResult); }
/// <inheritdoc /> public IEnumerable <IDiGraph <T, TWeight> > GetCyclicalComponents <T, TWeight>(IDiGraph <T, TWeight> graph) where TWeight : IComparable <TWeight> => GetStronglyConnectedComponents(graph).Where(IsCyclicSubGraph);
/// <inheritdoc /> public bool IsAcyclic <T, TWeight>(IDiGraph <T, TWeight> graph) where TWeight : IComparable <TWeight> => !GetCyclicalComponents(graph).Any();
private static bool IsCyclicSubGraph <T, TWeight>(IDiGraph <T, TWeight> graph) where TWeight : IComparable <TWeight> => 1 < graph.Vertices.Count() || graph.Vertices.Count() == 1 && graph.Edges.Any();