// relax vertex v and put other endpoints on queue if changed private void Relax(EdgeWeightedDigraph g, int v) { foreach (var e in g.Adj(v)) { var 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> /// check that algorithm computes either the topological order or finds a directed cycle /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Dfs(EdgeWeightedDigraph g, int v) { _onStack[v] = true; _marked[v] = true; foreach (var e in g.Adj(v)) { var w = e.To(); // short circuit if directed cycle found if (_cycle != null) { return; } //found new vertex, so recur if (!_marked[w]) { _edgeTo[w] = e; Dfs(g, w); } // trace back directed cycle else if (_onStack[w]) { TraceBackDirectedCycle(e, w); return; } } _onStack[v] = false; }
private readonly IndexMinPQ <Double> _pq; // priority queue of vertices /// <summary> /// Computes a shortest-paths tree from the source vertex <tt>s</tt> to every other /// vertex in the edge-weighted digraph <tt>G</tt>. /// </summary> /// <param name="g">g the edge-weighted digraph</param> /// <param name="s">s the source vertex</param> /// <exception cref="ArgumentException">if an edge weight is negative</exception> /// <exception cref="ArgumentException">unless 0 <= <tt>s</tt> <= <tt>V</tt> - 1</exception> public DijkstraSP(EdgeWeightedDigraph g, int s) { foreach (var 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 (var 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()) { var v = _pq.DelMin(); foreach (var e in g.Adj(v)) { Relax(e); } } // check optimality conditions //assert check(G, s); }
private readonly IndexMinPQ<Double> _pq; // priority queue of vertices #endregion Fields #region Constructors /// <summary> /// Computes a shortest-paths tree from the source vertex <tt>s</tt> to every other /// vertex in the edge-weighted digraph <tt>G</tt>. /// </summary> /// <param name="g">g the edge-weighted digraph</param> /// <param name="s">s the source vertex</param> /// <exception cref="ArgumentException">if an edge weight is negative</exception> /// <exception cref="ArgumentException">unless 0 <= <tt>s</tt> <= <tt>V</tt> - 1</exception> public DijkstraSP(EdgeWeightedDigraph g, int s) { foreach (var 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 (var 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()) { var v = _pq.DelMin(); foreach (var e in g.Adj(v)) Relax(e); } // check optimality conditions //assert check(G, s); }
private readonly DirectedEdge[] _edgeTo; // edgeTo[v] = last edge on shortest s->v path /// <summary> /// Computes a shortest paths tree from <tt>s</tt> to every other vertex in /// the directed acyclic graph <tt>G</tt>. /// </summary> /// <param name="g">g the acyclic digraph</param> /// <param name="s">s the source vertex</param> /// <exception cref="ArgumentException">if the digraph is not acyclic</exception> /// <exception cref="ArgumentException">unless 0 <= <tt>s</tt> <= <tt>V</tt> - 1</exception> public AcyclicSP(EdgeWeightedDigraph g, int s) { _distTo = new double[g.V]; _edgeTo = new DirectedEdge[g.V]; for (var v = 0; v < g.V; v++) { _distTo[v] = double.PositiveInfinity; } _distTo[s] = 0.0; // visit vertices in toplogical order var topological = new Topological(g); if (!topological.HasOrder()) { throw new ArgumentException("Digraph is not acyclic."); } foreach (int v in topological.Order()) { foreach (var e in g.Adj(v)) { Relax(e); } } }
/// <summary> /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Dfs(EdgeWeightedDigraph g, int v) { _marked[v] = true; _pre[v] = _preCounter++; _preorder.Enqueue(v); foreach (var e in g.Adj(v)) { var w = e.To(); if (!_marked[w]) { Dfs(g, w); } } _postorder.Enqueue(v); _post[v] = _postCounter++; }
private readonly DirectedEdge[] _edgeTo; // edgeTo[v] = last edge on longest s->v path #endregion Fields #region Constructors /// <summary> /// Computes a longest paths tree from <tt>s</tt> to every other vertex in /// the directed acyclic graph <tt>G</tt>. /// </summary> /// <param name="g">g the acyclic digraph</param> /// <param name="s">s the source vertex</param> /// <exception cref="ArgumentException">if the digraph is not acyclic</exception> /// <exception cref="ArgumentException">unless 0 <= <tt>s</tt> <= <tt>V</tt> - 1</exception> public AcyclicLP(EdgeWeightedDigraph g, int s) { _distTo = new double[g.V]; _edgeTo = new DirectedEdge[g.V]; for (var v = 0; v < g.V; v++) _distTo[v] = double.NegativeInfinity; _distTo[s] = 0.0; // relax vertices in toplogical order var topological = new Topological(g); if (!topological.HasOrder()) throw new ArgumentException("Digraph is not acyclic."); foreach (int v in topological.Order()) { foreach (var e in g.Adj(v)) Relax(e); } }
// check optimality conditions private bool Check(EdgeWeightedDigraph g, int s) { // no negative cycle if (!HasNegativeCycle) { for (var v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { var w = e.To(); for (var i = 0; i < g.V; i++) { if (_distTo[i][w] > _distTo[i][v] + e.Weight) { Console.WriteLine($"edge {e} is eligible"); return(false); } } } } } return(true); }
/// <summary> /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Dfs(EdgeWeightedDigraph g, int v) { _marked[v] = true; _pre[v] = _preCounter++; _preorder.Enqueue(v); foreach (var e in g.Adj(v)) { var w = e.To(); if (!_marked[w]) { Dfs(g, w); } } _postorder.Enqueue(v); _post[v] = _postCounter++; }
/// <summary> /// 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() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedDigraph g, int s) { // check that edge weights are nonnegative if (g.Edges().Any(e => e.Weight < 0)) { Console.Error.WriteLine("negative edge weight detected"); return(false); } // check that distTo[v] and edgeTo[v] are consistent if (Math.Abs(_distTo[s]) > 1E12 || _edgeTo[s] != null) { Console.Error.WriteLine("distTo[s] and edgeTo[s] inconsistent"); return(false); } for (var v = 0; v < g.V; v++) { if (v == s) { continue; } if (_edgeTo[v] == null && !double.IsPositiveInfinity(_distTo[v])) { Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent"); return(false); } } // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() for (var v = 0; v < g.V; v++) { foreach (var 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 (var w = 0; w < g.V; w++) { if (_edgeTo[w] == null) { continue; } var e = _edgeTo[w]; var v = e.From(); if (w != e.To()) { return(false); } if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) > 1E12) { 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()) { var weight = NegativeCycle().Sum(e => e.Weight); if (weight >= 0.0) { Console.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 (Math.Abs(_distTo[s]) > 0.0001 || _edgeTo[s] != null) { Console.WriteLine("distanceTo[s] and edgeTo[s] inconsistent"); return(false); } for (var v = 0; v < g.V; v++) { if (v == s) { continue; } if (_edgeTo[v] != null || double.IsPositiveInfinity(_distTo[v])) { continue; } Console.WriteLine("distTo[] and edgeTo[] inconsistent"); return(false); } // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() for (var v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { var w = e.To(); if (!(_distTo[v] + e.Weight < _distTo[w])) { continue; } Console.WriteLine($"edge {e} not relaxed"); return(false); } } // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight() for (var w = 0; w < g.V; w++) { if (_edgeTo[w] == null) { continue; } var e = _edgeTo[w]; var v = e.From(); if (w != e.To()) { return(false); } if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) < 0.0001) { continue; } Console.WriteLine($"edge {e} on shortest path not tight"); return(false); } } Console.WriteLine("Satisfies optimality conditions"); Console.WriteLine(); return(true); }
/// <summary> /// check that algorithm computes either the topological order or finds a directed cycle /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Dfs(EdgeWeightedDigraph g, int v) { _onStack[v] = true; _marked[v] = true; foreach (var e in g.Adj(v)) { var w = e.To(); // short circuit if directed cycle found if (_cycle != null) return; //found new vertex, so recur if (!_marked[w]) { _edgeTo[w] = e; Dfs(g, w); } // trace back directed cycle else if (_onStack[w]) { TraceBackDirectedCycle(e, w); return; } } _onStack[v] = false; }
/// <summary> /// 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() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedDigraph g, int s) { // check that edge weights are nonnegative if (g.Edges().Any(e => e.Weight < 0)) { Console.Error.WriteLine("negative edge weight detected"); return false; } // check that distTo[v] and edgeTo[v] are consistent if (Math.Abs(_distTo[s]) > 1E12 || _edgeTo[s] != null) { Console.Error.WriteLine("distTo[s] and edgeTo[s] inconsistent"); return false; } for (var v = 0; v < g.V; v++) { if (v == s) continue; if (_edgeTo[v] == null && !double.IsPositiveInfinity(_distTo[v])) { Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent"); return false; } } // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() for (var v = 0; v < g.V; v++) { foreach (var 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 (var w = 0; w < g.V; w++) { if (_edgeTo[w] == null) continue; var e = _edgeTo[w]; var v = e.From(); if (w != e.To()) return false; if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) > 1E12) { Console.Error.WriteLine($"edge {e} on shortest path not tight"); return false; } } return true; }
// check optimality conditions private bool Check(EdgeWeightedDigraph g, int s) { // no negative cycle if (!HasNegativeCycle) { for (var v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { var w = e.To(); for (var i = 0; i < g.V; i++) { if (_distTo[i][w] > _distTo[i][v] + e.Weight) { Console.WriteLine($"edge {e} is eligible"); return false; } } } } } return true; }
// relax vertex v and put other endpoints on queue if changed private void Relax(EdgeWeightedDigraph g, int v) { foreach (var e in g.Adj(v)) { var 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 } } }
// 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()) { var weight = NegativeCycle().Sum(e => e.Weight); if (weight >= 0.0) { Console.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 (Math.Abs(_distTo[s]) > 0.0001 || _edgeTo[s] != null) { Console.WriteLine("distanceTo[s] and edgeTo[s] inconsistent"); return false; } for (var v = 0; v < g.V; v++) { if (v == s) continue; if (_edgeTo[v] != null || double.IsPositiveInfinity(_distTo[v])) continue; Console.WriteLine("distTo[] and edgeTo[] inconsistent"); return false; } // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight() for (var v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { var w = e.To(); if (!(_distTo[v] + e.Weight < _distTo[w])) continue; Console.WriteLine($"edge {e} not relaxed"); return false; } } // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight() for (var w = 0; w < g.V; w++) { if (_edgeTo[w] == null) continue; var e = _edgeTo[w]; var v = e.From(); if (w != e.To()) return false; if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) < 0.0001) continue; Console.WriteLine($"edge {e} on shortest path not tight"); return false; } } Console.WriteLine("Satisfies optimality conditions"); Console.WriteLine(); return true; }