/// <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([NotNull] TEdge edge, [NotNull] TVertex source, [NotNull] 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 = GetVertexDistance(source); double dv = GetVertexDistance(target); double we = Weights(edge); double duwe = DistanceRelaxer.Combine(du, we); if (DistanceRelaxer.Compare(duwe, dv) < 0) { SetVertexDistance(target, duwe); return(true); } return(false); }
private void OnEdgeDiscovered([NotNull] TEdge edge) { Debug.Assert(edge != null); if (!Distances.TryGetValue(edge.Source, out double sourceDistance)) { Distances[edge.Source] = sourceDistance = DistanceRelaxer.InitialDistance; } Distances[edge.Target] = DistanceRelaxer.Combine(sourceDistance, EdgeWeights(edge)); }
private void OnEdgeDiscovered([NotNull] object sender, [NotNull] UndirectedEdgeEventArgs <TVertex, TEdge> args) { Debug.Assert(sender != null); Debug.Assert(args != null); if (!Distances.TryGetValue(args.Source, out double sourceDistance)) { Distances[args.Source] = sourceDistance = DistanceRelaxer.InitialDistance; } Distances[args.Target] = DistanceRelaxer.Combine(sourceDistance, EdgeWeights(args.Edge)); }
/// <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; } } foreach (TEdge edge in VisitedGraph.Edges) { double edgeWeight = Weights(edge); if (DistanceRelaxer.Compare( DistanceRelaxer.Combine(GetVertexDistance(edge.Source), edgeWeight), GetVertexDistance(edge.Target)) < 0) { OnEdgeMinimized(edge); FoundNegativeCycle = true; return; } OnEdgeNotMinimized(edge); } FoundNegativeCycle = false; }
private void EnqueueDeviationPaths( [NotNull] IQueue <DeviationPath> queue, [NotNull] IDictionary <TVertex, double> distances, [NotNull, ItemNotNull] TEdge[] path, int edgeIndex, [NotNull] TVertex previousVertex, double previousWeight) { Debug.Assert(queue != null); Debug.Assert(distances != null); Debug.Assert(path != null); Debug.Assert(previousVertex != null); TEdge edge = path[edgeIndex]; foreach (TEdge deviationEdge in VisitedGraph.OutEdges(previousVertex)) { // Skip self edges and equal edges if (EqualityComparer <TEdge> .Default.Equals(deviationEdge, edge) || deviationEdge.IsSelfEdge()) { continue; } // Any edge obviously creating a loop TVertex target = deviationEdge.Target; if (distances.TryGetValue(target, out double distance)) { double deviationWeight = DistanceRelaxer.Combine( previousWeight, DistanceRelaxer.Combine( _edgeWeights(deviationEdge), distance)); var deviation = new DeviationPath( path, edgeIndex, deviationEdge, deviationWeight); queue.Enqueue(deviation); } } }
private void OnAStarTreeEdge([NotNull] TEdge edge) { Debug.Assert(edge != null); bool decreased = Relax(edge); if (decreased) { TVertex target = edge.Target; double distance = GetVertexDistance(target); _costs[target] = DistanceRelaxer.Combine(distance, CostHeuristic(target)); OnTreeEdge(edge); } else { OnEdgeNotRelaxed(edge); } }
/// <summary> /// Runs the relaxation algorithm on the given <paramref name="edge"/>. /// </summary> /// <param name="edge">Edge to relax.</param> /// <returns>True if relaxation decreased the target vertex distance, false otherwise.</returns> protected bool Relax([NotNull] TEdge edge) { Debug.Assert(edge != null); TVertex source = edge.Source; TVertex target = edge.Target; double du = GetVertexDistance(source); double dv = GetVertexDistance(target); double we = Weights(edge); double duwe = DistanceRelaxer.Combine(du, we); if (DistanceRelaxer.Compare(duwe, dv) < 0) { _distances[target] = duwe; return(true); } return(false); }
private void OnGrayTarget(TEdge edge) { Debug.Assert(edge != null); bool decreased = Relax(edge); if (decreased) { TVertex target = edge.Target; double distance = Distances[target]; _costs[target] = DistanceRelaxer.Combine(distance, CostHeuristic(target)); _vertexQueue.Update(target); OnTreeEdge(edge); } else { OnEdgeNotRelaxed(edge); } }
private void OnBlackTarget([NotNull] TEdge edge) { Debug.Assert(edge != null); bool decreased = Relax(edge); if (decreased) { TVertex target = edge.Target; double distance = GetVertexDistance(target); OnTreeEdge(edge); _costs[target] = DistanceRelaxer.Combine(distance, CostHeuristic(target)); _vertexQueue.Enqueue(target); VerticesColors[target] = GraphColor.Gray; } else { OnEdgeNotRelaxed(edge); } }
/// <summary> /// Runs the relaxation algorithm on the given <paramref name="edge"/>. /// </summary> /// <param name="edge">Edge to relax.</param> /// <returns>True if relaxation decreased the target vertex distance, false otherwise.</returns> protected bool Relax([NotNull] TEdge edge) { if (edge == null) { throw new ArgumentNullException(nameof(edge)); } TVertex source = edge.Source; TVertex target = edge.Target; double du = Distances[source]; double dv = Distances[target]; double we = Weights(edge); double duwe = DistanceRelaxer.Combine(du, we); if (DistanceRelaxer.Compare(duwe, dv) < 0) { Distances[target] = duwe; return(true); } return(false); }