diff --git a/encompass-cs/Graph/DirectedGraph.cs b/encompass-cs/Graph/DirectedGraph.cs index b60db0d..c8620f2 100644 --- a/encompass-cs/Graph/DirectedGraph.cs +++ b/encompass-cs/Graph/DirectedGraph.cs @@ -89,7 +89,7 @@ namespace Encompass } } - public void AddEdges(params Tuple[] edges) + public void AddEdges(params ValueTuple[] edges) { foreach (var edge in edges) { @@ -174,6 +174,34 @@ namespace Encompass return priority.Values.Reverse(); } + public IEnumerable> LongestPaths(T source) + { + var topoSort = TopologicalSort(); + + var distances = new Dictionary(); + foreach (var node in Vertices) + { + distances[node] = int.MaxValue; + } + distances[source] = 0; + + foreach (var node in topoSort) + { + if (distances[node] != int.MaxValue) + { + foreach (var neighbor in Neighbors(node)) + { + if (distances[neighbor] > distances[node] + 1) + { + distances[neighbor] = distances[node] + 1; + } + } + } + } + + return distances.Select((pair) => (pair.Key, pair.Value)); + } + public IEnumerable> StronglyConnectedComponents() { var preorder = new Dictionary(); diff --git a/test/DirectedGraphTest.cs b/test/DirectedGraphTest.cs index 2a3731e..b4eca48 100644 --- a/test/DirectedGraphTest.cs +++ b/test/DirectedGraphTest.cs @@ -47,10 +47,10 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 4), - Tuple.Create(3, 4) + (1, 2), + (2, 3), + (2, 4), + (3, 4) ); Assert.That(myGraph.Neighbors(1), Does.Contain(2)); @@ -66,10 +66,10 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 4), - Tuple.Create(3, 4) + (1, 2), + (2, 3), + (2, 4), + (3, 4) ); myGraph.RemoveEdge(2, 3); @@ -84,10 +84,10 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(2, 4), - Tuple.Create(3, 4) + (1, 2), + (2, 3), + (2, 4), + (3, 4) ); myGraph.RemoveVertex(2); @@ -103,9 +103,9 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices('a', 'b', 'c', 'd'); myGraph.AddEdges( - Tuple.Create('a', 'b'), - Tuple.Create('a', 'c'), - Tuple.Create('b', 'd') + ('a', 'b'), + ('a', 'c'), + ('b', 'd') ); var result = myGraph.NodeDFS(); @@ -129,10 +129,10 @@ namespace Tests var simpleGraph = new DirectedGraph(); simpleGraph.AddVertices('a', 'b', 'c', 'd'); simpleGraph.AddEdges( - Tuple.Create('a', 'b'), - Tuple.Create('a', 'c'), - Tuple.Create('b', 'a'), - Tuple.Create('b', 'd') + ('a', 'b'), + ('a', 'c'), + ('b', 'a'), + ('b', 'd') ); Assert.That(simpleGraph.TopologicalSort(), Is.EqualTo(new char[] { 'a', 'c', 'b', 'd' })); @@ -144,14 +144,14 @@ namespace Tests var complexGraph = new DirectedGraph(); complexGraph.AddVertices('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'), + ('a', 'c'), + ('a', 'd'), + ('b', 'f'), + ('b', 'g'), + ('c', 'g'), + ('e', 't'), + ('t', 'm') ); Assert.That( @@ -160,16 +160,41 @@ namespace Tests ); } + [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', 1)); + result.Should().Contain(('x', 2)); + result.Should().Contain(('y', 2)); + result.Should().Contain(('z', 3)); + } + [Test] public void StronglyConnectedComponentsSimple() { var simpleGraph = new DirectedGraph(); simpleGraph.AddVertices(1, 2, 3); simpleGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 2), - Tuple.Create(2, 1) + (1, 2), + (2, 3), + (3, 2), + (2, 1) ); var result = simpleGraph.StronglyConnectedComponents(); @@ -185,12 +210,12 @@ namespace Tests var mediumGraph = new DirectedGraph(); mediumGraph.AddVertices(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), + (1, 3), + (1, 4), + (4, 2), + (3, 4), + (2, 3) ); var result = mediumGraph.StronglyConnectedComponents(); @@ -208,18 +233,18 @@ namespace Tests var complexGraph = new DirectedGraph(); complexGraph.AddVertices(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), + (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(); @@ -239,11 +264,11 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(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), + (1, 2), + (2, 3), + (2, 1), + (3, 4) ); var clone = myGraph.Clone(); @@ -260,11 +285,11 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(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), + (1, 2), + (2, 3), + (2, 1), + (3, 4) ); var subGraph = myGraph.SubGraph(1, 2, 3); @@ -280,13 +305,13 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(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), + (0, 1), + (0, 2), + (1, 2), + (2, 0), + (2, 1), + (2, 2) ); var result = myGraph.SimpleCycles(); @@ -311,20 +336,20 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(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), + (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(); @@ -348,10 +373,10 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 1), - Tuple.Create(3, 4) + (1, 2), + (2, 3), + (3, 1), + (3, 4) ); Assert.That(myGraph.Cyclic(), Is.True); @@ -363,9 +388,9 @@ namespace Tests var myGraph = new DirectedGraph(); myGraph.AddVertices(1, 2, 3, 4); myGraph.AddEdges( - Tuple.Create(1, 2), - Tuple.Create(2, 3), - Tuple.Create(3, 4) + (1, 2), + (2, 3), + (3, 4) ); Assert.That(myGraph.Cyclic(), Is.False);