using NUnit.Framework; using FluentAssertions; using System; using System.Linq; using Encompass; using System.Collections.Generic; namespace Tests { public class DirectedGraphTest { [Test] public void AddVertex() { var myGraph = new DirectedGraph(); myGraph.AddVertex(4); Assert.That(myGraph.Vertices, Does.Contain(4)); } [Test] public void AddVertices() { var myGraph = new DirectedGraph(); myGraph.AddVertices(4, 20, 69); Assert.IsTrue(myGraph.VertexExists(4)); Assert.IsTrue(myGraph.VertexExists(20)); Assert.IsTrue(myGraph.VertexExists(69)); } [Test] public void AddEdge() { var myGraph = new DirectedGraph(); myGraph.AddVertices(5, 6); myGraph.AddEdge(5, 6); Assert.That(myGraph.Neighbors(5), Does.Contain(6)); } [Test] public void AddEdges() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 2), (2, 3), (2, 4), (3, 4) ); Assert.That(myGraph.Neighbors(1), Does.Contain(2)); Assert.That(myGraph.Neighbors(2), Does.Contain(3)); Assert.That(myGraph.Neighbors(2), Does.Contain(4)); Assert.That(myGraph.Neighbors(3), Does.Contain(4)); Assert.That(myGraph.Neighbors(1), Does.Not.Contain(4)); } [Test] public void RemoveEdge() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 2), (2, 3), (2, 4), (3, 4) ); myGraph.RemoveEdge(2, 3); Assert.That(myGraph.Neighbors(2), Does.Not.Contain(3)); Assert.That(myGraph.Neighbors(2), Does.Contain(4)); } [Test] public void RemoveVertex() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 2), (2, 3), (2, 4), (3, 4) ); myGraph.RemoveVertex(2); myGraph.Vertices.Should().NotContain(2); myGraph.Neighbors(1).Should().NotContain(2); myGraph.Neighbors(3).Should().Contain(4); } [Test] public void NodeDFS() { var myGraph = new DirectedGraph(); myGraph.AddVertices('a', 'b', 'c', 'd'); myGraph.AddEdges( ('a', 'b'), ('a', 'c'), ('b', 'd') ); var result = myGraph.NodeDFS(); Assert.That(result['a'][SearchSymbol.start], Is.EqualTo(1)); Assert.That(result['a'][SearchSymbol.finish], Is.EqualTo(8)); Assert.That(result['b'][SearchSymbol.start], Is.EqualTo(2)); Assert.That(result['b'][SearchSymbol.finish], Is.EqualTo(5)); Assert.That(result['c'][SearchSymbol.start], Is.EqualTo(6)); Assert.That(result['c'][SearchSymbol.finish], Is.EqualTo(7)); Assert.That(result['d'][SearchSymbol.start], Is.EqualTo(3)); Assert.That(result['d'][SearchSymbol.finish], Is.EqualTo(4)); } [Test] public void TopologicalSortSimple() { var simpleGraph = new DirectedGraph(); simpleGraph.AddVertices('a', 'b', 'c', 'd'); simpleGraph.AddEdges( ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'd') ); Assert.That(simpleGraph.TopologicalSort(), Is.EqualTo(new char[] { 'a', 'c', 'b', 'd' })); } [Test] public void TopologicalSortComplex() { var complexGraph = new DirectedGraph(); complexGraph.AddVertices('a', 'b', 'c', 'd', 'e', 'f', 'g', 't', 'm'); complexGraph.AddEdges( ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'f'), ('b', 'g'), ('c', 'g'), ('e', 't'), ('t', 'm') ); Assert.That( complexGraph.TopologicalSort(), Is.EqualTo(new char[] { 'e', 't', 'm', 'a', 'd', 'c', 'b', 'g', 'f' }) ); } [Test] public void LongestPaths() { var graph = new DirectedGraph(); graph.AddVertices('r', 's', 't', 'x', 'y', 'z'); graph.AddEdges( ('r', 's'), ('r', 't'), ('s', 'x'), ('s', 't'), ('t', 'y'), ('t', 'x'), ('x', 'y'), ('y', 'z') ); var result = graph.LongestPaths('r'); result.Should().Contain(('r', 0)); result.Should().Contain(('s', 1)); result.Should().Contain(('t', 2)); result.Should().Contain(('x', 3)); result.Should().Contain(('y', 4)); result.Should().Contain(('z', 5)); } [Test] public void StronglyConnectedComponentsSimple() { var simpleGraph = new DirectedGraph(); simpleGraph.AddVertices(1, 2, 3); simpleGraph.AddEdges( (1, 2), (2, 3), (3, 2), (2, 1) ); var result = simpleGraph.StronglyConnectedComponents(); var scc = new int[] { 1, 2, 3 }; result.Should().ContainEquivalentOf(scc); Assert.That(result.Count, Is.EqualTo(1)); } [Test] public void StronglyConnectedComponentsMedium() { var mediumGraph = new DirectedGraph(); mediumGraph.AddVertices(1, 2, 3, 4); mediumGraph.AddEdges( (1, 2), (1, 3), (1, 4), (4, 2), (3, 4), (2, 3) ); var result = mediumGraph.StronglyConnectedComponents(); var sccA = new int[] { 2, 3, 4 }; var sccB = new int[] { 1 }; result.Should().ContainEquivalentOf(sccA); result.Should().ContainEquivalentOf(sccB); Assert.That(result.Count, Is.EqualTo(2)); } [Test] public void StronglyConnectedComponentsComplex() { var complexGraph = new DirectedGraph(); complexGraph.AddVertices(1, 2, 3, 4, 5, 6, 7, 8); complexGraph.AddEdges( (1, 2), (2, 3), (2, 8), (3, 4), (3, 7), (4, 5), (5, 3), (5, 6), (7, 4), (7, 6), (8, 1), (8, 7) ); var result = complexGraph.StronglyConnectedComponents(); var sccA = new int[] { 3, 4, 5, 7 }; var sccB = new int[] { 1, 2, 8 }; var sccC = new int[] { 6 }; result.Should().ContainEquivalentOf(sccA); result.Should().ContainEquivalentOf(sccB); result.Should().ContainEquivalentOf(sccC); Assert.That(result.Count, Is.EqualTo(3)); } [Test] public void Clone() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 1), (1, 2), (2, 3), (2, 1), (3, 4) ); var clone = myGraph.Clone(); Assert.That(clone, Is.Not.EqualTo(myGraph)); clone.Vertices.Should().BeEquivalentTo(1, 2, 3, 4); clone.Neighbors(1).Should().BeEquivalentTo(1, 2); clone.Neighbors(2).Should().BeEquivalentTo(3, 1); clone.Neighbors(3).Should().BeEquivalentTo(4); } [Test] public void SubGraph() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 1), (1, 2), (2, 3), (2, 1), (3, 4) ); var subGraph = myGraph.SubGraph(1, 2, 3); subGraph.Vertices.Should().BeEquivalentTo(1, 2, 3); subGraph.Neighbors(1).Should().BeEquivalentTo(1, 2); subGraph.Neighbors(2).Should().BeEquivalentTo(1, 3); subGraph.Neighbors(3).Should().NotContain(4); } [Test] public void SimpleCyclesSimple() { var myGraph = new DirectedGraph(); myGraph.AddVertices(0, 1, 2); myGraph.AddEdges( (0, 0), (0, 1), (0, 2), (1, 2), (2, 0), (2, 1), (2, 2) ); var result = myGraph.SimpleCycles(); var cycleA = new int[] { 0 }; var cycleB = new int[] { 0, 1, 2 }; var cycleC = new int[] { 0, 2 }; var cycleD = new int[] { 1, 2 }; var cycleE = new int[] { 2 }; result.Should().ContainEquivalentOf(cycleA); result.Should().ContainEquivalentOf(cycleB); result.Should().ContainEquivalentOf(cycleC); result.Should().ContainEquivalentOf(cycleD); result.Should().ContainEquivalentOf(cycleE); result.Should().HaveCount(5); } [Test] public void SimpleCyclesComplex() { var myGraph = new DirectedGraph(); myGraph.AddVertices(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); myGraph.AddEdges( (0, 1), (1, 2), (2, 3), (3, 0), (0, 3), (3, 4), (4, 5), (5, 0), (0, 1), (1, 6), (6, 7), (7, 8), (8, 0), (8, 9) ); var result = myGraph.SimpleCycles(); var cycleA = new int[] { 0, 3 }; var cycleB = new int[] { 0, 1, 2, 3, 4, 5 }; var cycleC = new int[] { 0, 1, 2, 3 }; var cycleD = new int[] { 0, 3, 4, 5 }; var cycleE = new int[] { 0, 1, 6, 7, 8 }; result.Should().ContainEquivalentOf(cycleA); result.Should().ContainEquivalentOf(cycleB); result.Should().ContainEquivalentOf(cycleC); result.Should().ContainEquivalentOf(cycleD); result.Should().ContainEquivalentOf(cycleE); result.Should().HaveCount(5); } [Test] public void Cyclic() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 2), (2, 3), (3, 1), (3, 4) ); Assert.That(myGraph.Cyclic(), Is.True); } [Test] public void Acyclic() { var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( (1, 2), (2, 3), (3, 4) ); Assert.That(myGraph.Cyclic(), Is.False); } } }