예제 #1
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);
            }
        }