private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on longest s->v path /// <summary> /// Computes a longest 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 AcyclicLP(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.NegativeInfinity; } distTo[s] = 0.0; // relax 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); } } }
// 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)); }
// 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 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)); }
// 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++; }
// 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); }
// 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; }
// 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); }
// 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); }