示例#1
0
        /// <summary>
        /// Find all possible paths between two vertices.
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <param name="graph"></param>
        /// <param name="start"></param>
        /// <param name="destination"></param>
        /// <param name="vertexComparer"></param>
        /// <returns></returns>
        public static IEnumerable <IReadOnlyList <V> > FindAllPaths <V, E>(this IDirectedGraph <V, E> graph, V start, V destination,
                                                                           IEqualityComparer <V> vertexComparer = null)
        {
            using (Trace.Entering())
            {
                vertexComparer = vertexComparer ?? EqualityComparer <V> .Default;

                HashSet <V> used = new HashSet <V>(vertexComparer);
                used.Add(start);

                List <V> localPath = new List <V>();

                IEnumerable <IReadOnlyList <V> > result = graph.FindAllPathsInternal(start, destination, localPath, used, vertexComparer);
                return(result);
            }
        }
示例#2
0
        private static IEnumerable <List <V> > FindAllPathsInternal <V, E>(this IDirectedGraph <V, E> graph,
                                                                           V start, V destination,
                                                                           List <V> localPath,
                                                                           HashSet <V> alreadyUsed,
                                                                           IEqualityComparer <V> vertexComparer)
        {
            using (Trace.Entering())
            {
                localPath.Add(start);

                var toGo = graph.GetEdgesGoingFrom(start)
                           .Select(x => x.To)
                           .ToHashSet(vertexComparer);

                foreach (var to in toGo)
                {
                    if (vertexComparer.Equals(to, destination))
                    {
                        localPath.Add(to);

                        // Provide the whole path.
                        List <V> result = localPath.ToList();

                        localPath.RemoveAt(localPath.Count - 1);

                        yield return(result);

                        // If the self-reference is not included yet.
                        if (!vertexComparer.Equals(start, to))
                        {
                            List <V> pathWithSelfreferencingDestination = null;
                            bool     selfReferencingDestination         = graph.GetEdges(destination, destination).Any();
                            if (selfReferencingDestination)
                            {
                                pathWithSelfreferencingDestination = result.ToList();
                                pathWithSelfreferencingDestination.Add(destination);
                                yield return(pathWithSelfreferencingDestination);
                            }

                            // If an edge to itself exists then include it to the result.
                            if (toGo.Contains(start))
                            {
                                var pathWithSelfReference = result.ToList();
                                pathWithSelfReference.Insert(result.Count - 1, start);
                                yield return(pathWithSelfReference);

                                if (selfReferencingDestination)
                                {
                                    var pathWithBothSelfReferences = pathWithSelfReference.ToList();
                                    pathWithBothSelfReferences.Add(destination);
                                    yield return(pathWithBothSelfReferences);
                                }
                            }
                        }
                    }
                    else if (alreadyUsed.Add(to))
                    {
                        IEnumerable <List <V> > foundPaths = graph.FindAllPathsInternal(to, destination, localPath, alreadyUsed, vertexComparer);
                        foreach (var path in foundPaths)
                        {
                            // Return the path.
                            yield return(path);
                        }

                        alreadyUsed.Add(start);
                    }
                }

                localPath.RemoveAt(localPath.Count - 1);
            }
        }