public EdgeWeightedDirectedCycle(WeightedDiGraph <T> G) { var vertexes = new List <T>(G.Vertexes()); foreach (var v in vertexes) { marked.Add(v, false); } foreach (var v in vertexes) { edgeTo.Add(v, null); } foreach (var v in vertexes) { onStack.Add(v, false); } foreach (var v in vertexes) { if (!marked[v]) { Dfs(G, v); } } }
public TopologicalSortShortestPath(WeightedDiGraph G, int s) { this.s = s; int V = G.V(); marked = new bool[V]; edgeTo = new Edge[V]; cost = new double[V]; for (var i = 0; i < V; ++i) { cost[i] = Double.MaxValue; } cost[s] = 0; DepthFirstPostOrder dfo = new DepthFirstPostOrder(G.ToDiGraph()); foreach (var v in dfo.PostOrder()) { foreach (var e in G.adj(v)) { Relax(G, e); } } }
/// <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.AddOrUpdateEdge(vertex.Key, edge.TargetVertex.Key, edge.Weight <W>(), @operator); //add a backward edge for residual graph with edge value as default(W) newGraph.AddOrUpdateEdge(edge.TargetVertex.Key, vertex.Key, @operator.defaultWeight, @operator); } } return(newGraph); }
public void GetEdge() { WeightedDiGraph <int> directedGraph = GetTestGraph(); Assert.AreEqual(new WeightedEdge <int>(1, 2, 7), directedGraph.GetEdge(1, 2)); Assert.AreEqual(WeightedEdge <int> .None, directedGraph.GetEdge(3, 0)); }
public void TravellingSalesman_Smoke_Test() { var graph = new WeightedDiGraph <int, int>(); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); graph.AddVertex(3); graph.AddEdge(0, 1, 1); graph.AddEdge(0, 2, 15); graph.AddEdge(0, 3, 6); graph.AddEdge(1, 0, 2); graph.AddEdge(1, 2, 7); graph.AddEdge(1, 3, 3); graph.AddEdge(2, 0, 9); graph.AddEdge(2, 1, 6); graph.AddEdge(2, 3, 12); graph.AddEdge(3, 0, 10); graph.AddEdge(3, 1, 4); graph.AddEdge(3, 2, 8); Assert.AreEqual(21, TravellingSalesman.GetMinWeight(graph)); }
/// <summary> /// Trace back path from destination to source using parent map. /// </summary> private ShortestPathResult <T, W> tracePath(WeightedDiGraph <T, W> 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 = operators.DefaultValue; while (pathStack.Count > 0) { resultPath.Add(pathStack.Pop()); } for (int i = 0; i < resultPath.Count - 1; i++) { resultLength = operators.Sum(resultLength, graph.Vertices[resultPath[i]].OutEdges[graph.Vertices[resultPath[i + 1]]]); } return(new ShortestPathResult <T, W>(resultPath, resultLength)); }
/// <summary> /// Augment current Path to residual Graph /// </summary> /// <param name="graph"></param> /// <param name="residualGraph"></param> /// <param name="path"></param> /// <returns></returns> private W AugmentResidualGraph(WeightedDiGraph <T, W> graph, WeightedDiGraph <T, W> residualGraph, List <T> path) { var min = operators.MaxWeight; for (int i = 0; i < path.Count - 1; i++) { var vertex_1 = residualGraph.FindVertex(path[i]); var vertex_2 = residualGraph.FindVertex(path[i + 1]); var edgeValue = vertex_1.OutEdges[vertex_2]; if (min.CompareTo(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] = operators.SubstractWeights(vertex_1.OutEdges[vertex_2], min); //add for backward paths vertex_2.OutEdges[vertex_1] = operators.AddWeights(vertex_2.OutEdges[vertex_1], min); } return(min); }
/// <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)); }
public BellmanFord(WeightedDiGraph <T> G, T s) { this.s = s; vertexes = new List <T>(G.Vertexes()); foreach (var v in vertexes) { distTo.Add(v, double.MaxValue); } foreach (var v in vertexes) { edgeTo.Add(v, null); } foreach (var v in vertexes) { onQueue.Add(v, false); } distTo[s] = 0.0; queue.Enqueue(s); onQueue[s] = true; while (!queue.IsEmpty && !HasNegativeCycle()) { T v = queue.Dequeue(); onQueue[v] = false; Relax(G, v); } }
/// <summary> /// clones this graph and creates a residual graph /// </summary> /// <param name="graph"></param> /// <returns></returns> private WeightedDiGraph <T, W> createResidualGraph(WeightedDiGraph <T, W> graph) { var newGraph = new WeightedDiGraph <T, W>(); //clone graph vertices foreach (var vertex in graph.Vertices) { newGraph.AddVertex(vertex.Key); } //clone edges foreach (var vertex in graph.Vertices) { //Use either OutEdges or InEdges for cloning //here we use OutEdges foreach (var edge in vertex.Value.OutEdges) { //original edge newGraph.AddEdge(vertex.Key, edge.Key.Value, edge.Value); //add a backward edge for residual graph with edge value as default(W) newGraph.AddEdge(edge.Key.Value, vertex.Key, default(W)); } } return(newGraph); }
public void MinCut_Smoke_Test_1() { var graph = new WeightedDiGraph <char, int>(); graph.AddVertex('S'); graph.AddVertex('A'); graph.AddVertex('B'); graph.AddVertex('C'); graph.AddVertex('D'); graph.AddVertex('T'); graph.AddEdge('S', 'A', 10); graph.AddEdge('S', 'C', 10); graph.AddEdge('A', 'B', 4); graph.AddEdge('A', 'C', 2); graph.AddEdge('A', 'D', 8); graph.AddEdge('B', 'T', 10); graph.AddEdge('C', 'D', 9); graph.AddEdge('D', 'B', 6); graph.AddEdge('D', 'T', 10); var algorithm = new MinCut <char, int>(new EdmondKarpOperators()); var result = algorithm.ComputeMinCut(graph, 'S', 'T'); Assert.AreEqual(result.Count, 2); }
public void EdmondKarp_Smoke_Test() { var graph = new WeightedDiGraph <char, int>(); graph.AddVertex('S'); graph.AddVertex('A'); graph.AddVertex('B'); graph.AddVertex('C'); graph.AddVertex('D'); graph.AddVertex('T'); graph.AddEdge('S', 'A', 10); graph.AddEdge('S', 'C', 10); graph.AddEdge('A', 'B', 4); graph.AddEdge('A', 'C', 2); graph.AddEdge('A', 'D', 8); graph.AddEdge('B', 'T', 10); graph.AddEdge('C', 'D', 9); graph.AddEdge('D', 'B', 6); graph.AddEdge('D', 'T', 10); var algo = new EdmondKarpMaxFlow <char, int>(new EdmondKarpOperators()); var result = algo.ComputeMaxFlow(graph, 'S', 'T'); Assert.AreEqual(result, 19); }
public void ShortestPathsWithOneEdgeLength() { WeightedDiGraph <int> directedGraph = new WeightedDiGraph <int> { new WeightedEdge <int>(0, 1, 10), new WeightedEdge <int>(0, 2, 5), new WeightedEdge <int>(0, 3, 7) }; GraphShortestPaths <int> shortestPaths = new GraphShortestPaths <int>(0, directedGraph); IList <WeightedEdge <int> > shortestPath = shortestPaths.GetShortestPath(1).ToList(); Assert.AreEqual(1, shortestPath.Count, "Shortest path count"); Assert.AreEqual(new WeightedEdge <int>(0, 1, 10), shortestPath[0]); shortestPath = shortestPaths.GetShortestPath(2).ToList(); Assert.AreEqual(1, shortestPath.Count, "Shortest path count"); Assert.AreEqual(new WeightedEdge <int>(0, 2, 5), shortestPath[0]); shortestPath = shortestPaths.GetShortestPath(3).ToList(); Assert.AreEqual(1, shortestPath.Count, "Shortest path count"); Assert.AreEqual(new WeightedEdge <int>(0, 3, 7), shortestPath[0]); }
public List <MinCutEdge <T> > ComputeMinCut(WeightedDiGraph <T, W> graph, T source, T sink) { var edmondsKarpMaxFlow = new EdmondKarpMaxFlow <T, W>(operators); 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(graph, maxFlowResidualGraph, source); var result = new List <MinCutEdge <T> >(); foreach (var vertex in reachableVertices) { foreach (var edge in graph.Vertices[vertex].OutEdges) { //if unreachable if (!reachableVertices.Contains(edge.Key.Value)) { result.Add(new MinCutEdge <T>(vertex, edge.Key.Value)); } } } return(result); }
public static int GetMinWeight(WeightedDiGraph <int, int> graph) { return(getMinWeight(graph.ReferenceVertex, graph.ReferenceVertex, graph.VerticesCount, new HashSet <WeightedDiGraphVertex <int, int> >(), new Dictionary <string, int>())); }
public void FordFulkerson_Smoke_Test() { var graph = new WeightedDiGraph <char, int>(); graph.AddVertex('S'); graph.AddVertex('A'); graph.AddVertex('B'); graph.AddVertex('C'); graph.AddVertex('D'); graph.AddVertex('T'); graph.AddEdge('S', 'A', 10); graph.AddEdge('S', 'C', 10); graph.AddEdge('A', 'B', 4); graph.AddEdge('A', 'C', 2); graph.AddEdge('A', 'D', 8); graph.AddEdge('B', 'T', 10); graph.AddEdge('C', 'D', 9); graph.AddEdge('D', 'B', 6); graph.AddEdge('D', 'T', 10); var algorithm = new FordFulkersonMaxFlow <char, int>(new FordFulkersonOperators()); var result = algorithm.ComputeMaxFlow(graph, 'S', 'T'); Assert.AreEqual(result, 19); }
public Dijkstra(WeightedDiGraph G, int s) { this.s = s; int V = G.V(); marked = new bool[V]; edgeTo = new Edge[V]; cost = new double[V]; for (var i = 0; i < V; ++i) { cost[i] = Double.MaxValue; } cost[s] = 0; pq = new IndexMinPQ <Double>(V); pq.Insert(s, 0); while (!pq.IsEmpty) { var v = pq.DelMin(); marked[v] = true; foreach (var e in G.adj(v)) { Relax(G, e); } } }
public void ShortedPathsWithSeveralEdges(int vertexTo, double expectedWeight) { WeightedDiGraph <int> directedGraph = new WeightedDiGraph <int> { new WeightedEdge <int>(0, 2, 0.26), new WeightedEdge <int>(0, 4, 0.38), new WeightedEdge <int>(2, 7, 0.34), new WeightedEdge <int>(4, 5, 0.35), new WeightedEdge <int>(5, 4, 0.35), new WeightedEdge <int>(4, 7, 0.37), new WeightedEdge <int>(5, 7, 0.28), new WeightedEdge <int>(7, 5, 0.28), new WeightedEdge <int>(7, 3, 0.39), new WeightedEdge <int>(1, 3, 0.29), new WeightedEdge <int>(6, 2, 0.40), new WeightedEdge <int>(6, 0, 0.58), new WeightedEdge <int>(6, 4, 0.93), new WeightedEdge <int>(5, 1, 0.32), new WeightedEdge <int>(3, 6, 0.52) }; GraphShortestPaths <int> shortestPaths = new GraphShortestPaths <int>(0, directedGraph); IList <WeightedEdge <int> > shortestPath = shortestPaths.GetShortestPath(vertexTo).ToList(); Assert.AreEqual(expectedWeight, Math.Round(shortestPath.Sum(x => x.Weight), 2)); }
private void Relax(WeightedDiGraph <T> G, T v) { foreach (var e in G.Adj(v)) { T w = e.To(); if (distTo[w] > distTo[v] + e.Weight) { distTo[w] = distTo[v] + e.Weight; edgeTo[w] = e; if (!onQueue[w]) { queue.Enqueue(w); onQueue[w] = true; } } if (cost++ % G.V() == 0) { FindNegativeCycle(); if (HasNegativeCycle()) { return; // found a negative cycle } } } }
/// <summary> /// create a directed unit weighted graph with given dummySource to Patition 1 and Patition 2 to dummy sink. /// </summary> private static WeightedDiGraph <T, int> createFlowGraph(IGraph <T> graph, T dummySource, T dummySink, Dictionary <int, List <T> > partitions) { var workGraph = new WeightedDiGraph <T, int>(); workGraph.AddVertex(dummySource); foreach (var group1Vertex in partitions[1]) { workGraph.AddVertex(group1Vertex); workGraph.AddEdge(dummySource, group1Vertex, 1); } workGraph.AddVertex(dummySink); foreach (var group2Vertex in partitions[2]) { workGraph.AddVertex(group2Vertex); workGraph.AddEdge(group2Vertex, dummySink, 1); } //now add directed edges from group 1 vertices to group 2 vertices foreach (var group1Vertex in partitions[1]) { foreach (var edge in graph.GetVertex(group1Vertex).Edges) { workGraph.AddEdge(group1Vertex, edge.TargetVertexKey, 1); } } return(workGraph); }
/// <summary> /// Computes Max Flow using Push-Relabel algorithm /// </summary> /// <param name="graph"></param> /// <param name="source"></param> /// <param name="sink"></param> /// <returns></returns> public W ComputeMaxFlow(WeightedDiGraph <T, W> graph, T source, T sink) { //clone to create a residual graph var residualGraph = createResidualGraph(graph); //init vertex Height & Overflow object (ResidualGraphVertexStatus) var vertexStatusMap = new Dictionary <T, ResidualGraphVertexStatus>(); foreach (var vertex in residualGraph.Vertices) { if (vertex.Value.Value.Equals(source)) { //for source vertex //init source height to Maximum (equal to total vertex count) vertexStatusMap.Add(vertex.Value.Value, new ResidualGraphVertexStatus(residualGraph.Vertices.Count, operators.defaultWeight)); } else { vertexStatusMap.Add(vertex.Value.Value, new ResidualGraphVertexStatus(0, operators.defaultWeight)); } } //init source neighbour overflow to capacity of source-neighbour edges foreach (var edge in residualGraph.Vertices[source].OutEdges.ToList()) { //update edge vertex overflow vertexStatusMap[edge.Key.Value].Overflow = edge.Value; //increment reverse edge residualGraph.Vertices[edge.Key.Value] .OutEdges[residualGraph.Vertices[source]] = edge.Value; //set to minimum residualGraph.Vertices[source].OutEdges[edge.Key] = operators.defaultWeight; } var overflowVertex = findOverflowVertex(vertexStatusMap, source, sink); //until there is not more overflow vertices while (!overflowVertex.Equals(default(T))) { //if we can't push this vertex if (!push(residualGraph.Vertices[overflowVertex], vertexStatusMap)) { //increase its height and try again relabel(residualGraph.Vertices[overflowVertex], vertexStatusMap); } overflowVertex = findOverflowVertex(vertexStatusMap, source, sink); } //overflow of sink will be the net flow return(vertexStatusMap[sink].Overflow); }
/// <summary> /// Gets a list of reachable vertices in residual graph from source. /// </summary> private HashSet <T> getReachable(WeightedDiGraph <T, W> residualGraph, T source) { var visited = new HashSet <T>(); dfs(residualGraph.Vertices[source], visited); return(visited); }
public GraphShortestPaths(T from, WeightedDiGraph <T> directedGraph) { From = from; DirectedGraph = directedGraph; _parents = new HashDictionary <T, WeightedEdge <T> >(); _calcWeights = new HashDictionary <T, double>(); _priorityQueue = new PriorityQueue <T>(); InitQueue(); BuildShortestPaths(); }
/// <summary> /// Gets a list of reachable vertices in residual graph from source /// </summary> /// <param name="residualGraph"></param> /// <param name="source"></param> /// <returns></returns> public HashSet <T> GetReachable(WeightedDiGraph <T, W> graph, WeightedDiGraph <T, W> residualGraph, T source) { var visited = new HashSet <T>(); DFS(graph, residualGraph.Vertices[source], visited); return(visited); }
private void SolveButton_Click(object sender, EventArgs e) { List <Arrow> cp; var thread = new Thread ( () => { if (!loaded) { List <Arrow> arrows = new List <Arrow>(); for (int i = 1; i <= vertices; i++) { for (int j = 1; j <= vertices; j++) { double weight = Convert.ToDouble(Controls.Find(i + "," + j, true)[0].Text); if (weight >= 0) { arrows.Add(new Arrow(i, j, weight)); } } } G = new WeightedDiGraph(arrows); } cp = CPM.GetCriticalPath(G); solutionBox.Text += "Solution #" + solutionNumber + ":\nCritical path: " + cp[0].GetBegin(); double summWeight = 0; foreach (Arrow a in cp) { summWeight += a.GetWeight(); solutionBox.Text += ", " + a.GetEnd(); } solutionBox.Text += ";\nSumm weight = " + summWeight + ".\n\n"; solutionNumber++; } ); thread.Start(); thread.Join(); /* * string args = vertices.ToString(); * * for (int i = 1; i <= vertices; i++) * for (int j = 1; j <= vertices; j++) * args += " " + Controls.Find(i + "," + j, true)[0].Text; * solutionBox.Text += "Solution #" + solutionNumber + ExecutableSolve(args); * solutionNumber++; */ }
public void WeightedGraphToString() { WeightedGraph <int> graph = new WeightedDiGraph <int> { new WeightedEdge <int>(1, 2, 1), new WeightedEdge <int>(2, 3, 2), new WeightedEdge <int>(3, 1, 3) }; Assert.IsNotNull(graph.ToString()); }
public void GetAdjacencyListTest() { WeightedDiGraph <int> directedGraph = GetTestGraph(); ICollection <WeightedEdge <int> > adjacencyList = directedGraph.GetAdjacencyList(0); Assert.AreEqual(3, adjacencyList.Count, "Adjacency list count"); Assert.IsTrue(adjacencyList.Contains(new WeightedEdge <int>(0, 1, 10))); Assert.IsTrue(adjacencyList.Contains(new WeightedEdge <int>(0, 2, 5))); Assert.IsTrue(adjacencyList.Contains(new WeightedEdge <int>(0, 3, 3))); }
private WeightedDiGraph <int> GetTestGraph() { WeightedDiGraph <int> directedGraph = new WeightedDiGraph <int> { new WeightedEdge <int>(0, 1, 10), new WeightedEdge <int>(0, 2, 5), new WeightedEdge <int>(0, 3, 3), new WeightedEdge <int>(1, 2, 7) }; return(directedGraph); }
private void Relax(WeightedDiGraph G, Edge e) { int v = e.from(); int w = e.to(); if (cost[w] > cost[v] + e.Weight) { cost[w] = cost[v] + e.Weight; edgeTo[w] = e; marked[w] = true; } }
private bool Relax(WeightedDiGraph G, Edge e) { var v = e.from(); var w = e.to(); if (cost[w] > cost[v] + e.Weight) { cost[w] = cost[v] + e.Weight; edgeTo[w] = e; return(true); } return(false); }