restructure inheritance

master
Evan Hemsley 2019-10-23 18:05:28 -07:00
parent 92bab9db75
commit fcd9c23ecd
6 changed files with 103 additions and 177 deletions

View File

@ -5,19 +5,8 @@ using Collections.Pooled;
namespace MoonTools.Core.Graph namespace MoonTools.Core.Graph
{ {
public enum SearchSymbol public class DirectedGraph<TNode, TEdgeData> : SimpleGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
{ {
Start,
Finish
}
public class DirectedGraph<TNode, TEdgeData> : IGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
{
protected HashSet<TNode> nodes = new HashSet<TNode>();
protected HashSet<(TNode, TNode)> edges = new HashSet<(TNode, TNode)>();
protected Dictionary<(TNode, TNode), TEdgeData> edgesToEdgeData = new Dictionary<(TNode, TNode), TEdgeData>();
protected Dictionary<TNode, HashSet<TNode>> neighbors = new Dictionary<TNode, HashSet<TNode>>();
private class SimpleCycleComparer : IEqualityComparer<IEnumerable<TNode>> private class SimpleCycleComparer : IEqualityComparer<IEnumerable<TNode>>
{ {
public bool Equals(IEnumerable<TNode> x, IEnumerable<TNode> y) public bool Equals(IEnumerable<TNode> x, IEnumerable<TNode> y)
@ -31,56 +20,6 @@ namespace MoonTools.Core.Graph
} }
} }
public IEnumerable<TNode> Nodes => nodes;
public IEnumerable<(TNode, TNode)> Edges => edges;
public int Order => nodes.Count;
public int Size => edges.Count;
public void AddNode(TNode node)
{
if (!Exists(node))
{
nodes.Add(node);
neighbors.Add(node, new HashSet<TNode>());
}
}
public void AddNodes(params TNode[] nodes)
{
foreach (var node in nodes)
{
AddNode(node);
}
}
public bool Exists(TNode node)
{
return nodes.Contains(node);
}
public bool Exists(TNode v, TNode u)
{
return edges.Contains((v, u));
}
private void CheckNodes(params TNode[] givenNodes)
{
foreach (var node in givenNodes)
{
if (!Exists(node))
{
throw new ArgumentException($"Vertex {node} does not exist in the graph");
}
}
}
public int Degree(TNode node)
{
CheckNodes(node);
return neighbors[node].Count;
}
public void RemoveNode(TNode node) public void RemoveNode(TNode node)
{ {
CheckNodes(node); CheckNodes(node);
@ -114,7 +53,7 @@ namespace MoonTools.Core.Graph
neighbors[v].Add(u); neighbors[v].Add(u);
edges.Add((v, u)); edges.Add((v, u));
edgesToEdgeData.Add((v, u), edgeData); edgeToEdgeData.Add((v, u), edgeData);
} }
public virtual void AddEdges(params (TNode, TNode, TEdgeData)[] edges) public virtual void AddEdges(params (TNode, TNode, TEdgeData)[] edges)
@ -125,31 +64,12 @@ namespace MoonTools.Core.Graph
} }
} }
private void CheckEdge(TNode v, TNode u)
{
CheckNodes(v, u);
if (!Exists(v, u)) { throw new ArgumentException($"Edge between vertex {v} and vertex {u} does not exist in the graph"); }
}
public virtual void RemoveEdge(TNode v, TNode u) public virtual void RemoveEdge(TNode v, TNode u)
{ {
CheckEdge(v, u); CheckEdge(v, u);
neighbors[v].Remove(u); neighbors[v].Remove(u);
edges.Remove((v, u)); edges.Remove((v, u));
edgesToEdgeData.Remove((v, u)); edgeToEdgeData.Remove((v, u));
}
public TEdgeData EdgeData(TNode v, TNode u)
{
CheckEdge(v, u);
return edgesToEdgeData[(v, u)];
}
public IEnumerable<TNode> Neighbors(TNode node)
{
CheckNodes(node);
return neighbors[node];
} }
public IEnumerable<TNode> PreorderNodeDFS() public IEnumerable<TNode> PreorderNodeDFS()
@ -549,12 +469,12 @@ namespace MoonTools.Core.Graph
return subGraph; return subGraph;
} }
public void Clear() public virtual void Clear()
{ {
nodes.Clear(); nodes.Clear();
neighbors.Clear(); neighbors.Clear();
edges.Clear(); edges.Clear();
edgesToEdgeData.Clear(); edgeToEdgeData.Clear();
} }
} }
} }

View File

@ -6,51 +6,14 @@ using MoreLinq;
namespace MoonTools.Core.Graph namespace MoonTools.Core.Graph
{ {
public class DirectedWeightedGraph<TNode, TEdgeData> : IGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode> public class DirectedWeightedGraph<TNode, TEdgeData> : DirectedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
{ {
protected HashSet<TNode> nodes = new HashSet<TNode>();
protected Dictionary<TNode, HashSet<TNode>> neighbors = new Dictionary<TNode, HashSet<TNode>>();
protected Dictionary<(TNode, TNode), TEdgeData> edgeToEdgeData = new Dictionary<(TNode, TNode), TEdgeData>();
protected Dictionary<(TNode, TNode), int> weights = new Dictionary<(TNode, TNode), int>(); protected Dictionary<(TNode, TNode), int> weights = new Dictionary<(TNode, TNode), int>();
public IEnumerable<TNode> Nodes => nodes;
public void AddNode(TNode node)
{
if (Exists(node)) { return; }
nodes.Add(node);
neighbors[node] = new HashSet<TNode>();
}
public void AddNodes(params TNode[] nodes)
{
foreach (var node in nodes)
{
AddNode(node);
}
}
private void CheckNodes(params TNode[] givenNodes)
{
foreach (var node in givenNodes)
{
if (!Exists(node))
{
throw new ArgumentException($"Vertex {node} does not exist in the graph");
}
}
}
public void AddEdge(TNode v, TNode u, int weight, TEdgeData data) public void AddEdge(TNode v, TNode u, int weight, TEdgeData data)
{ {
CheckNodes(v, u); base.AddEdge(v, u, data);
if (Exists(v, u)) { throw new ArgumentException($"Edge with vertex {v} and {u} already exists in the graph"); }
neighbors[v].Add(u);
weights.Add((v, u), weight); weights.Add((v, u), weight);
edgeToEdgeData.Add((v, u), data);
} }
public void AddEdges(params (TNode, TNode, int, TEdgeData)[] edges) public void AddEdges(params (TNode, TNode, int, TEdgeData)[] edges)
@ -61,46 +24,18 @@ namespace MoonTools.Core.Graph
} }
} }
public void Clear() public override void Clear()
{ {
nodes.Clear(); base.Clear();
neighbors.Clear();
edgeToEdgeData.Clear();
weights.Clear(); weights.Clear();
} }
public bool Exists(TNode node) => nodes.Contains(node);
public bool Exists(TNode v, TNode u)
{
CheckNodes(v, u);
return neighbors[v].Contains(u);
}
public IEnumerable<TNode> Neighbors(TNode node)
{
CheckNodes(node);
return neighbors[node];
}
private void CheckEdge(TNode v, TNode u)
{
CheckNodes(v, u);
if (!Exists(v, u)) { throw new ArgumentException($"Edge between vertex {v} and vertex {u} does not exist in the graph"); }
}
public int Weight(TNode v, TNode u) public int Weight(TNode v, TNode u)
{ {
CheckEdge(v, u); CheckEdge(v, u);
return weights[(v, u)]; return weights[(v, u)];
} }
public TEdgeData EdgeData(TNode v, TNode u)
{
CheckEdge(v, u);
return edgeToEdgeData[(v, u)];
}
private IEnumerable<(TNode, TNode)> ReconstructPath(PooledDictionary<TNode, TNode> cameFrom, TNode currentNode) private IEnumerable<(TNode, TNode)> ReconstructPath(PooledDictionary<TNode, TNode> cameFrom, TNode currentNode)
{ {
while (cameFrom.ContainsKey(currentNode)) while (cameFrom.ContainsKey(currentNode))

View File

@ -6,7 +6,7 @@ using MoreLinq;
namespace MoonTools.Core.Graph namespace MoonTools.Core.Graph
{ {
public class DirectedWeightedMultiGraph<TNode, TEdgeData> : IGraph<TNode, TEdgeData> where TNode : IEquatable<TNode> public class DirectedWeightedMultiGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
{ {
protected HashSet<TNode> nodes = new HashSet<TNode>(); protected HashSet<TNode> nodes = new HashSet<TNode>();
protected Dictionary<TNode, HashSet<TNode>> neighbors = new Dictionary<TNode, HashSet<TNode>>(); protected Dictionary<TNode, HashSet<TNode>> neighbors = new Dictionary<TNode, HashSet<TNode>>();
@ -15,13 +15,6 @@ namespace MoonTools.Core.Graph
protected Dictionary<Guid, int> weights = new Dictionary<Guid, int>(); protected Dictionary<Guid, int> weights = new Dictionary<Guid, int>();
protected Dictionary<Guid, TEdgeData> edgeToEdgeData = new Dictionary<Guid, TEdgeData>(); protected Dictionary<Guid, TEdgeData> edgeToEdgeData = new Dictionary<Guid, TEdgeData>();
// store search sets to prevent GC
protected HashSet<TNode> openSet = new HashSet<TNode>();
protected HashSet<TNode> closedSet = new HashSet<TNode>();
protected Dictionary<TNode, int> gScore = new Dictionary<TNode, int>();
protected Dictionary<TNode, int> fScore = new Dictionary<TNode, int>();
protected Dictionary<TNode, Guid> cameFrom = new Dictionary<TNode, Guid>();
public IEnumerable<TNode> Nodes => nodes; public IEnumerable<TNode> Nodes => nodes;
public void AddNode(TNode node) public void AddNode(TNode node)

60
Graph/Graph.cs Normal file
View File

@ -0,0 +1,60 @@
using System.Collections.Generic;
namespace MoonTools.Core.Graph
{
abstract public class Graph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
{
protected HashSet<TNode> nodes = new HashSet<TNode>();
protected Dictionary<TNode, HashSet<TNode>> neighbors = new Dictionary<TNode, HashSet<TNode>>();
public IEnumerable<TNode> Nodes => nodes;
public int Order => nodes.Count;
public void AddNode(TNode node)
{
if (!Exists(node))
{
nodes.Add(node);
neighbors.Add(node, new HashSet<TNode>());
}
}
public void AddNodes(params TNode[] nodes)
{
foreach (var node in nodes)
{
AddNode(node);
}
}
public int Degree(TNode node)
{
CheckNodes(node);
return neighbors[node].Count;
}
public bool Exists(TNode node)
{
return nodes.Contains(node);
}
public IEnumerable<TNode> Neighbors(TNode node)
{
CheckNodes(node);
return neighbors[node];
}
protected void CheckNodes(params TNode[] givenNodes)
{
foreach (var node in givenNodes)
{
if (!Exists(node))
{
throw new System.ArgumentException($"Vertex {node} does not exist in the graph");
}
}
}
}
}

View File

@ -1,15 +0,0 @@
using System.Collections.Generic;
namespace MoonTools.Core.Graph
{
public interface IGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
{
IEnumerable<TNode> Nodes { get; }
void AddNode(TNode node);
void AddNodes(params TNode[] nodes);
bool Exists(TNode node);
IEnumerable<TNode> Neighbors(TNode node);
void Clear();
}
}

33
Graph/SimpleGraph.cs Normal file
View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
namespace MoonTools.Core.Graph
{
abstract public class SimpleGraph<TNode, TEdgeData> : Graph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
{
protected HashSet<(TNode, TNode)> edges = new HashSet<(TNode, TNode)>();
protected Dictionary<(TNode, TNode), TEdgeData> edgeToEdgeData = new Dictionary<(TNode, TNode), TEdgeData>();
public IEnumerable<(TNode, TNode)> Edges => edges;
public int Size => edges.Count;
public bool Exists(TNode v, TNode u)
{
CheckNodes(v, u);
return edges.Contains((v, u));
}
public TEdgeData EdgeData(TNode v, TNode u)
{
CheckEdge(v, u);
return edgeToEdgeData[(v, u)];
}
protected void CheckEdge(TNode v, TNode u)
{
CheckNodes(v, u);
if (!Exists(v, u)) { throw new ArgumentException($"Edge between vertex {v} and vertex {u} does not exist in the graph"); }
}
}
}