public void GraphExploration()
        {
            var graph     = new AdjacencyGraph <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> >();
            var algorithm = new CloneableVertexGraphExplorerAlgorithm <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> >(graph);

            IEnumerable <ITransitionFactory <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> > > factories =
                GenerateTransitionFactories(
                    out IEnumerable <EquatableCloneableTestVertex> vertices,
                    out _);

            EquatableCloneableTestVertex[] verticesArray = vertices.ToArray();

            algorithm.AddTransitionFactories(factories);

            var discoveredVertices = new List <EquatableCloneableTestVertex>(verticesArray);

            algorithm.DiscoverVertex += vertex =>
            {
                Assert.IsTrue(discoveredVertices.Remove(vertex));
            };

            algorithm.TreeEdge    += Assert.IsNotNull;
            algorithm.BackEdge    += Assert.IsNotNull;
            algorithm.EdgeSkipped += _ => Assert.Fail("Edge must not be skipped.");

            algorithm.Compute(verticesArray[0]);

            CollectionAssert.AreEquivalent(
                new[] { verticesArray[7] },
                discoveredVertices);
            // Isolated vertex are not considered unexplored
            CollectionAssert.IsEmpty(algorithm.UnExploredVertices);
            Assert.IsTrue(algorithm.FinishedSuccessfully);
        }
        public void ComputeWithRoot_Throws()
        {
            var graph     = new AdjacencyGraph <CloneableTestVertex, Edge <CloneableTestVertex> >();
            var algorithm = new CloneableVertexGraphExplorerAlgorithm <CloneableTestVertex, Edge <CloneableTestVertex> >(graph);

            // ReSharper disable once AssignNullToNotNullAttribute
            Assert.Throws <ArgumentNullException>(() => algorithm.Compute(null));
            Assert.IsFalse(algorithm.TryGetRootVertex(out _));
        }
        public void GraphExploration_Throws()
        {
            var vertex1 = new CloneableTestVertex();

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

            graph.AddVertex(vertex1);

            var algorithm = new CloneableVertexGraphExplorerAlgorithm <CloneableTestVertex, Edge <CloneableTestVertex> >(graph)
            {
                AddVertexPredicate = vertex => vertex != vertex1
            };

            Assert.Throws <InvalidOperationException>(() => algorithm.Compute(vertex1));
        }
        public void GraphExplorationWithPredicates()
        {
            var graph     = new AdjacencyGraph <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> >();
            var algorithm = new CloneableVertexGraphExplorerAlgorithm <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> >(graph);

            IEnumerable <ITransitionFactory <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> > > factories =
                GenerateTransitionFactories(
                    out IEnumerable <EquatableCloneableTestVertex> vertices,
                    out IEnumerable <Edge <EquatableCloneableTestVertex> > edges);

            EquatableCloneableTestVertex[]        verticesArray = vertices.ToArray();
            Edge <EquatableCloneableTestVertex>[] edgesArray    = edges.ToArray();

            algorithm.AddTransitionFactories(factories);

            algorithm.AddVertexPredicate     = vertex => !vertex.Equals(verticesArray[1]); // vertex2
            algorithm.ExploreVertexPredicate = vertex => !vertex.Equals(verticesArray[4]); // vertex5
            algorithm.AddEdgePredicate       = edge => edge != edgesArray[1];              // edge13

            var discoveredVertices = new List <EquatableCloneableTestVertex>(verticesArray);

            algorithm.DiscoverVertex += vertex =>
            {
                Assert.IsTrue(discoveredVertices.Remove(vertex));
            };

            algorithm.TreeEdge += Assert.IsNotNull;
            algorithm.BackEdge += Assert.IsNotNull;
            var skippedEdge = new List <Edge <EquatableCloneableTestVertex> >();

            algorithm.EdgeSkipped += edge => skippedEdge.Add(edge);

            algorithm.Compute(verticesArray[0]);

            CollectionAssert.AreEquivalent(
                new[] { verticesArray[1], verticesArray[6], verticesArray[7] },
                discoveredVertices);
            CollectionAssert.AreEquivalent(
                new[] { edgesArray[0], edgesArray[1], edgesArray[3] },
                skippedEdge);
            CollectionAssert.IsEmpty(algorithm.UnExploredVertices);
            Assert.IsTrue(algorithm.FinishedSuccessfully);
        }
        public void GraphExplorationWithEarlyEndingEdge()
        {
            var graph     = new AdjacencyGraph <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> >();
            var algorithm = new CloneableVertexGraphExplorerAlgorithm <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> >(graph);

            IEnumerable <ITransitionFactory <EquatableCloneableTestVertex, Edge <EquatableCloneableTestVertex> > > factories =
                GenerateTransitionFactories(
                    out IEnumerable <EquatableCloneableTestVertex> vertices,
                    out _);

            EquatableCloneableTestVertex[] verticesArray = vertices.ToArray();

            algorithm.AddTransitionFactories(factories);

            algorithm.FinishedPredicate =
                new CloneableVertexGraphExplorerAlgorithm
                <
                    EquatableCloneableTestVertex,
                    Edge <EquatableCloneableTestVertex>
                > .DefaultFinishedPredicate(int.MaxValue, 3).Test;

            var discoveredVertices = new List <EquatableCloneableTestVertex>(verticesArray);

            algorithm.DiscoverVertex += vertex =>
            {
                Assert.IsTrue(discoveredVertices.Remove(vertex));
            };

            algorithm.TreeEdge    += Assert.IsNotNull;
            algorithm.BackEdge    += Assert.IsNotNull;
            algorithm.EdgeSkipped += _ => Assert.Fail("Edge must not be skipped.");

            algorithm.Compute(verticesArray[0]);

            CollectionAssert.AreEquivalent(
                new[] { verticesArray[3], verticesArray[4], verticesArray[6], verticesArray[7] },
                discoveredVertices);
            CollectionAssert.AreEquivalent(
                new[] { verticesArray[5] },
                algorithm.UnExploredVertices);
            Assert.IsFalse(algorithm.FinishedSuccessfully);
        }