예제 #1
0
 /// <summary>
 /// Determines value equality.
 /// </summary>
 /// <param name="other">The other object to compare against.</param>
 /// <returns>True if the objects are equal.</returns>
 /// TODO: Should this be virtual?
 protected virtual bool IsEqual(DefaultMutablePath <V, E> other)
 {
     return(Src.Equals(other.Src) &&
            Dst.Equals(other.Dst) &&
            Cost.Equals(other.Cost) &&
            Edges.SequenceEqual(other.Edges));
 }
예제 #2
0
 /// <inheritdoc/>
 public bool Equals(DefaultMutablePath <V, E> other)
 {
     if (other is null)
     {
         return(false);
     }
     if (ReferenceEquals(this, other))
     {
         return(true);
     }
     return(IsEqual(other));
 }
예제 #3
0
        /// <summary>
        /// Builds a set of all paths between the source and destination using the graph search
        /// result by applying breadth-first search through the parent edges and vertex costs.
        /// </summary>
        /// <param name="result">The graph search result.</param>
        /// <param name="src">The source vertex.</param>
        /// <param name="dst">The destination vertex.</param>
        /// <param name="maxPaths">The limit on the number of paths built, <see cref="AllPaths"/> for no limit.</param>
        private static void BuildAllPaths(DefaultResult result, V src, V dst, int maxPaths = AllPaths)
        {
            var basePath = new DefaultMutablePath <V, E>();

            basePath.Cost = result.GetCost(dst);
            var pendingPaths = new HashSet <DefaultMutablePath <V, E> >();

            pendingPaths.Add(basePath);

            while (pendingPaths.Count != 0 &&
                   (maxPaths == AllPaths || result.Paths.Count < maxPaths))
            {
                var frontier = new HashSet <DefaultMutablePath <V, E> >();

                foreach (DefaultMutablePath <V, E> path in pendingPaths)
                {
                    // For each pending path, locate its first vertex
                    // since we will be moving backwards from it.
                    V firstVertex = GetFirstVertex(path, dst);

                    // If the first vertex is our expected source, we have reached
                    // the beginning, so add this path to the result paths.
                    if (firstVertex.Equals(src))
                    {
                        path.Cost = result.GetCost(dst);
                        result.Paths.Add(new DefaultPath <V, E>(path.Edges, path.Cost));
                    }
                    else
                    {
                        // If we have not reached the beginning, i.e. the source, fetch the
                        // set of edges leading to the first vertex of this pending path.
                        // If there are none, abandon processing this path for good.
                        ISet <E> firstVertexParents = result.Parents.GetOrDefault(firstVertex, new HashSet <E>());
                        if (firstVertexParents is null || firstVertexParents?.Count is 0)
                        {
                            break;
                        }

                        // Now, iterate over all the edges and for each of them cloning the current
                        // path and then inserting that edge to the path and adding that path to the
                        // pending ones. When processing the last edge, modify the current pending
                        // path rather than cloning a new one.
                        List <E> edges = firstVertexParents.ToList();
                        for (int i = 0; i < edges.Count; ++i)
                        {
                            E    edge   = edges[i];
                            bool isLast = i == edges.Count - 1;
                            // Exclude any looping paths.
                            if (!IsInPath(edge, path))
                            {
                                DefaultMutablePath <V, E> pendingPath = isLast ? path : new DefaultMutablePath <V, E>(path);
                                pendingPath.InsertEdge(edge);
                                frontier.Add(pendingPath);
                            }
                        }
                    }
                }

                // All pending paths have been scaned, so promote the next frontier.
                pendingPaths = frontier;
            }
        }