/// <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)); }
/// <inheritdoc/> public bool Equals(DefaultMutablePath <V, E> other) { if (other is null) { return(false); } if (ReferenceEquals(this, other)) { return(true); } return(IsEqual(other)); }
/// <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; } }