encompass-cs/test/DirectedGraphTest.cs

400 lines
12 KiB
C#

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<int>();
myGraph.AddVertex(4);
Assert.That(myGraph.Vertices, Does.Contain(4));
}
[Test]
public void AddVertices()
{
var myGraph = new DirectedGraph<int>();
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<int>();
myGraph.AddVertices(5, 6);
myGraph.AddEdge(5, 6);
Assert.That(myGraph.Neighbors(5), Does.Contain(6));
}
[Test]
public void AddEdges()
{
var myGraph = new DirectedGraph<int>();
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<int>();
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<int>();
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<char>();
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<char>();
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<char>();
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<char>();
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', 1));
result.Should().Contain(('x', 2));
result.Should().Contain(('y', 2));
result.Should().Contain(('z', 3));
}
[Test]
public void StronglyConnectedComponentsSimple()
{
var simpleGraph = new DirectedGraph<int>();
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<int>();
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<int>();
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<int>();
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<int>();
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<int>();
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<int>();
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<int>();
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<int>();
myGraph.AddVertices(1, 2, 3, 4);
myGraph.AddEdges(
(1, 2),
(2, 3),
(3, 4)
);
Assert.That(myGraph.Cyclic(), Is.False);
}
}
}