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); }
/// <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; }
/// <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); }