optimizations

master
Evan Hemsley 2019-10-23 16:46:04 -07:00
parent bae6acd6f3
commit a08a39c353
3 changed files with 68 additions and 84 deletions

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Collections.Pooled;
namespace MoonTools.Core.Graph namespace MoonTools.Core.Graph
{ {
@ -80,13 +81,11 @@ namespace MoonTools.Core.Graph
return neighbors[node].Count; return neighbors[node].Count;
} }
readonly List<(TNode, TNode)> edgesToRemove = new List<(TNode, TNode)>();
public void RemoveNode(TNode node) public void RemoveNode(TNode node)
{ {
CheckNodes(node); CheckNodes(node);
edgesToRemove.Clear(); var edgesToRemove = new PooledList<(TNode, TNode)>(ClearMode.Always);
foreach (var entry in neighbors) foreach (var entry in neighbors)
{ {
@ -101,6 +100,8 @@ namespace MoonTools.Core.Graph
RemoveEdge(edge.Item1, edge.Item2); RemoveEdge(edge.Item1, edge.Item2);
} }
edgesToRemove.Dispose();
nodes.Remove(node); nodes.Remove(node);
neighbors.Remove(node); neighbors.Remove(node);
} }
@ -149,13 +150,10 @@ namespace MoonTools.Core.Graph
return neighbors[node]; return neighbors[node];
} }
readonly Stack<TNode> dfsStack = new Stack<TNode>();
readonly HashSet<TNode> dfsDiscovered = new HashSet<TNode>();
public IEnumerable<TNode> PreorderNodeDFS() public IEnumerable<TNode> PreorderNodeDFS()
{ {
dfsStack.Clear(); var dfsStack = new PooledStack<TNode>(ClearMode.Always);
dfsDiscovered.Clear(); var dfsDiscovered = new PooledSet<TNode>(ClearMode.Always);
foreach (var node in Nodes) foreach (var node in Nodes)
{ {
@ -177,75 +175,49 @@ namespace MoonTools.Core.Graph
} }
} }
} }
dfsStack.Dispose();
dfsDiscovered.Dispose();
} }
// public IEnumerable<TNode> PostorderNodeDFS() private IEnumerable<TNode> PostorderNodeDFSHelper(PooledSet<TNode> discovered, TNode v)
// { {
// dfsStack.Clear(); discovered.Add(v);
// dfsDiscovered.Clear();
// foreach (var node in Nodes) foreach (var neighbor in Neighbors(v))
// { {
// if (!dfsDiscovered.Contains(node)) if (!discovered.Contains(neighbor))
// { {
// dfsStack.Push(node); foreach (var node in PostorderNodeDFSHelper(discovered, neighbor))
// while (dfsStack.Count > 0) {
// { yield return node;
// var current = dfsStack.Pop(); }
// if (!dfsDiscovered.Contains(current)) }
// { }
// dfsDiscovered.Add(current);
// foreach (var neighbor in Neighbors(current))
// {
// dfsStack.Push(neighbor);
// }
// yield return current;
// }
// }
// }
// }
// }
List<TNode> postorderOutput = new List<TNode>(); yield return v;
}
public IEnumerable<TNode> PostorderNodeDFS() public IEnumerable<TNode> PostorderNodeDFS()
{ {
dfsDiscovered.Clear(); var dfsDiscovered = new PooledSet<TNode>(ClearMode.Always);
postorderOutput.Clear();
void dfsHelper(TNode v) // refactor this to remove closure
{
dfsDiscovered.Add(v);
foreach (var neighbor in Neighbors(v))
{
if (!dfsDiscovered.Contains(neighbor))
{
dfsHelper(neighbor);
}
}
postorderOutput.Add(v);
}
foreach (var node in Nodes) foreach (var node in Nodes)
{ {
if (!dfsDiscovered.Contains(node)) if (!dfsDiscovered.Contains(node))
{ {
dfsHelper(node); foreach (var thing in PostorderNodeDFSHelper(dfsDiscovered, node))
{
yield return thing;
}
} }
} }
return postorderOutput;
} }
readonly Queue<TNode> bfsQueue = new Queue<TNode>();
readonly HashSet<TNode> bfsDiscovered = new HashSet<TNode>();
public IEnumerable<TNode> NodeBFS() public IEnumerable<TNode> NodeBFS()
{ {
bfsQueue.Clear(); var bfsQueue = new PooledQueue<TNode>(ClearMode.Always);
bfsDiscovered.Clear(); var bfsDiscovered = new PooledSet<TNode>(ClearMode.Always);
foreach (var node in Nodes) foreach (var node in Nodes)
{ {
@ -267,49 +239,54 @@ namespace MoonTools.Core.Graph
} }
} }
} }
bfsQueue.Dispose();
bfsDiscovered.Dispose();
} }
// hoo boy this is bad for the GC List<PooledSet<TNode>> lexicographicSets = new List<PooledSet<TNode>>();
HashSet<PooledSet<TNode>> replacedSets = new HashSet<PooledSet<TNode>>();
public IEnumerable<TNode> LexicographicBFS() public IEnumerable<TNode> LexicographicBFS()
{ {
var sets = new List<List<TNode>>(); lexicographicSets.Add(Nodes.ToPooledSet());
sets.Add(Nodes.ToList());
while (sets.Count > 0) while (lexicographicSets.Count > 0)
{ {
var firstSet = sets[0]; var firstSet = lexicographicSets[0];
var node = firstSet[0]; var node = firstSet.First();
firstSet.RemoveAt(0); firstSet.Remove(node);
if (firstSet.Count == 0) { sets.RemoveAt(0); } if (firstSet.Count == 0) { lexicographicSets.RemoveAt(0); }
yield return node; yield return node;
var replaced = new List<List<TNode>>();
foreach (var neighbor in Neighbors(node)) foreach (var neighbor in Neighbors(node))
{ {
if (sets.Any(set => set.Contains(neighbor))) if (lexicographicSets.Any(set => set.Contains(neighbor)))
{ {
var s = sets.Find(set => set.Contains(neighbor)); var s = lexicographicSets.Find(set => set.Contains(neighbor));
var sIndex = sets.IndexOf(s); var sIndex = lexicographicSets.IndexOf(s);
List<TNode> t; PooledSet<TNode> t;
if (replaced.Contains(s)) if (replacedSets.Contains(s) && sIndex > 0)
{ {
t = sets[sIndex - 1]; t = lexicographicSets[sIndex - 1];
} }
else else
{ {
t = new List<TNode>(); t = new PooledSet<TNode>(ClearMode.Always);
sets.Insert(sIndex, t); lexicographicSets.Insert(sIndex, t);
replaced.Add(s); replacedSets.Add(s);
} }
s.Remove(neighbor); s.Remove(neighbor);
t.Add(neighbor); t.Add(neighbor);
if (s.Count == 0) { sets.Remove(s); } if (s.Count == 0) { lexicographicSets.Remove(s); replacedSets.Remove(s); }
} }
} }
} }
lexicographicSets.Clear();
replacedSets.Clear();
} }
public bool Cyclic() public bool Cyclic()

View File

@ -4,5 +4,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="morelinq" Version="3.2.0"/> <PackageReference Include="morelinq" Version="3.2.0"/>
<PackageReference Include="Collections.Pooled" Version="1.0.82"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,5 +1,6 @@
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Collections.Pooled;
namespace MoonTools.Core.Graph namespace MoonTools.Core.Graph
{ {
@ -21,7 +22,7 @@ namespace MoonTools.Core.Graph
.All(pair => .All(pair =>
{ {
var (node, index) = pair; var (node, index) = pair;
var successors = lexicographicOrder.Skip(index - 1).Take(nodes.Count - index - 1); var successors = lexicographicOrder.Skip(index).Take(nodes.Count - index);
return Clique(Neighbors(node).Intersect(successors).Union(Enumerable.Repeat(node, 1))); return Clique(Neighbors(node).Intersect(successors).Union(Enumerable.Repeat(node, 1)));
}); });
} }
@ -31,9 +32,9 @@ namespace MoonTools.Core.Graph
{ {
get get
{ {
var colors = new Dictionary<TNode, Color>(); var colors = new PooledDictionary<TNode, Color>();
var d = new Dictionary<TNode, int>(); var d = new PooledDictionary<TNode, int>();
var partition = new Dictionary<TNode, int>(); var partition = new PooledDictionary<TNode, int>();
foreach (var node in Nodes) foreach (var node in Nodes)
{ {
@ -47,7 +48,7 @@ namespace MoonTools.Core.Graph
partition[start] = 1; partition[start] = 1;
d[start] = 0; d[start] = 0;
var stack = new Stack<TNode>(); var stack = new PooledStack<TNode>();
stack.Push(start); stack.Push(start);
while (stack.Count > 0) while (stack.Count > 0)
@ -68,6 +69,11 @@ namespace MoonTools.Core.Graph
colors[node] = Color.Black; colors[node] = Color.Black;
} }
stack.Dispose();
colors.Dispose();
d.Dispose();
partition.Dispose();
return true; return true;
} }
} }