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

View File

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

View File

@ -1,5 +1,6 @@
using System.Linq;
using System.Collections.Generic;
using Collections.Pooled;
namespace MoonTools.Core.Graph
{
@ -21,7 +22,7 @@ namespace MoonTools.Core.Graph
.All(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)));
});
}
@ -31,9 +32,9 @@ namespace MoonTools.Core.Graph
{
get
{
var colors = new Dictionary<TNode, Color>();
var d = new Dictionary<TNode, int>();
var partition = new Dictionary<TNode, int>();
var colors = new PooledDictionary<TNode, Color>();
var d = new PooledDictionary<TNode, int>();
var partition = new PooledDictionary<TNode, int>();
foreach (var node in Nodes)
{
@ -47,7 +48,7 @@ namespace MoonTools.Core.Graph
partition[start] = 1;
d[start] = 0;
var stack = new Stack<TNode>();
var stack = new PooledStack<TNode>();
stack.Push(start);
while (stack.Count > 0)
@ -68,6 +69,11 @@ namespace MoonTools.Core.Graph
colors[node] = Color.Black;
}
stack.Dispose();
colors.Dispose();
d.Dispose();
partition.Dispose();
return true;
}
}