/// <summary>
        /// Search strict dangling vertices, for example
        /// |\
        /// | \
        /// |__\Y_________Z
        /// In the above draft, Z is a dangling vertex, but Y is not.
        /// </summary>
        /// <returns></returns>
        public IEnumerable <CurveVertex> SearchDanglingVertices()
        {
            // Search none loop vertices.
            var noneLoopVertices = SearchNoneLoopVertices();

            // Depth first search the graph, and find all the path end vertices.
            var result   = new HashSet <CurveVertex>();
            var observer = new VertexPredecessorPathRecorderObserver <CurveVertex, SEdge <CurveVertex> >();
            var dfs      = new DepthFirstSearchAlgorithm <CurveVertex, SEdge <CurveVertex> >((IVertexListGraph <CurveVertex, SEdge <CurveVertex> >)_graph);

            using (observer.Attach(dfs))
            {
                dfs.Compute();
            }
            // Dangling vertex must be an end path vertex.
            foreach (var curveVertex in observer.EndPathVertices)
            {
                if (!noneLoopVertices.Contains(curveVertex))
                {
                    continue;
                }

                result.Add(curveVertex);
                // Check whether this path's root point is a dangling vertex.
                var root = GetRootVertex(observer.VertexPredecessors, curveVertex);
                if (root != null && noneLoopVertices.Contains(root.Value))
                {
                    result.Add(root.Value);
                }
            }
            return(result);
        }
        public IEnumerable <IEnumerable <SEdge <CurveVertex> > > SearchDanglingPaths()
        {
            // Search all none loop vertices
            var noneLoopVertices = SearchNoneLoopVertices();
            var danglingEdges    = new List <SEdge <CurveVertex> >();

            foreach (var vertex in noneLoopVertices)
            {
                IEnumerable <SEdge <CurveVertex> > edges = null;
                if (_graph.TryGetOutEdges(vertex, out edges))
                {
                    danglingEdges.AddRange(edges);
                }
            }

            // Create a small graph.
            var tempGraph = danglingEdges.ToAdjacencyGraph <CurveVertex, SEdge <CurveVertex> >();
            // Deep first search the graph and get all its paths.
            var observer = new VertexPredecessorPathRecorderObserver <CurveVertex, SEdge <CurveVertex> >();
            var dfs      = new DepthFirstSearchAlgorithm <CurveVertex, SEdge <CurveVertex> >((IVertexListGraph <CurveVertex, SEdge <CurveVertex> >)tempGraph);

            using (observer.Attach(dfs))
            {
                dfs.Compute();
            }

            return(observer.AllPaths());
        }
        public static IList <IEnumerable <TaggedEdge <string, string> > > GetPaths(AdjacencyGraph <string, TaggedEdge <string, string> > g)
        {
            var dfs      = new DepthFirstSearchAlgorithm <string, TaggedEdge <string, string> >(g);
            var recorder = new VertexPredecessorPathRecorderObserver <string, TaggedEdge <string, string> >();

            List <IEnumerable <TaggedEdge <string, string> > > results = new List <IEnumerable <TaggedEdge <string, string> > >();

            using (recorder.Attach(dfs))
            {
                dfs.Compute();
                var paths = recorder.AllPaths();
                foreach (var p in paths)
                {
                    results.Add(p);
                }
            }
            return(results);
        }
        public void Constructor()
        {
            var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

            CollectionAssert.IsEmpty(recorder.VerticesPredecessors);
            CollectionAssert.IsEmpty(recorder.EndPathVertices);

            var predecessors = new Dictionary <int, Edge <int> >();

            recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(predecessors);
            Assert.AreSame(predecessors, recorder.VerticesPredecessors);
            CollectionAssert.IsEmpty(recorder.EndPathVertices);

            predecessors = new Dictionary <int, Edge <int> >
            {
                [1] = new Edge <int>(2, 1)
            };
            recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(predecessors);
            Assert.AreSame(predecessors, recorder.VerticesPredecessors);
            CollectionAssert.IsEmpty(recorder.EndPathVertices);
        }
        public void Attach()
        {
            // DFS is used for tests but result may change if using another search algorithm
            // or another starting point
            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                var graph = new AdjacencyGraph <int, Edge <int> >();

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.IsEmpty(recorder.VerticesPredecessors);
                    CollectionAssert.IsEmpty(recorder.EndPathVertices);
                }
            }

            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                var graph = new AdjacencyGraph <int, Edge <int> >();
                graph.AddVertexRange(new[] { 1, 2 });

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.IsEmpty(recorder.VerticesPredecessors);
                    CollectionAssert.AreEquivalent(new[] { 1, 2 }, recorder.EndPathVertices);
                }
            }

            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                // Graph without cycle
                var edge12 = new Edge <int>(1, 2);
                var edge13 = new Edge <int>(1, 3);
                var edge14 = new Edge <int>(1, 4);
                var edge24 = new Edge <int>(2, 4);
                var edge31 = new Edge <int>(3, 1);
                var edge33 = new Edge <int>(3, 3);
                var edge34 = new Edge <int>(3, 4);
                var graph  = new AdjacencyGraph <int, Edge <int> >();
                graph.AddVerticesAndEdgeRange(new[]
                {
                    edge12, edge13, edge14, edge24, edge31, edge33, edge34
                });

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.AreEqual(
                        new Dictionary <int, Edge <int> >
                    {
                        [2] = edge12,
                        [3] = edge13,
                        [4] = edge24
                    },
                        recorder.VerticesPredecessors);
                    CollectionAssert.AreEquivalent(new[] { 3, 4 }, recorder.EndPathVertices);
                }
            }

            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                // Graph with cycle
                var edge12 = new Edge <int>(1, 2);
                var edge13 = new Edge <int>(1, 3);
                var edge14 = new Edge <int>(1, 4);
                var edge24 = new Edge <int>(2, 4);
                var edge31 = new Edge <int>(3, 1);
                var edge33 = new Edge <int>(3, 3);
                var edge34 = new Edge <int>(3, 4);
                var edge41 = new Edge <int>(4, 1);
                var graph  = new AdjacencyGraph <int, Edge <int> >();
                graph.AddVerticesAndEdgeRange(new[]
                {
                    edge12, edge13, edge14, edge24, edge31, edge33, edge34, edge41
                });

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.AreEqual(
                        new Dictionary <int, Edge <int> >
                    {
                        [2] = edge12,
                        [3] = edge13,
                        [4] = edge24
                    },
                        recorder.VerticesPredecessors);
                    CollectionAssert.AreEquivalent(new[] { 3, 4 }, recorder.EndPathVertices);
                }
            }
        }
        public void AllPaths()
        {
            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                var graph = new AdjacencyGraph <int, Edge <int> >();

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.IsEmpty(recorder.AllPaths());
                }
            }

            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                var graph = new AdjacencyGraph <int, Edge <int> >();
                graph.AddVertexRange(new[] { 1, 2 });

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.IsEmpty(recorder.AllPaths());
                }
            }

            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                // Graph without cycle
                var edge12 = new Edge <int>(1, 2);
                var edge13 = new Edge <int>(1, 3);
                var edge14 = new Edge <int>(1, 4);
                var edge24 = new Edge <int>(2, 4);
                var edge31 = new Edge <int>(3, 1);
                var edge33 = new Edge <int>(3, 3);
                var edge34 = new Edge <int>(3, 4);
                var graph  = new AdjacencyGraph <int, Edge <int> >();
                graph.AddVerticesAndEdgeRange(new[]
                {
                    edge12, edge13, edge14, edge24, edge31, edge33, edge34
                });

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.AreEquivalent(
                        new IEnumerable <Edge <int> >[]
                    {
                        new[] { edge13 },
                        new[] { edge12, edge24 }
                    },
                        recorder.AllPaths());
                }
            }

            {
                var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >();

                // Graph with cycle
                var edge12 = new Edge <int>(1, 2);
                var edge13 = new Edge <int>(1, 3);
                var edge14 = new Edge <int>(1, 4);
                var edge24 = new Edge <int>(2, 4);
                var edge31 = new Edge <int>(3, 1);
                var edge33 = new Edge <int>(3, 3);
                var edge34 = new Edge <int>(3, 4);
                var edge41 = new Edge <int>(4, 1);
                var graph  = new AdjacencyGraph <int, Edge <int> >();
                graph.AddVerticesAndEdgeRange(new[]
                {
                    edge12, edge13, edge14, edge24, edge31, edge33, edge34, edge41
                });

                var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph);
                using (recorder.Attach(dfs))
                {
                    dfs.Compute();

                    CollectionAssert.AreEquivalent(
                        new IEnumerable <Edge <int> >[]
                    {
                        new[] { edge13 },
                        new[] { edge12, edge24 }
                    },
                        recorder.AllPaths());
                }
            }
        }