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 AddTransitionFactories_Throws()
        {
            var graph     = new AdjacencyGraph <CloneableTestVertex, Edge <CloneableTestVertex> >();
            var algorithm = new CloneableVertexGraphExplorerAlgorithm <CloneableTestVertex, Edge <CloneableTestVertex> >(graph);

            // ReSharper disable once AssignNullToNotNullAttribute
            Assert.Throws <ArgumentNullException>(() => algorithm.AddTransitionFactories(null));
        }
        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);
        }
        public void RemoveTransitionFactories()
        {
            var graph     = new AdjacencyGraph <CloneableTestVertex, Edge <CloneableTestVertex> >();
            var algorithm = new CloneableVertexGraphExplorerAlgorithm <CloneableTestVertex, Edge <CloneableTestVertex> >(graph);

            Assert.IsFalse(algorithm.RemoveTransitionFactory(null));

            var vertex1  = new CloneableTestVertex("1");
            var vertex2  = new CloneableTestVertex("2");
            var vertex3  = new CloneableTestVertex("3");
            var factory1 = new TestTransitionFactory <CloneableTestVertex>(vertex1, Enumerable.Empty <Edge <CloneableTestVertex> >());
            var factory2 = new TestTransitionFactory <CloneableTestVertex>(vertex2, Enumerable.Empty <Edge <CloneableTestVertex> >());
            var factory3 = new TestTransitionFactory <CloneableTestVertex>(vertex3, Enumerable.Empty <Edge <CloneableTestVertex> >());

            algorithm.AddTransitionFactories(new[] { factory1, factory2 });

            Assert.IsFalse(algorithm.ContainsTransitionFactory(null));
            Assert.IsTrue(algorithm.ContainsTransitionFactory(factory1));
            Assert.IsTrue(algorithm.ContainsTransitionFactory(factory2));

            Assert.IsFalse(algorithm.RemoveTransitionFactory(factory3));
            Assert.IsTrue(algorithm.RemoveTransitionFactory(factory1));
            Assert.IsFalse(algorithm.RemoveTransitionFactory(factory1));
            Assert.IsTrue(algorithm.RemoveTransitionFactory(factory2));

            var factory4 = new TestTransitionFactory <CloneableTestVertex>(
                vertex1,
                new[]
            {
                new Edge <CloneableTestVertex>(vertex1, vertex2),
                new Edge <CloneableTestVertex>(vertex1, vertex3)
            });

            algorithm.AddTransitionFactory(factory4);
            Assert.IsTrue(algorithm.ContainsTransitionFactory(factory4));
        }