コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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));
        }
コード例 #3
0
        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));
        }
コード例 #4
0
        /// <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;
        }
コード例 #5
0
        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);
                }
            }
        }
コード例 #6
0
        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);
            }
        }
コード例 #7
0
        /// <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);
            }
        }
コード例 #9
0
        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);
            }
        }
コード例 #10
0
        /// <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);
        }