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 graph <tt>G</tt>. /// </summary> /// <param name="g">g the edge-weighted graph</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 DijkstraUndirectedSP(EdgeWeightedGraph 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 EdgeW[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, v); } // check optimality conditions //assert check(G, s); }
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 graph <tt>G</tt>. /// </summary> /// <param name="g">g the edge-weighted graph</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 DijkstraUndirectedSP(EdgeWeightedGraph 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 EdgeW[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, v); } } // check optimality conditions //assert check(G, s); }
/// <summary> /// scan vertex v /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Scan(EdgeWeightedGraph g, int v) { _marked[v] = true; foreach (var e in g.Adj(v)) { var w = e.Other(v); if (_marked[w]) { continue; // v-w is obsolete edge } if (e.Weight < _distTo[w]) { _distTo[w] = e.Weight; _edgeTo[w] = e; if (_pq.Contains(w)) { _pq.DecreaseKey(w, _distTo[w]); } else { _pq.Insert(w, _distTo[w]); } } } }
/// <summary> /// add all edges e incident to v onto pq if the other endpoint has not yet been scanned /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Scan(EdgeWeightedGraph g, int v) { //assert !marked[v]; _marked[v] = true; foreach (var e in g.Adj(v)) { if (!_marked[e.Other(v)]) { _pq.Insert(e); } } }
/// <summary> /// add all edges e incident to v onto pq if the other endpoint has not yet been scanned /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Scan(EdgeWeightedGraph g, int v) { //assert !marked[v]; _marked[v] = true; foreach (var e in g.Adj(v)) if (!_marked[e.Other(v)]) _pq.Insert(e); }
/// <summary> /// check optimality conditions: /// (i) for all edges e = v-w: distTo[w] <= distTo[v] + e.weight() /// (ii) for all edge e = v-w on the SPT: distTo[w] == distTo[v] + e.weight() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedGraph 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)) { var w = e.Other(v); 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]; if (w != e.Either() && w != e.Other(e.Either())) { return(false); } int v = e.Other(w); 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 = v-w: distTo[w] <= distTo[v] + e.weight() /// (ii) for all edge e = v-w on the SPT: distTo[w] == distTo[v] + e.weight() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedGraph 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)) { var w = e.Other(v); 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]; if (w != e.Either() && w != e.Other(e.Either())) return false; int v = e.Other(w); 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> /// scan vertex v /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Scan(EdgeWeightedGraph g, int v) { _marked[v] = true; foreach (var e in g.Adj(v)) { var w = e.Other(v); if (_marked[w]) continue; // v-w is obsolete edge if (e.Weight < _distTo[w]) { _distTo[w] = e.Weight; _edgeTo[w] = e; if (_pq.Contains(w)) _pq.DecreaseKey(w, _distTo[w]); else _pq.Insert(w, _distTo[w]); } } }