public ShortestPathEnumerator(IGraph <V, E> graph, V src, V dst, IEdgeWeigher <V, E> weigher) { this.graph = CheckNotNull(graph); CheckNotNull(src); this.dst = CheckNotNull(dst); this.weigher = CheckNotNull(weigher); maskingWeigher = new InnerEdgeWeigher(weigher); next = () => search.Search(graph, src, dst, weigher, 1).Paths.FirstOrDefault(); }
/// <inheritdoc/> protected override IResult <V, E> InternalSearch(IGraph <V, E> graph, V src, V dst, IEdgeWeigher <V, E> weigher, int maxPaths = 1) { CheckNotNull(weigher, "The edge weigher cannot be null."); CheckArgument(maxPaths != AllPaths, "KShortestPath cannot search all paths."); CheckArgument(maxPaths > 0, "The max number of paths must be greater than 0."); IGraph <V, E> originalGraph = CheckNotNull(graph, "The graph cannot be null."); var modifiedWeigher = new InnerEdgeWeigher(weigher); var result = new InnerOrderedResult(src, dst, maxPaths); var resultPaths = new List <IPath <V, E> >(maxPaths); var potentialPaths = new List <IPath <V, E> >(); var dijkstraSearch = new DijkstraGraphSearch <V, E>(); ISet <IPath <V, E> > dijkstraResults = dijkstraSearch.Search(originalGraph, src, dst, modifiedWeigher, 1).Paths; // Checks if the destination was reachable. if (dijkstraResults.Count == 0) { log.Warn("No path was found."); return(result); } // If it was reachable, add the first shortest path to the set of results. resultPaths.Add(dijkstraResults.First()); for (int k = 1; k < maxPaths; ++k) { for (int i = 0; i < resultPaths[k - 1].Edges.Count; ++i) { V spurNode = resultPaths[k - 1].Edges[i].Src; List <E> rootPathEdgeList = resultPaths[k - 1].Edges.Take(i).ToList(); foreach (IPath <V, E> path in resultPaths) { if (path.Edges.Count >= i && rootPathEdgeList.SequenceEqual(path.Edges.Take(i))) { modifiedWeigher.RemovedEdges.Add(path.Edges[i]); } } // Effectively remove all nodes from the source path. foreach (E edge in rootPathEdgeList) { foreach (E e in originalGraph.GetEdgesFrom(edge.Src)) { modifiedWeigher.RemovedEdges.Add(e); } foreach (E e in originalGraph.GetEdgesTo(edge.Src)) { modifiedWeigher.RemovedEdges.Add(e); } } dijkstraResults = dijkstraSearch.Search(originalGraph, spurNode, dst, modifiedWeigher, 1).Paths; if (dijkstraResults.Count > 0) { IPath <V, E> spurPath = dijkstraResults.First(); var totalPath = new List <E>(rootPathEdgeList); foreach (E edge in spurPath.Edges) { totalPath.Add(edge); } // The following line must use the original weigher, not the modified weigher, because the // modifed weigher will count -1 values used for modifying the graph and return an inaccurate cost. potentialPaths.Add(new DefaultPath <V, E>(totalPath, CalculatePathCost(weigher, totalPath))); } // Restore all removed paths and nodes. modifiedWeigher.RemovedEdges.Clear(); } if (potentialPaths.Count == 0) { break; } potentialPaths.Sort(new InnerPathComparer()); resultPaths.Add(potentialPaths[0]); potentialPaths.RemoveAt(0); } resultPaths.ForEach(p => result.PathSet.Add(p)); return(result); }