GC optimization on DirectedGraph methods
parent
4e5a5eb06b
commit
0b66236d78
|
@ -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);
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Reference in New Issue