optimizations
parent
bae6acd6f3
commit
a08a39c353
|
@ -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()
|
||||||
|
|
|
@ -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>
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue