GC optimization on DirectedGraph methods

master
evan 2019-10-22 20:20:10 -07:00
parent 4e5a5eb06b
commit 0b66236d78
2 changed files with 44 additions and 56 deletions

View File

@ -71,30 +71,29 @@ namespace MoonTools.Core.Graph
} }
} }
readonly List<(TNode, TNode)> edgesToRemove = new List<(TNode, TNode)>();
public void RemoveNode(TNode node) public void RemoveNode(TNode node)
{ {
CheckNodes(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) public void AddEdge(TNode v, TNode u, TEdgeData edgeData)
@ -103,7 +102,7 @@ namespace MoonTools.Core.Graph
neighbors[v].Add(u); neighbors[v].Add(u);
edges.Add((v, u)); edges.Add((v, u));
this.edgesToEdgeData.Add((v, u), edgeData); edgesToEdgeData.Add((v, u), edgeData);
} }
public void AddEdges(params (TNode, TNode, TEdgeData)[] edges) public void AddEdges(params (TNode, TNode, TEdgeData)[] edges)
@ -124,6 +123,7 @@ namespace MoonTools.Core.Graph
{ {
CheckEdge(v, u); CheckEdge(v, u);
neighbors[v].Remove(u); neighbors[v].Remove(u);
edgesToEdgeData.Remove((v, u));
} }
public TEdgeData EdgeData(TNode v, TNode u) public TEdgeData EdgeData(TNode v, TNode u)
@ -139,22 +139,18 @@ namespace MoonTools.Core.Graph
return neighbors[node]; return neighbors[node];
} }
public Dictionary<TNode, Dictionary<SearchSymbol, uint>> NodeDFS() readonly HashSet<TNode> discovered = new HashSet<TNode>();
readonly Dictionary<TNode, uint> dfsOutput = new Dictionary<TNode, uint>();
public IEnumerable<(TNode, uint)> NodeDFS()
{ {
var discovered = new HashSet<TNode>(); discovered.Clear();
dfsOutput.Clear();
uint time = 0; uint time = 0;
var output = new Dictionary<TNode, Dictionary<SearchSymbol, uint>>();
foreach (var node in Nodes) void dfsHelper(TNode v) // refactor this to remove closure
{
output.Add(node, new Dictionary<SearchSymbol, uint>());
}
void dfsHelper(TNode v)
{ {
discovered.Add(v); discovered.Add(v);
time++;
output[v].Add(SearchSymbol.Start, time);
foreach (var neighbor in Neighbors(v)) foreach (var neighbor in Neighbors(v))
{ {
@ -165,7 +161,7 @@ namespace MoonTools.Core.Graph
} }
time++; time++;
output[v].Add(SearchSymbol.Finish, time); dfsOutput[v] = time;
} }
foreach (var node in Nodes) 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() public bool Cyclic()
@ -186,23 +182,22 @@ namespace MoonTools.Core.Graph
public IEnumerable<TNode> TopologicalSort() public IEnumerable<TNode> TopologicalSort()
{ {
var dfs = NodeDFS(); return NodeDFS().OrderByDescending(entry => entry.Item2).Select(entry => entry.Item1);
var priority = new SortedList<uint, TNode>();
foreach (var entry in dfs)
{
priority.Add(entry.Value[SearchSymbol.Finish], entry.Key);
}
return priority.Values.Reverse();
} }
readonly Dictionary<TNode, uint> preorder = new Dictionary<TNode, uint>();
readonly Dictionary<TNode, uint> lowlink = new Dictionary<TNode, uint>();
readonly Dictionary<TNode, bool> sccFound = new Dictionary<TNode, bool>();
readonly Stack<TNode> sccQueue = new Stack<TNode>();
readonly List<List<TNode>> sccResult = new List<List<TNode>>();
public IEnumerable<IEnumerable<TNode>> StronglyConnectedComponents() public IEnumerable<IEnumerable<TNode>> StronglyConnectedComponents()
{ {
var preorder = new Dictionary<TNode, uint>(); preorder.Clear();
var lowlink = new Dictionary<TNode, uint>(); lowlink.Clear();
var sccFound = new Dictionary<TNode, bool>(); sccFound.Clear();
var sccQueue = new Stack<TNode>(); sccQueue.Clear();
sccResult.Clear();
var result = new List<List<TNode>>();
uint preorderCounter = 0; uint preorderCounter = 0;
@ -265,7 +260,7 @@ namespace MoonTools.Core.Graph
sccFound[k] = true; sccFound[k] = true;
scc.Add(k); scc.Add(k);
} }
result.Add(scc); sccResult.Add(scc);
} }
else else
{ {
@ -276,12 +271,12 @@ namespace MoonTools.Core.Graph
} }
} }
return result; return sccResult;
} }
public IEnumerable<IEnumerable<TNode>> SimpleCycles() public IEnumerable<IEnumerable<TNode>> SimpleCycles()
{ {
void unblock(TNode thisnode, HashSet<TNode> blocked, Dictionary<TNode, HashSet<TNode>> B) void unblock(TNode thisnode, HashSet<TNode> blocked, Dictionary<TNode, HashSet<TNode>> B) //refactor to remove closure
{ {
var stack = new Stack<TNode>(); var stack = new Stack<TNode>();
stack.Push(thisnode); stack.Push(thisnode);

View File

@ -111,17 +111,10 @@ namespace Tests
var result = myGraph.NodeDFS(); var result = myGraph.NodeDFS();
Assert.That(result['a'][SearchSymbol.Start], Is.EqualTo(1)); result.Should().Contain(('d', 1));
Assert.That(result['a'][SearchSymbol.Finish], Is.EqualTo(8)); result.Should().Contain(('b', 2));
result.Should().Contain(('c', 3));
Assert.That(result['b'][SearchSymbol.Start], Is.EqualTo(2)); result.Should().Contain(('a', 4));
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] [Test]