private void FillJData( [NotNull, ItemNotNull] IEnumerable <TVertex> vertices, [NotNull] TVertex vi, [NotNull] TVertex vk, VertexData pathIk) { foreach (TVertex vj in vertices) { var kj = new SEquatableEdge <TVertex>(vk, vj); if (_data.TryGetValue(kj, out VertexData pathKj)) { double combined = _distanceRelaxer.Combine( pathIk.Distance, pathKj.Distance); var ij = new SEquatableEdge <TVertex>(vi, vj); if (_data.TryGetValue(ij, out VertexData pathIj)) { if (_distanceRelaxer.Compare(combined, pathIj.Distance) < 0) { _data[ij] = new VertexData(combined, vk); } } else { _data[ij] = new VertexData(combined, vk); } } } }
/// <summary> /// Runs the relaxation algorithm on the given <paramref name="edge"/>. /// </summary> /// <param name="edge">Edge to relax.</param> /// <param name="source">Source vertex.</param> /// <param name="target">Target vertex.</param> /// <returns>True if relaxation decreased the target vertex distance, false otherwise.</returns> protected bool Relax(TEdge edge, TVertex source, TVertex target) { Debug.Assert(edge != null); Debug.Assert(source != null); Debug.Assert(target != null); Debug.Assert( (EqualityComparer <TVertex> .Default.Equals(edge.Source, source) && EqualityComparer <TVertex> .Default.Equals(edge.Target, target)) || (EqualityComparer <TVertex> .Default.Equals(edge.Source, target) && EqualityComparer <TVertex> .Default.Equals(edge.Target, source))); double du = Distances[source]; double dv = Distances[target]; double we = Weights(edge); IDistanceRelaxer relaxer = DistanceRelaxer; double duwe = relaxer.Combine(du, we); if (relaxer.Compare(duwe, dv) < 0) { Distances[target] = duwe; return(true); } return(false); }
/// <summary> /// Applies the Bellman Ford algorithm. /// </summary> /// <remarks> /// Does not initialize the predecessor and distance map. /// </remarks> protected override void InternalCompute() { // Getting the number of vertices int nbVertices = VisitedGraph.VertexCount; for (int k = 0; k < nbVertices; ++k) { bool atLeastOneTreeEdge = false; foreach (TEdge edge in VisitedGraph.Edges) { OnExamineEdge(edge); if (Relax(edge)) { atLeastOneTreeEdge = true; OnTreeEdge(edge); } else { OnEdgeNotRelaxed(edge); } } if (!atLeastOneTreeEdge) { break; } } IDistanceRelaxer relaxer = DistanceRelaxer; foreach (TEdge edge in VisitedGraph.Edges) { var edgeWeight = Weights(edge); if (edgeWeight < 0) { throw new InvalidOperationException("Non negative edge weight."); } if (relaxer.Compare( relaxer.Combine(Distances[edge.Source], edgeWeight), Distances[edge.Target]) < 0) { OnEdgeMinimized(edge); FoundNegativeCycle = true; return; } OnEdgeNotMinimized(edge); } FoundNegativeCycle = false; }
/// <summary> /// Applies the Bellman Ford algorithm. /// </summary> /// <remarks> /// Does not initialize the predecessor and distance map. /// </remarks> protected override void InternalCompute() { // Getting the number of vertices int nbVertices = VisitedGraph.VertexCount; for (int k = 0; k < nbVertices; ++k) { bool atLeastOneTreeEdge = false; foreach (TEdge edge in VisitedGraph.Edges) { OnExamineEdge(edge); if (Relax(edge)) { atLeastOneTreeEdge = true; OnTreeEdge(edge); } else { OnEdgeNotRelaxed(edge); } } if (!atLeastOneTreeEdge) { break; } } IDistanceRelaxer relaxer = DistanceRelaxer; foreach (TEdge edge in VisitedGraph.Edges) { double edgeWeight = Weights(edge); if (relaxer.Compare( relaxer.Combine(GetVertexDistance(edge.Source), edgeWeight), GetVertexDistance(edge.Target)) < 0) { OnEdgeMinimized(edge); FoundNegativeCycle = true; return; } OnEdgeNotMinimized(edge); } FoundNegativeCycle = false; }