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 ); } } }