public static void MainTest(string[] args) { TextInput input = new TextInput(args[0]); int s = int.Parse(args[1]); EdgeWeightedDigraph G = new EdgeWeightedDigraph(input); // find shortest path from s to each other vertex in DAG AcyclicSP sp = new AcyclicSP(G, s); for (int v = 0; v < G.V; v++) { if (sp.HasPathTo(v)) { Console.Write("{0} to {1} ({2:F2}) ", s, v, sp.DistTo(v)); foreach (DirectedEdge e in sp.PathTo(v)) { Console.Write(e + " "); } Console.WriteLine(); } else { Console.Write("{0} to {1} no path\n", s, v); } } }
public static void MainTest(string[] args) { TextInput input = new TextInput(args[0]); EdgeWeightedDigraph G = new EdgeWeightedDigraph(input); int s = int.Parse(args[1]); // compute shortest paths DijkstraSP sp = new DijkstraSP(G, s); // print shortest path for (int t = 0; t < G.V; t++) { if (sp.HasPathTo(t)) { Console.Write("{0} to {1} ({2:F2}) ", s, t, sp.DistTo(t)); foreach (DirectedEdge e in sp.PathTo(t)) { Console.Write(e + " "); } Console.WriteLine(); } else { Console.Write("{0} to {1} no path\n", s, t); } } }
// relax vertex v and put other endpoints on queue if changed private void relax(EdgeWeightedDigraph G, int v) { foreach (DirectedEdge e in G.Adj(v)) { int 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 } } } }
private IndexMinPQ <double> pq; // priority queue of vertices /// <summary>Computes a shortest-paths tree from the source vertex <c>s</c> to every other /// vertex in the edge-weighted digraph <c>G</c>.</summary> /// <param name="G">the edge-weighted digraph</param> /// <param name="s">the source vertex</param> /// <exception cref="ArgumentException">if an edge weight is negative</exception> /// <exception cref="ArgumentException">unless 0 <= <c>s</c> <=e <c>V</c> - 1</exception> /// public DijkstraSP(EdgeWeightedDigraph G, int s) { foreach (DirectedEdge e in G.Edges()) { if (e.Weight < 0) { throw new ArgumentException("edge " + e + " has negative weight"); } } distTo = new double[G.V]; edgeTo = new DirectedEdge[G.V]; for (int v = 0; v < G.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0.0; // relax vertices in order of distance from s pq = new IndexMinPQ <double>(G.V); pq.Insert(s, distTo[s]); while (!pq.IsEmpty) { int v = pq.DelMin(); foreach (DirectedEdge e in G.Adj(v)) { relax(e); } } // check optimality conditions Debug.Assert(check(G, s)); }
private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on shortest s->v path /// <summary>Computes a shortest paths tree from <c>s</c> to every other vertex in /// the directed acyclic graph <c>G</c>.</summary> /// <param name="G">the acyclic digraph</param> /// <param name="s">the source vertex</param> /// <exception cref="ArgumentException">if the digraph is not acyclic</exception> /// <exception cref="ArgumentException">unless 0 <= <c>s</c> <= <c>V</c> - 1</exception> /// public AcyclicSP(EdgeWeightedDigraph G, int s) { distTo = new double[G.V]; edgeTo = new DirectedEdge[G.V]; for (int v = 0; v < G.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0.0; // visit vertices in toplogical order Topological topological = new Topological(G); if (!topological.HasOrder) { throw new ArgumentException("Digraph is not acyclic."); } foreach (int v in topological.Order()) { foreach (DirectedEdge e in G.Adj(v)) { relax(e); } } }
// find shortest augmenting path and upate private void augment() { // build residual graph EdgeWeightedDigraph G = new EdgeWeightedDigraph(2 * N + 2); int s = 2 * N, t = 2 * N + 1; for (int i = 0; i < N; i++) { if (xy[i] == UNMATCHED) { G.AddEdge(new DirectedEdge(s, i, 0.0)); } } for (int j = 0; j < N; j++) { if (yx[j] == UNMATCHED) { G.AddEdge(new DirectedEdge(N + j, t, py[j])); } } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (xy[i] == j) { G.AddEdge(new DirectedEdge(N + j, i, 0.0)); } else { G.AddEdge(new DirectedEdge(i, N + j, reducedCost(i, j))); } } } // compute shortest path from s to every other vertex DijkstraSP spt = new DijkstraSP(G, s); // augment along alternating path foreach (DirectedEdge e in spt.PathTo(t)) { int i = e.From, j = e.To - N; if (i < N) { xy[i] = j; yx[j] = i; } } // update dual variables for (int i = 0; i < N; i++) { px[i] += spt.DistTo(i); } for (int j = 0; j < N; j++) { py[j] += spt.DistTo(N + j); } }
/// <summary> /// Computes a shortest paths tree from each vertex to to every other vertex in /// the edge-weighted digraph <c>G</c>.</summary> /// <param name="G">the edge-weighted digraph</param> /// <exception cref="ArgumentException">if an edge weight is negative</exception> /// <exception cref="ArgumentException">unless 0 <= <c>s</c> <= <c>V</c> - 1</exception> /// public DijkstraAllPairsSP(EdgeWeightedDigraph G) { all = new DijkstraSP[G.V]; for (int v = 0; v < G.V; v++) { all[v] = new DijkstraSP(G, v); } }
public static void MainTest(string[] args) { // create random DAG with V vertices and E edges; then add F random edges int V = int.Parse(args[0]); int E = int.Parse(args[1]); int F = int.Parse(args[2]); EdgeWeightedDigraph G = new EdgeWeightedDigraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (int i = 0; i < E; i++) { int v, w; do { v = StdRandom.Uniform(V); w = StdRandom.Uniform(V); } while (v >= w); double weight = StdRandom.Uniform(); G.AddEdge(new DirectedEdge(v, w, weight)); } // add F extra edges for (int i = 0; i < F; i++) { int v = StdRandom.Uniform(V); int w = StdRandom.Uniform(V); double weight = StdRandom.Uniform(0.0, 1.0); G.AddEdge(new DirectedEdge(v, w, weight)); } Console.WriteLine(G); // find a directed cycle EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G); if (finder.HasCycle) { Console.Write("Cycle: "); foreach (DirectedEdge e in finder.GetCycle()) { Console.Write(e + " "); } Console.WriteLine(); } // or give topologial sort else { Console.WriteLine("No directed cycle"); } }
/// <summary> /// Determines whether the edge-weighted digraph <c>G</c> has a topological /// order and, if so, finds such an order.</summary> /// <param name="G">the edge-weighted digraph</param> /// public Topological(EdgeWeightedDigraph G) { EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G); if (!finder.HasCycle) { DepthFirstOrder dfs = new DepthFirstOrder(G); order = dfs.ReversePost(); } }
/// <summary> /// Determines whether the edge-weighted digraph <c>G</c> has a /// topological order and, if so, finds such a topological order.</summary> /// <param name="G">the digraph</param> /// public TopologicalX(EdgeWeightedDigraph G) { // indegrees of remaining vertices int[] indegree = new int[G.V]; for (int v = 0; v < G.V; v++) { indegree[v] = G.Indegree(v); } // initialize rank = new int[G.V]; order = new LinkedQueue <int>(); int count = 0; // initialize queue to contain all vertices with indegree = 0 LinkedQueue <int> queue = new LinkedQueue <int>(); for (int v = 0; v < G.V; v++) { if (indegree[v] == 0) { queue.Enqueue(v); } } for (int j = 0; !queue.IsEmpty; j++) { int v = queue.Dequeue(); order.Enqueue(v); rank[v] = count++; foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; indegree[w]--; if (indegree[w] == 0) { queue.Enqueue(w); } } } // there is a directed cycle in subgraph of vertices with indegree >= 1. if (count != G.V) { order = null; } Debug.Assert(check(G)); }
// certify that digraph is acyclic private bool check(EdgeWeightedDigraph G) { // digraph is acyclic if (HasOrder) { // check that ranks are a permutation of 0 to V-1 bool[] found = new bool[G.V]; for (int i = 0; i < G.V; i++) { found[Rank(i)] = true; } for (int i = 0; i < G.V; i++) { if (!found[i]) { Console.Error.WriteLine("No vertex with rank " + i); return(false); } } // check that ranks provide a valid topological order for (int v = 0; v < G.V; v++) { foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; if (Rank(v) > Rank(w)) { Console.Error.WriteLine("{0}-{1}: rank({2}) = {3}, rank({4}) = {5}\n", v, w, v, Rank(v), w, Rank(w)); return(false); } } } // check that order() is consistent with rank() int r = 0; foreach (int v in Order()) { if (Rank(v) != r) { Console.Error.WriteLine("Order() and Rank() inconsistent"); return(false); } r++; } } return(true); }
/// <summary> /// Determines a depth-first order for the edge-weighted digraph <c>G</c>.</summary> /// <param name="G">the edge-weighted digraph</param> /// public DepthFirstOrder(EdgeWeightedDigraph G) { pre = new int[G.V]; post = new int[G.V]; postorder = new LinkedQueue <int>(); preorder = new LinkedQueue <int>(); marked = new bool[G.V]; for (int v = 0; v < G.V; v++) { if (!marked[v]) { dfs(G, v); } } }
// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder private void dfs(EdgeWeightedDigraph G, int v) { marked[v] = true; pre[v] = preCounter++; preorder.Enqueue(v); foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; if (!marked[w]) { dfs(G, w); } } postorder.Enqueue(v); post[v] = postCounter++; }
private LinkedStack <DirectedEdge> cycle; // directed cycle (or null if no such cycle) /// <summary> /// Determines whether the edge-weighted digraph <c>G</c> has a directed cycle and, /// if so, finds such a cycle.</summary> /// <param name="G">the edge-weighted digraph</param> /// public EdgeWeightedDirectedCycle(EdgeWeightedDigraph G) { marked = new bool[G.V]; onStack = new bool[G.V]; edgeTo = new DirectedEdge[G.V]; for (int v = 0; v < G.V; v++) { if (!marked[v]) { dfs(G, v); } } // check that digraph has a cycle Debug.Assert(check(G)); }
// by finding a cycle in predecessor graph private void findNegativeCycle() { int V = edgeTo.Length; EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V); for (int v = 0; v < V; v++) { if (edgeTo[v] != null) { spt.AddEdge(edgeTo[v]); } } EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt); cycle = finder.GetCycle(); }
public static void MainTest(string[] args) { TextInput StdIn = new TextInput(); // number of jobs int N = StdIn.ReadInt(); // source and sink int source = 2 * N; int sink = 2 * N + 1; // build network EdgeWeightedDigraph G = new EdgeWeightedDigraph(2 * N + 2); for (int i = 0; i < N; i++) { double duration = StdIn.ReadDouble(); G.AddEdge(new DirectedEdge(source, i, 0.0)); G.AddEdge(new DirectedEdge(i + N, sink, 0.0)); G.AddEdge(new DirectedEdge(i, i + N, duration)); // precedence constraints int M = StdIn.ReadInt(); for (int j = 0; j < M; j++) { int precedent = StdIn.ReadInt(); G.AddEdge(new DirectedEdge(N + i, precedent, 0.0)); } } // compute longest path AcyclicLP lp = new AcyclicLP(G, source); // print results Console.WriteLine(" job start finish"); Console.WriteLine("--------------------"); for (int i = 0; i < N; i++) { Console.Write("{0,4} {1,7:F1} {2,7:F1}\n", i, lp.DistTo(i), lp.DistTo(i + N)); } Console.Write("Finish time: {0,7:F1}\n", lp.DistTo(sink)); }
/// <summary> /// Initializes a new edge-weighted digraph that is a deep copy of <c>G</c>.</summary> /// <param name="G">the edge-weighted digraph to copy</param> /// public EdgeWeightedDigraph(EdgeWeightedDigraph G) : this(G.V) { numEdges = G.E; for (int v = 0; v < G.V; v++) { indegree[v] = G.Indegree(v); } for (int v = 0; v < G.V; v++) { // reverse so that adjacency list is in same order as original Stack <DirectedEdge> reverse = new Stack <DirectedEdge>(); foreach (DirectedEdge e in G.adj[v]) { reverse.Push(e); } foreach (DirectedEdge e in reverse) { adj[v].Add(e); } } }
public static void MainTest(string[] args) { TextInput StdIn = new TextInput(); // V currencies int V = StdIn.ReadInt(); string[] name = new string[V]; // create complete network EdgeWeightedDigraph G = new EdgeWeightedDigraph(V); for (int v = 0; v < V; v++) { name[v] = StdIn.ReadString(); for (int w = 0; w < V; w++) { double rate = StdIn.ReadDouble(); DirectedEdge e = new DirectedEdge(v, w, -Math.Log(rate)); G.AddEdge(e); } } // find negative cycle BellmanFordSP spt = new BellmanFordSP(G, 0); if (spt.HasNegativeCycle) { double stake = 1000.0; foreach (DirectedEdge e in spt.GetNegativeCycle()) { Console.Write("{0,10:F5} {1} ", stake, name[e.From]); stake *= Math.Exp(-e.Weight); Console.Write("= {0,10:F5} {1}\n", stake, name[e.To]); } } else { Console.WriteLine("No arbitrage opportunity"); } }
// check optimality conditions private bool check(EdgeWeightedDigraph G, int s) { // no negative cycle if (!HasNegativeCycle) { for (int v = 0; v < G.V; v++) { foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; for (int i = 0; i < G.V; i++) { if (distTo[i, w] > distTo[i, v] + e.Weight) { Console.Error.WriteLine("edge " + e + " is eligible"); return(false); } } } } } return(true); }
/// <summary> /// Returns a negative cycle, or <c>null</c> if there is no such cycle.</summary> /// <returns>a negative cycle as an iterable of edges, /// or <c>null</c> if there is no such cycle</returns> /// public IEnumerable <DirectedEdge> NegativeCycle() { for (int v = 0; v < distTo.Length; v++) { // negative cycle in v's predecessor graph if (distTo[v, v] < 0.0) { int V = edgeTo.Length; EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V); for (int w = 0; w < V; w++) { if (edgeTo[v, w] != null) { spt.AddEdge(edgeTo[v, w]); } } EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt); Debug.Assert(finder.HasCycle); return(finder.GetCycle()); } } return(null); }
public static void MainTest(string[] args) { EdgeWeightedDigraph G = new EdgeWeightedDigraph(new TextInput(args[0])); int s = int.Parse(args[1]); AcyclicLP lp = new AcyclicLP(G, s); for (int v = 0; v < G.V; v++) { if (lp.HasPathTo(v)) { Console.Write("{0} to {1} ({2:F2}) ", s, v, lp.DistTo(v)); foreach (DirectedEdge e in lp.PathTo(v)) { Console.Write(e + " "); } Console.WriteLine(); } else { Console.Write("{0} to {0} no path\n", s, v); } } }
// check that algorithm computes either the topological order or finds a directed cycle private void dfs(EdgeWeightedDigraph G, int v) { onStack[v] = true; marked[v] = true; foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; // short circuit if directed cycle found if (cycle != null) { return; } else if (!marked[w]) { //found new vertex, so recur edgeTo[w] = e; dfs(G, w); } else if (onStack[w]) { // trace back directed cycle cycle = new LinkedStack <DirectedEdge>(); DirectedEdge eTemp = e; while (eTemp.From != w) { cycle.Push(eTemp); eTemp = edgeTo[eTemp.From]; } cycle.Push(eTemp); return; } } onStack[v] = false; }
public static void MainTest(string[] args) { TextInput input = new TextInput(args[0]); EdgeWeightedDigraph G = new EdgeWeightedDigraph(input); int s = int.Parse(args[1]); BellmanFordSP sp = new BellmanFordSP(G, s); // print negative cycle if (sp.HasNegativeCycle) { foreach (DirectedEdge e in sp.GetNegativeCycle()) { Console.WriteLine(e); } } else // print shortest paths { for (int v = 0; v < G.V; v++) { if (sp.HasPathTo(v)) { Console.Write("{0} to {1} ({2:F2}) ", s, v, sp.DistTo(v)); foreach (DirectedEdge e in sp.PathTo(v)) { Console.Write(e + " "); } Console.WriteLine(); } else { Console.Write("{0} to {1}: no path\n", s, v); } } } }
private IEnumerable <DirectedEdge> cycle; // negative cycle (or null if no such cycle) /// <summary>Computes a shortest paths tree from <c>s</c> to every other vertex in /// the edge-weighted digraph <c>G</c>.</summary> /// <param name="G">the acyclic digraph</param> /// <param name="s">the source vertex</param> /// <exception cref="ArgumentException">unless 0 <= <c>s</c> <= <c>V</c> - 1</exception> /// public BellmanFordSP(EdgeWeightedDigraph G, int s) { distTo = new double[G.V]; edgeTo = new DirectedEdge[G.V]; onQueue = new bool[G.V]; for (int v = 0; v < G.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0.0; // Bellman-Ford algorithm queue = new LinkedQueue <int>(); queue.Enqueue(s); onQueue[s] = true; while (!queue.IsEmpty && !HasNegativeCycle) { int v = queue.Dequeue(); onQueue[v] = false; relax(G, v); } Debug.Assert(check(G, s)); }
// check optimality conditions: // (i) for all edges e: distTo[e.To] <= distTo[e.From] + e.Weight // (ii) for all edge e on the SPT: distTo[e.To] == distTo[e.From] + e.Weight private bool check(EdgeWeightedDigraph G, int s) { // check that edge weights are nonnegative foreach (DirectedEdge e in G.Edges()) { if (e.Weight < 0) { Console.Error.WriteLine("negative edge weight detected"); return(false); } } // check that distTo[v] and edgeTo[v] are consistent if (distTo[s] != 0.0 || edgeTo[s] != null) { Console.Error.WriteLine("distTo[s] and edgeTo[s] inconsistent"); return(false); } for (int v = 0; v < G.V; v++) { if (v == s) { continue; } if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity) { Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent"); return(false); } } // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() for (int v = 0; v < G.V; v++) { foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; if (distTo[v] + e.Weight < distTo[w]) { Console.Error.WriteLine("edge " + e + " not relaxed"); return(false); } } } // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight() for (int w = 0; w < G.V; w++) { if (edgeTo[w] == null) { continue; } DirectedEdge e = edgeTo[w]; int v = e.From; if (w != e.To) { return(false); } if (distTo[v] + e.Weight != distTo[w]) { Console.Error.WriteLine("edge " + e + " on shortest path not tight"); return(false); } } return(true); }
// check optimality conditions: either // (i) there exists a negative cycle reacheable from s // or // (ii) for all edges e = v->w: distTo[w] <= distTo[v] + e.Weight // (ii') for all edges e = v->w on the SPT: distTo[w] == distTo[v] + e.Weight private bool check(EdgeWeightedDigraph G, int s) { // has a negative cycle if (HasNegativeCycle) { double weight = 0.0; foreach (DirectedEdge e in GetNegativeCycle()) { weight += e.Weight; } if (weight >= 0.0) { Console.Error.WriteLine("error: weight of negative cycle = " + weight); return(false); } } // no negative cycle reachable from source else { // check that distTo[v] and edgeTo[v] are consistent if (distTo[s] != 0.0 || edgeTo[s] != null) { Console.Error.WriteLine("distanceTo[s] and edgeTo[s] inconsistent"); return(false); } for (int v = 0; v < G.V; v++) { if (v == s) { continue; } if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity) { Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent"); return(false); } } // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.Weight for (int v = 0; v < G.V; v++) { foreach (DirectedEdge e in G.Adj(v)) { int w = e.To; if (distTo[v] + e.Weight < distTo[w]) { Console.Error.WriteLine("edge " + e + " not relaxed"); return(false); } } } // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.Weight for (int w = 0; w < G.V; w++) { if (edgeTo[w] == null) { continue; } DirectedEdge e = edgeTo[w]; int v = e.From; if (w != e.To) { return(false); } if (distTo[v] + e.Weight != distTo[w]) { Console.Error.WriteLine("edge " + e + " on shortest path not tight"); return(false); } } } //Console.WriteLine("Satisfies optimality conditions"); return(true); }
public static void MainTest(string[] args) { EdgeWeightedDigraph G = new EdgeWeightedDigraph(new TextInput(args[0])); Console.WriteLine(G); }