Ejemplo n.º 1
0
        private void EnqueueFirstShortestPath(
            IQueue <DeviationPath> queue,
            IDictionary <TVertex, TEdge> successors,
            IDictionary <TVertex, double> distances,
            TVertex root)
        {
            Contract.Requires(queue != null);
            Contract.Requires(queue.Count == 0);
            Contract.Requires(successors != null);
            Contract.Requires(distances != null);
            Contract.Requires(root != null);

            var path = new List <TEdge>();

            AppendShortestPath(
                path,
                successors,
                root);
            if (path.Count == 0)
            {
                return; // unreachable vertices
            }
            if (!EdgeExtensions.HasCycles <TVertex, TEdge>(path))
            {
                this.AddComputedShortestPath(path);
            }

            // create deviation paths
            this.EnqueueDeviationPaths(
                queue,
                root,
                distances,
                path.ToArray(),
                0);
        }
        protected override void InternalCompute()
        {
            var     cancelManager = this.Services.CancelManager;
            TVertex root;

            if (!this.TryGetRootVertex(out root))
            {
                throw new InvalidOperationException("root vertex not set");
            }
            TVertex goal;

            if (!this.TryGetGoalVertex(out goal))
            {
                throw new InvalidOperationException("goal vertex not set");
            }

            // start by building the minimum tree starting from the goal vertex.
            IDictionary <TVertex, TEdge>  successors;
            IDictionary <TVertex, double> distances;

            this.ComputeMinimumTree(goal, out successors, out distances);

            if (cancelManager.IsCancelling)
            {
                return;
            }

            var queue       = new FibonacciQueue <DeviationPath, double>(dp => dp.Weight);
            var vertexCount = this.VisitedGraph.VertexCount;

            // first shortest path
            this.EnqueueFirstShortestPath(queue, successors, distances, root);

            while (queue.Count > 0 &&
                   this.ComputedShortestPathCount < this.ShortestPathCount)
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }

                var deviation = queue.Dequeue();

                // turn into path
                var path = new List <TEdge>();
                for (int i = 0; i < deviation.DeviationIndex; ++i)
                {
                    path.Add(deviation.ParentPath[i]);
                }
                path.Add(deviation.DeviationEdge);
                int startEdge = path.Count;
                this.AppendShortestPath(path, successors, deviation.DeviationEdge.Target);

                Contract.Assert(deviation.Weight == Enumerable.Sum(path, e => edgeWeights(e)));
                Contract.Assert(path.Count > 0);

                // add to list if loopless
                if (!EdgeExtensions.HasCycles <TVertex, TEdge>(path))
                {
                    this.AddComputedShortestPath(path);
                }

                // append new deviation paths
                if (path.Count < vertexCount)
                {
                    this.EnqueueDeviationPaths(
                        queue,
                        root,
                        successors,
                        distances,
                        path.ToArray(),
                        startEdge
                        );
                }
            }
        }