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();
 }
Example #2
0
        /// <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);
        }