From 0b66236d78e197a3bf465240dc4adee71a25fde7 Mon Sep 17 00:00:00 2001 From: evan Date: Tue, 22 Oct 2019 20:20:10 -0700 Subject: [PATCH] GC optimization on DirectedGraph methods --- Graph/DirectedGraph.cs | 85 ++++++++++++++++++--------------------- test/DirectedGraphTest.cs | 15 ++----- 2 files changed, 44 insertions(+), 56 deletions(-) diff --git a/Graph/DirectedGraph.cs b/Graph/DirectedGraph.cs index 11145b0..988183d 100644 --- a/Graph/DirectedGraph.cs +++ b/Graph/DirectedGraph.cs @@ -71,30 +71,29 @@ namespace MoonTools.Core.Graph } } + readonly List<(TNode, TNode)> edgesToRemove = new List<(TNode, TNode)>(); + public void RemoveNode(TNode node) { CheckNodes(node); - var edgesToRemove = new List<(TNode, TNode)>(); + edgesToRemove.Clear(); - if (Exists(node)) + foreach (var entry in neighbors) { - foreach (var entry in neighbors) + if (entry.Value.Contains(node)) { - if (entry.Value.Contains(node)) - { - edgesToRemove.Add((entry.Key, node)); - } + edgesToRemove.Add((entry.Key, node)); } - - foreach (var edge in edgesToRemove) - { - RemoveEdge(edge.Item1, edge.Item2); - } - - nodes.Remove(node); - neighbors.Remove(node); } + + foreach (var edge in edgesToRemove) + { + RemoveEdge(edge.Item1, edge.Item2); + } + + nodes.Remove(node); + neighbors.Remove(node); } public void AddEdge(TNode v, TNode u, TEdgeData edgeData) @@ -103,7 +102,7 @@ namespace MoonTools.Core.Graph neighbors[v].Add(u); edges.Add((v, u)); - this.edgesToEdgeData.Add((v, u), edgeData); + edgesToEdgeData.Add((v, u), edgeData); } public void AddEdges(params (TNode, TNode, TEdgeData)[] edges) @@ -124,6 +123,7 @@ namespace MoonTools.Core.Graph { CheckEdge(v, u); neighbors[v].Remove(u); + edgesToEdgeData.Remove((v, u)); } public TEdgeData EdgeData(TNode v, TNode u) @@ -139,22 +139,18 @@ namespace MoonTools.Core.Graph return neighbors[node]; } - public Dictionary> NodeDFS() + readonly HashSet discovered = new HashSet(); + readonly Dictionary dfsOutput = new Dictionary(); + + public IEnumerable<(TNode, uint)> NodeDFS() { - var discovered = new HashSet(); + discovered.Clear(); + dfsOutput.Clear(); uint time = 0; - var output = new Dictionary>(); - foreach (var node in Nodes) - { - output.Add(node, new Dictionary()); - } - - void dfsHelper(TNode v) + void dfsHelper(TNode v) // refactor this to remove closure { discovered.Add(v); - time++; - output[v].Add(SearchSymbol.Start, time); foreach (var neighbor in Neighbors(v)) { @@ -165,7 +161,7 @@ namespace MoonTools.Core.Graph } time++; - output[v].Add(SearchSymbol.Finish, time); + dfsOutput[v] = time; } foreach (var node in Nodes) @@ -176,7 +172,7 @@ namespace MoonTools.Core.Graph } } - return output; + return dfsOutput.Select(entry => (entry.Key, entry.Value)); } public bool Cyclic() @@ -186,23 +182,22 @@ namespace MoonTools.Core.Graph public IEnumerable TopologicalSort() { - var dfs = NodeDFS(); - var priority = new SortedList(); - foreach (var entry in dfs) - { - priority.Add(entry.Value[SearchSymbol.Finish], entry.Key); - } - return priority.Values.Reverse(); + return NodeDFS().OrderByDescending(entry => entry.Item2).Select(entry => entry.Item1); } + readonly Dictionary preorder = new Dictionary(); + readonly Dictionary lowlink = new Dictionary(); + readonly Dictionary sccFound = new Dictionary(); + readonly Stack sccQueue = new Stack(); + readonly List> sccResult = new List>(); + public IEnumerable> StronglyConnectedComponents() { - var preorder = new Dictionary(); - var lowlink = new Dictionary(); - var sccFound = new Dictionary(); - var sccQueue = new Stack(); - - var result = new List>(); + preorder.Clear(); + lowlink.Clear(); + sccFound.Clear(); + sccQueue.Clear(); + sccResult.Clear(); uint preorderCounter = 0; @@ -265,7 +260,7 @@ namespace MoonTools.Core.Graph sccFound[k] = true; scc.Add(k); } - result.Add(scc); + sccResult.Add(scc); } else { @@ -276,12 +271,12 @@ namespace MoonTools.Core.Graph } } - return result; + return sccResult; } public IEnumerable> SimpleCycles() { - void unblock(TNode thisnode, HashSet blocked, Dictionary> B) + void unblock(TNode thisnode, HashSet blocked, Dictionary> B) //refactor to remove closure { var stack = new Stack(); stack.Push(thisnode); diff --git a/test/DirectedGraphTest.cs b/test/DirectedGraphTest.cs index 54c2fc5..b343227 100644 --- a/test/DirectedGraphTest.cs +++ b/test/DirectedGraphTest.cs @@ -111,17 +111,10 @@ namespace Tests 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)); + result.Should().Contain(('d', 1)); + result.Should().Contain(('b', 2)); + result.Should().Contain(('c', 3)); + result.Should().Contain(('a', 4)); } [Test]