From 0fb16abcbbe7227fe3d725aa4241a7579db480e3 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Tue, 22 Oct 2019 00:28:29 -0700 Subject: [PATCH] restructuring --- Graph/DirectedGraph.cs | 203 +++++++------ Graph/Exceptions/InvalidVertexException.cs | 12 + Graph/IGraph.cs | 15 + test/DirectedGraphTest.cs | 318 ++++++++++++--------- 4 files changed, 316 insertions(+), 232 deletions(-) create mode 100644 Graph/Exceptions/InvalidVertexException.cs create mode 100644 Graph/IGraph.cs diff --git a/Graph/DirectedGraph.cs b/Graph/DirectedGraph.cs index 39ac3ad..70c2cde 100644 --- a/Graph/DirectedGraph.cs +++ b/Graph/DirectedGraph.cs @@ -10,63 +10,67 @@ namespace MoonTools.Core.Graph finish } - public class DirectedGraph + public class DirectedGraph : IGraph { - private class SimpleCycleComparer : IEqualityComparer> + protected HashSet nodes = new HashSet(); + protected HashSet<(TNode, TNode)> edges = new HashSet<(TNode, TNode)>(); + protected Dictionary<(TNode, TNode), TEdgeData> edgesToEdgeData = new Dictionary<(TNode, TNode), TEdgeData>(); + protected Dictionary> neighbors = new Dictionary>(); + + private class SimpleCycleComparer : IEqualityComparer> { - public bool Equals(IEnumerable x, IEnumerable y) + public bool Equals(IEnumerable x, IEnumerable y) { return x.SequenceEqual(y); } - public int GetHashCode(IEnumerable obj) + public int GetHashCode(IEnumerable obj) { return obj.Aggregate(0, (current, next) => current.GetHashCode() ^ next.GetHashCode()); } } - protected List _vertices = new List(); - protected Dictionary> _neighbors = new Dictionary>(); + public IEnumerable Nodes { get { return nodes; } } + public IEnumerable<(TNode, TNode)> Edges { get { return edges; } } - public IEnumerable Vertices { get { return _vertices; } } - - /* - * GRAPH STRUCTURE METHODS - */ - - public void AddVertex(T vertex) + public bool Exists(TNode node) { - if (!VertexExists(vertex)) + return nodes.Contains(node); + } + + public bool Exists((TNode, TNode) edge) + { + return edges.Contains(edge); + } + + public void AddNode(TNode node) + { + if (!Exists(node)) { - _vertices.Add(vertex); - _neighbors.Add(vertex, new HashSet()); + nodes.Add(node); + neighbors.Add(node, new HashSet()); } } - public void AddVertices(params T[] vertices) + public void AddNodes(params TNode[] nodes) { - foreach (var vertex in vertices) + foreach (var node in nodes) { - AddVertex(vertex); + AddNode(node); } } - public bool VertexExists(T vertex) + public void RemoveNode(TNode node) { - return Vertices.Contains(vertex); - } + var edgesToRemove = new List<(TNode, TNode)>(); - public void RemoveVertex(T vertex) - { - var edgesToRemove = new List>(); - - if (VertexExists(vertex)) + if (Exists(node)) { - foreach (var entry in _neighbors) + foreach (var entry in neighbors) { - if (entry.Value.Contains(vertex)) + if (entry.Value.Contains(node)) { - edgesToRemove.Add(Tuple.Create(entry.Key, vertex)); + edgesToRemove.Add((entry.Key, node)); } } @@ -75,60 +79,63 @@ namespace MoonTools.Core.Graph RemoveEdge(edge.Item1, edge.Item2); } - _vertices.Remove(vertex); - _neighbors.Remove(vertex); + nodes.Remove(node); + neighbors.Remove(node); } } - public void AddEdge(T v, T u) + public void AddEdge(TNode v, TNode u, TEdgeData edgeData) { - if (VertexExists(v) && VertexExists(u)) + if (Exists(v) && Exists(u)) { - _neighbors[v].Add(u); + neighbors[v].Add(u); + edges.Add((v, u)); + this.edgesToEdgeData.Add((v, u), edgeData); } } - public void AddEdges(params Tuple[] edges) + public void AddEdges(params (TNode, TNode, TEdgeData)[] edges) { foreach (var edge in edges) { - AddEdge(edge.Item1, edge.Item2); + AddEdge(edge.Item1, edge.Item2, edge.Item3); } } - public void RemoveEdge(T v, T u) + public void RemoveEdge(TNode v, TNode u) { - _neighbors[v].Remove(u); + neighbors[v].Remove(u); } - public IEnumerable Neighbors(T vertex) + public TEdgeData EdgeData((TNode, TNode) edge) { - if (VertexExists(vertex)) + return edgesToEdgeData[edge]; + } + + public IEnumerable Neighbors(TNode node) + { + if (Exists(node)) { - return _neighbors[vertex]; + return neighbors[node]; } else { - return Enumerable.Empty(); + return Enumerable.Empty(); } } - /* - * GRAPH ANALYSIS METHODS - */ - - public Dictionary> NodeDFS() + public Dictionary> NodeDFS() { - var discovered = new HashSet(); + var discovered = new HashSet(); uint time = 0; - var output = new Dictionary>(); + var output = new Dictionary>(); - foreach (var vertex in Vertices) + foreach (var node in Nodes) { - output.Add(vertex, new Dictionary()); + output.Add(node, new Dictionary()); } - void dfsHelper(T v) + void dfsHelper(TNode v) { discovered.Add(v); time++; @@ -146,11 +153,11 @@ namespace MoonTools.Core.Graph output[v].Add(SearchSymbol.finish, time); } - foreach (var vertex in Vertices) + foreach (var node in Nodes) { - if (!discovered.Contains(vertex)) + if (!discovered.Contains(node)) { - dfsHelper(vertex); + dfsHelper(node); } } @@ -162,10 +169,10 @@ namespace MoonTools.Core.Graph return StronglyConnectedComponents().Any((scc) => scc.Count() > 1); } - public IEnumerable TopologicalSort() + public IEnumerable TopologicalSort() { var dfs = NodeDFS(); - var priority = new SortedList(); + var priority = new SortedList(); foreach (var entry in dfs) { priority.Add(entry.Value[SearchSymbol.finish], entry.Key); @@ -173,22 +180,22 @@ namespace MoonTools.Core.Graph return priority.Values.Reverse(); } - public IEnumerable> StronglyConnectedComponents() + public IEnumerable> StronglyConnectedComponents() { - var preorder = new Dictionary(); - var lowlink = new Dictionary(); - var sccFound = new Dictionary(); - var sccQueue = new Stack(); + var preorder = new Dictionary(); + var lowlink = new Dictionary(); + var sccFound = new Dictionary(); + var sccQueue = new Stack(); - var result = new List>(); + var result = new List>(); uint preorderCounter = 0; - foreach (var source in Vertices) + foreach (var source in Nodes) { if (!sccFound.ContainsKey(source)) { - var queue = new Stack(); + var queue = new Stack(); queue.Push(source); while (queue.Count > 0) @@ -233,7 +240,7 @@ namespace MoonTools.Core.Graph if (lowlink[v] == preorder[v]) { sccFound[v] = true; - var scc = new List + var scc = new List { v }; @@ -257,11 +264,11 @@ namespace MoonTools.Core.Graph return result; } - public IEnumerable> SimpleCycles() + public IEnumerable> SimpleCycles() { - void unblock(T thisnode, HashSet blocked, Dictionary> B) + void unblock(TNode thisnode, HashSet blocked, Dictionary> B) { - var stack = new Stack(); + var stack = new Stack(); stack.Push(thisnode); while (stack.Count > 0) @@ -285,10 +292,10 @@ namespace MoonTools.Core.Graph } } - List> result = new List>(); + List> result = new List>(); var subGraph = Clone(); - var sccs = new Stack>(); + var sccs = new Stack>(); foreach (var scc in StronglyConnectedComponents()) { sccs.Push(scc); @@ -296,18 +303,18 @@ namespace MoonTools.Core.Graph while (sccs.Count > 0) { - var scc = new Stack(sccs.Pop()); + var scc = new Stack(sccs.Pop()); var startNode = scc.Pop(); - var path = new Stack(); + var path = new Stack(); path.Push(startNode); - var blocked = new HashSet + var blocked = new HashSet { startNode }; - var closed = new HashSet(); - var B = new Dictionary>(); - var stack = new Stack>>(); - stack.Push(Tuple.Create(startNode, new Stack(subGraph.Neighbors(startNode)))); + var closed = new HashSet(); + var B = new Dictionary>(); + var stack = new Stack>>(); + stack.Push(Tuple.Create(startNode, new Stack(subGraph.Neighbors(startNode)))); while (stack.Count > 0) { @@ -321,7 +328,7 @@ namespace MoonTools.Core.Graph if (nextNode.Equals(startNode)) { - var resultPath = new List(); + var resultPath = new List(); foreach (var v in path) { resultPath.Add(v); @@ -335,7 +342,7 @@ namespace MoonTools.Core.Graph else if (!blocked.Contains(nextNode)) { path.Push(nextNode); - stack.Push(Tuple.Create(nextNode, new Stack(subGraph.Neighbors(nextNode)))); + stack.Push(Tuple.Create(nextNode, new Stack(subGraph.Neighbors(nextNode)))); closed.Remove(nextNode); blocked.Add(nextNode); continue; @@ -354,7 +361,7 @@ namespace MoonTools.Core.Graph { if (!B.ContainsKey(neighbor)) { - B[neighbor] = new HashSet(); + B[neighbor] = new HashSet(); } B[neighbor].Add(thisnode); } @@ -365,7 +372,7 @@ namespace MoonTools.Core.Graph } } - subGraph.RemoveVertex(startNode); + subGraph.RemoveNode(startNode); var H = subGraph.SubGraph(scc.ToArray()); var HSccs = H.StronglyConnectedComponents(); foreach (var HScc in HSccs) @@ -377,37 +384,37 @@ namespace MoonTools.Core.Graph return result.Distinct(new SimpleCycleComparer()); } - public DirectedGraph Clone() + public DirectedGraph Clone() { - var clone = new DirectedGraph(); - clone.AddVertices(Vertices.ToArray()); + var clone = new DirectedGraph(); + clone.AddNodes(Nodes.ToArray()); - foreach (var v in Vertices) + foreach (var v in Nodes) { foreach (var n in Neighbors(v)) { - clone.AddEdge(v, n); + clone.AddEdge(v, n, EdgeData((v, n))); } } return clone; } - public DirectedGraph SubGraph(params T[] subVertices) + public DirectedGraph SubGraph(params TNode[] subVertices) { - var subGraph = new DirectedGraph(); - subGraph.AddVertices(subVertices.ToArray()); + var subGraph = new DirectedGraph(); + subGraph.AddNodes(subVertices.ToArray()); - foreach (var v in Vertices) + foreach (var n in Nodes) { - if (Vertices.Contains(v)) + if (Nodes.Contains(n)) { - var neighbors = Neighbors(v); + var neighbors = Neighbors(n); foreach (var u in neighbors) { if (subVertices.Contains(u)) { - subGraph.AddEdge(v, u); + subGraph.AddEdge(n, u, EdgeData((n, u))); } } } @@ -415,5 +422,11 @@ namespace MoonTools.Core.Graph return subGraph; } + + public void Clear() + { + nodes.Clear(); + neighbors.Clear(); + } } } diff --git a/Graph/Exceptions/InvalidVertexException.cs b/Graph/Exceptions/InvalidVertexException.cs new file mode 100644 index 0000000..57318ab --- /dev/null +++ b/Graph/Exceptions/InvalidVertexException.cs @@ -0,0 +1,12 @@ +using System; + +namespace MoonTools.Core.Graph +{ + public class InvalidVertexException : Exception + { + public InvalidVertexException( + string format, + params object[] args + ) : base(string.Format(format, args)) { } + } +} diff --git a/Graph/IGraph.cs b/Graph/IGraph.cs new file mode 100644 index 0000000..1fe0be6 --- /dev/null +++ b/Graph/IGraph.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace MoonTools.Core.Graph +{ + public interface IGraph + { + IEnumerable Nodes { get; } + + void AddNode(TNode node); + void AddNodes(params TNode[] nodes); + bool Exists(TNode node); + IEnumerable Neighbors(TNode node); + void Clear(); + } +} \ No newline at end of file diff --git a/test/DirectedGraphTest.cs b/test/DirectedGraphTest.cs index 6793fc6..4481c1e 100644 --- a/test/DirectedGraphTest.cs +++ b/test/DirectedGraphTest.cs @@ -8,34 +8,38 @@ using MoonTools.Core.Graph; namespace Tests { + struct EdgeData { } + public class DirectedGraphTest { - [Test] - public void AddVertex() - { - var myGraph = new DirectedGraph(); - myGraph.AddVertex(4); + EdgeData dummyEdgeData; - Assert.That(myGraph.Vertices, Does.Contain(4)); + [Test] + public void AddNode() + { + var myGraph = new DirectedGraph(); + myGraph.AddNode(4); + + Assert.That(myGraph.Nodes, Does.Contain(4)); } [Test] - public void AddVertices() + public void AddNodes() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(4, 20, 69); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(4, 20, 69); - Assert.IsTrue(myGraph.VertexExists(4)); - Assert.IsTrue(myGraph.VertexExists(20)); - Assert.IsTrue(myGraph.VertexExists(69)); + Assert.IsTrue(myGraph.Exists(4)); + Assert.IsTrue(myGraph.Exists(20)); + Assert.IsTrue(myGraph.Exists(69)); } [Test] public void AddEdge() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(5, 6); - myGraph.AddEdge(5, 6); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(5, 6); + myGraph.AddEdge(5, 6, dummyEdgeData); Assert.That(myGraph.Neighbors(5), Does.Contain(6)); } @@ -43,13 +47,13 @@ namespace Tests [Test] public void AddEdges() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 4), - Tuple.Create(3, 4) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (2, 4, dummyEdgeData), + (3, 4, dummyEdgeData) ); Assert.That(myGraph.Neighbors(1), Does.Contain(2)); @@ -62,13 +66,13 @@ namespace Tests [Test] public void RemoveEdge() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 4), - Tuple.Create(3, 4) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (2, 4, dummyEdgeData), + (3, 4, dummyEdgeData) ); myGraph.RemoveEdge(2, 3); @@ -78,20 +82,20 @@ namespace Tests } [Test] - public void RemoveVertex() + public void RemoveNode() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 4), - Tuple.Create(3, 4) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (2, 4, dummyEdgeData), + (3, 4, dummyEdgeData) ); - myGraph.RemoveVertex(2); + myGraph.RemoveNode(2); - myGraph.Vertices.Should().NotContain(2); + myGraph.Nodes.Should().NotContain(2); myGraph.Neighbors(1).Should().NotContain(2); myGraph.Neighbors(3).Should().Contain(4); } @@ -99,12 +103,12 @@ namespace Tests [Test] public void NodeDFS() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices('a', 'b', 'c', 'd'); + var myGraph = new DirectedGraph(); + myGraph.AddNodes('a', 'b', 'c', 'd'); myGraph.AddEdges( - Tuple.Create('a', 'b'), - Tuple.Create('a', 'c'), - Tuple.Create('b', 'd') + ('a', 'b', dummyEdgeData), + ('a', 'c', dummyEdgeData), + ('b', 'd', dummyEdgeData) ); var result = myGraph.NodeDFS(); @@ -125,13 +129,13 @@ namespace Tests [Test] public void TopologicalSortSimple() { - var simpleGraph = new DirectedGraph(); - simpleGraph.AddVertices('a', 'b', 'c', 'd'); + var simpleGraph = new DirectedGraph(); + simpleGraph.AddNodes('a', 'b', 'c', 'd'); simpleGraph.AddEdges( - Tuple.Create('a', 'b'), - Tuple.Create('a', 'c'), - Tuple.Create('b', 'a'), - Tuple.Create('b', 'd') + ('a', 'b', dummyEdgeData), + ('a', 'c', dummyEdgeData), + ('b', 'a', dummyEdgeData), + ('b', 'd', dummyEdgeData) ); Assert.That(simpleGraph.TopologicalSort(), Is.EqualTo(new char[] { 'a', 'c', 'b', 'd' })); @@ -140,17 +144,17 @@ namespace Tests [Test] public void TopologicalSortComplex() { - var complexGraph = new DirectedGraph(); - complexGraph.AddVertices('a', 'b', 'c', 'd', 'e', 'f', 'g', 't', 'm'); + var complexGraph = new DirectedGraph(); + complexGraph.AddNodes('a', 'b', 'c', 'd', 'e', 'f', 'g', 't', 'm'); complexGraph.AddEdges( - Tuple.Create('a', 'b'), - Tuple.Create('a', 'c'), - Tuple.Create('a', 'd'), - Tuple.Create('b', 'f'), - Tuple.Create('b', 'g'), - Tuple.Create('c', 'g'), - Tuple.Create('e', 't'), - Tuple.Create('t', 'm') + ('a', 'b', dummyEdgeData), + ('a', 'c', dummyEdgeData), + ('a', 'd', dummyEdgeData), + ('b', 'f', dummyEdgeData), + ('b', 'g', dummyEdgeData), + ('c', 'g', dummyEdgeData), + ('e', 't', dummyEdgeData), + ('t', 'm', dummyEdgeData) ); Assert.That( @@ -162,13 +166,13 @@ namespace Tests [Test] public void StronglyConnectedComponentsSimple() { - var simpleGraph = new DirectedGraph(); - simpleGraph.AddVertices(1, 2, 3); + var simpleGraph = new DirectedGraph(); + simpleGraph.AddNodes(1, 2, 3); simpleGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 2), - Tuple.Create(2, 1) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (3, 2, dummyEdgeData), + (2, 1, dummyEdgeData) ); var result = simpleGraph.StronglyConnectedComponents(); @@ -181,15 +185,15 @@ namespace Tests [Test] public void StronglyConnectedComponentsMedium() { - var mediumGraph = new DirectedGraph(); - mediumGraph.AddVertices(1, 2, 3, 4); + var mediumGraph = new DirectedGraph(); + mediumGraph.AddNodes(1, 2, 3, 4); mediumGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(1, 3), - Tuple.Create(1, 4), - Tuple.Create(4, 2), - Tuple.Create(3, 4), - Tuple.Create(2, 3) + (1, 2, dummyEdgeData), + (1, 3, dummyEdgeData), + (1, 4, dummyEdgeData), + (4, 2, dummyEdgeData), + (3, 4, dummyEdgeData), + (2, 3, dummyEdgeData) ); var result = mediumGraph.StronglyConnectedComponents(); @@ -204,21 +208,21 @@ namespace Tests [Test] public void StronglyConnectedComponentsComplex() { - var complexGraph = new DirectedGraph(); - complexGraph.AddVertices(1, 2, 3, 4, 5, 6, 7, 8); + var complexGraph = new DirectedGraph(); + complexGraph.AddNodes(1, 2, 3, 4, 5, 6, 7, 8); complexGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 8), - Tuple.Create(3, 4), - Tuple.Create(3, 7), - Tuple.Create(4, 5), - Tuple.Create(5, 3), - Tuple.Create(5, 6), - Tuple.Create(7, 4), - Tuple.Create(7, 6), - Tuple.Create(8, 1), - Tuple.Create(8, 7) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (2, 8, dummyEdgeData), + (3, 4, dummyEdgeData), + (3, 7, dummyEdgeData), + (4, 5, dummyEdgeData), + (5, 3, dummyEdgeData), + (5, 6, dummyEdgeData), + (7, 4, dummyEdgeData), + (7, 6, dummyEdgeData), + (8, 1, dummyEdgeData), + (8, 7, dummyEdgeData) ); var result = complexGraph.StronglyConnectedComponents(); @@ -235,19 +239,19 @@ namespace Tests [Test] public void Clone() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 1), - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 1), - Tuple.Create(3, 4) + (1, 1, dummyEdgeData), + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (2, 1, dummyEdgeData), + (3, 4, dummyEdgeData) ); var clone = myGraph.Clone(); Assert.That(clone, Is.Not.EqualTo(myGraph)); - clone.Vertices.Should().BeEquivalentTo(1, 2, 3, 4); + clone.Nodes.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); @@ -256,18 +260,18 @@ namespace Tests [Test] public void SubGraph() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 1), - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 1), - Tuple.Create(3, 4) + (1, 1, dummyEdgeData), + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (2, 1, dummyEdgeData), + (3, 4, dummyEdgeData) ); var subGraph = myGraph.SubGraph(1, 2, 3); - subGraph.Vertices.Should().BeEquivalentTo(1, 2, 3); + subGraph.Nodes.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); @@ -276,16 +280,16 @@ namespace Tests [Test] public void SimpleCyclesSimple() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(0, 1, 2); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(0, 1, 2); myGraph.AddEdges( - Tuple.Create(0, 0), - Tuple.Create(0, 1), - Tuple.Create(0, 2), - Tuple.Create(1, 2), - Tuple.Create(2, 0), - Tuple.Create(2, 1), - Tuple.Create(2, 2) + (0, 0, dummyEdgeData), + (0, 1, dummyEdgeData), + (0, 2, dummyEdgeData), + (1, 2, dummyEdgeData), + (2, 0, dummyEdgeData), + (2, 1, dummyEdgeData), + (2, 2, dummyEdgeData) ); var result = myGraph.SimpleCycles(); @@ -307,23 +311,22 @@ namespace Tests [Test] public void SimpleCyclesComplex() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); myGraph.AddEdges( - Tuple.Create(0, 1), - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 0), - Tuple.Create(0, 3), - Tuple.Create(3, 4), - Tuple.Create(4, 5), - Tuple.Create(5, 0), - Tuple.Create(0, 1), - Tuple.Create(1, 6), - Tuple.Create(6, 7), - Tuple.Create(7, 8), - Tuple.Create(8, 0), - Tuple.Create(8, 9) + (0, 1, dummyEdgeData), + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (3, 0, dummyEdgeData), + (0, 3, dummyEdgeData), + (3, 4, dummyEdgeData), + (4, 5, dummyEdgeData), + (5, 0, dummyEdgeData), + (1, 6, dummyEdgeData), + (6, 7, dummyEdgeData), + (7, 8, dummyEdgeData), + (8, 0, dummyEdgeData), + (8, 9, dummyEdgeData) ); var result = myGraph.SimpleCycles(); @@ -344,13 +347,13 @@ namespace Tests [Test] public void Cyclic() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 1), - Tuple.Create(3, 4) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (3, 1, dummyEdgeData), + (3, 4, dummyEdgeData) ); Assert.That(myGraph.Cyclic(), Is.True); @@ -359,15 +362,56 @@ namespace Tests [Test] public void Acyclic() { - var myGraph = new DirectedGraph(); - myGraph.AddVertices(1, 2, 3, 4); + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 4) + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (3, 4, dummyEdgeData) ); Assert.That(myGraph.Cyclic(), Is.False); } + + [Test] + public void Clear() + { + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2, 3, 4); + myGraph.AddEdges( + (1, 2, dummyEdgeData), + (2, 3, dummyEdgeData), + (3, 4, dummyEdgeData) + ); + + myGraph.Clear(); + + myGraph.Nodes.Should().BeEmpty(); + } + + [Test] + public void EdgeExists() + { + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2); + myGraph.AddEdge(1, 2, dummyEdgeData); + + myGraph.Exists((1, 2)).Should().BeTrue(); + } + + struct TestEdgeData + { + public int testNum; + } + + [Test] + public void EdgeData() + { + var myGraph = new DirectedGraph(); + myGraph.AddNodes(1, 2); + myGraph.AddEdge(1, 2, new TestEdgeData { testNum = 4 }); + + myGraph.EdgeData((1, 2)).testNum.Should().Be(4); + } } }