From 01556338eb08a0e84d1a49ea3e3713282d60b7ff Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Wed, 23 Oct 2019 18:47:48 -0700 Subject: [PATCH] more restructuring --- Graph/DirectedGraph.cs | 8 +-- Graph/DirectedMultiGraph.cs | 21 +++++++ Graph/DirectedWeightedGraph.cs | 9 +-- Graph/DirectedWeightedMultiGraph.cs | 89 ++--------------------------- Graph/MultiGraph.cs | 60 +++++++++++++++++++ Graph/SimpleGraph.cs | 11 ++++ 6 files changed, 100 insertions(+), 98 deletions(-) create mode 100644 Graph/DirectedMultiGraph.cs create mode 100644 Graph/MultiGraph.cs diff --git a/Graph/DirectedGraph.cs b/Graph/DirectedGraph.cs index 72e2d0c..2ad3687 100644 --- a/Graph/DirectedGraph.cs +++ b/Graph/DirectedGraph.cs @@ -22,13 +22,7 @@ namespace MoonTools.Core.Graph public virtual void AddEdge(TNode v, TNode u, TEdgeData edgeData) { - CheckNodes(v, u); - - if (v.Equals(u)) { throw new ArgumentException("Self-edges are not allowed in a simple graph. Use a multigraph instead"); } - - neighbors[v].Add(u); - edges.Add((v, u)); - edgeToEdgeData.Add((v, u), edgeData); + BaseAddEdge(v, u, edgeData); } public virtual void AddEdges(params (TNode, TNode, TEdgeData)[] edges) diff --git a/Graph/DirectedMultiGraph.cs b/Graph/DirectedMultiGraph.cs new file mode 100644 index 0000000..ed22993 --- /dev/null +++ b/Graph/DirectedMultiGraph.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace MoonTools.Core.Graph +{ + public class DirectedMultiGraph : MultiGraph where TNode : System.IEquatable + { + public void AddEdge(TNode v, TNode u, TEdgeData edgeData) + { + BaseAddEdge(v, u, edgeData); + } + + public void AddEdges(params (TNode, TNode, TEdgeData)[] edges) + { + foreach (var edge in edges) + { + AddEdge(edge.Item1, edge.Item2, edge.Item3); + } + } + } +} \ No newline at end of file diff --git a/Graph/DirectedWeightedGraph.cs b/Graph/DirectedWeightedGraph.cs index b88ba4c..53f877b 100644 --- a/Graph/DirectedWeightedGraph.cs +++ b/Graph/DirectedWeightedGraph.cs @@ -12,14 +12,7 @@ namespace MoonTools.Core.Graph public void AddEdge(TNode v, TNode u, int weight, TEdgeData edgeData) { - CheckNodes(v, u); - - if (v.Equals(u)) { throw new ArgumentException("Self-edges are not allowed in a simple graph. Use a multigraph instead"); } - - neighbors[v].Add(u); - edges.Add((v, u)); - edgeToEdgeData.Add((v, u), edgeData); - + BaseAddEdge(v, u, edgeData); weights.Add((v, u), weight); } diff --git a/Graph/DirectedWeightedMultiGraph.cs b/Graph/DirectedWeightedMultiGraph.cs index 051ed10..1fbe524 100644 --- a/Graph/DirectedWeightedMultiGraph.cs +++ b/Graph/DirectedWeightedMultiGraph.cs @@ -6,47 +6,15 @@ using MoreLinq; namespace MoonTools.Core.Graph { - public class DirectedWeightedMultiGraph where TNode : IEquatable + public class DirectedWeightedMultiGraph : MultiGraph where TNode : IEquatable { - protected HashSet nodes = new HashSet(); - protected Dictionary> neighbors = new Dictionary>(); - protected Dictionary<(TNode, TNode), HashSet> edges = new Dictionary<(TNode, TNode), HashSet>(); - protected Dictionary IDToEdge = new Dictionary(); protected Dictionary weights = new Dictionary(); - protected Dictionary edgeToEdgeData = new Dictionary(); - public IEnumerable Nodes => nodes; - - public void AddNode(TNode node) + public Guid AddEdge(TNode v, TNode u, int weight, TEdgeData data) { - if (Exists(node)) { return; } - - nodes.Add(node); - neighbors[node] = new HashSet(); - } - - public void AddNodes(params TNode[] nodes) - { - foreach (var node in nodes) - { - AddNode(node); - } - } - - public void AddEdge(TNode v, TNode u, int weight, TEdgeData data) - { - CheckNodes(v, u); - - var id = Guid.NewGuid(); - neighbors[v].Add(u); + var id = BaseAddEdge(v, u, data); weights.Add(id, weight); - if (!edges.ContainsKey((v, u))) - { - edges[(v, u)] = new HashSet(); - } - edges[(v, u)].Add(id); - edgeToEdgeData.Add(id, data); - IDToEdge.Add(id, (v, u)); + return id; } public void AddEdges(params (TNode, TNode, int, TEdgeData)[] edges) @@ -57,45 +25,10 @@ namespace MoonTools.Core.Graph } } - public void Clear() + public override void Clear() { - nodes.Clear(); - neighbors.Clear(); + base.Clear(); weights.Clear(); - edges.Clear(); - IDToEdge.Clear(); - edgeToEdgeData.Clear(); - } - - 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 IEnumerable EdgeIDs(TNode v, TNode u) - { - CheckNodes(v, u); - return edges.ContainsKey((v, u)) ? edges[(v, u)] : Enumerable.Empty(); - } - - public bool Exists(TNode node) => nodes.Contains(node); - - public bool Exists(TNode v, TNode u) - { - CheckNodes(v, u); - return edges.ContainsKey((v, u)); - } - - public IEnumerable Neighbors(TNode node) - { - CheckNodes(node); - return neighbors.ContainsKey(node) ? neighbors[node] : Enumerable.Empty(); } public IEnumerable Weights(TNode v, TNode u) @@ -104,16 +37,6 @@ namespace MoonTools.Core.Graph return edges[(v, u)].Select(id => weights[id]); } - public TEdgeData EdgeData(Guid id) - { - if (!edgeToEdgeData.ContainsKey(id)) - { - throw new ArgumentException($"Edge {id} does not exist in the graph."); - } - - return edgeToEdgeData[id]; - } - private IEnumerable ReconstructPath(PooledDictionary cameFrom, TNode currentNode) { while (cameFrom.ContainsKey(currentNode)) diff --git a/Graph/MultiGraph.cs b/Graph/MultiGraph.cs new file mode 100644 index 0000000..0449886 --- /dev/null +++ b/Graph/MultiGraph.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MoonTools.Core.Graph +{ + abstract public class MultiGraph : Graph where TNode : System.IEquatable + { + protected Dictionary<(TNode, TNode), HashSet> edges = new Dictionary<(TNode, TNode), HashSet>(); + protected Dictionary IDToEdge = new Dictionary(); + protected Dictionary edgeToEdgeData = new Dictionary(); + + protected Guid BaseAddEdge(TNode v, TNode u, TEdgeData edgeData) + { + CheckNodes(v, u); + + var id = Guid.NewGuid(); + neighbors[v].Add(u); + if (!edges.ContainsKey((v, u))) + { + edges[(v, u)] = new HashSet(); + } + edges[(v, u)].Add(id); + edgeToEdgeData.Add(id, edgeData); + IDToEdge.Add(id, (v, u)); + + return id; + } + + public override void Clear() + { + base.Clear(); + edges.Clear(); + IDToEdge.Clear(); + edgeToEdgeData.Clear(); + } + + public IEnumerable EdgeIDs(TNode v, TNode u) + { + CheckNodes(v, u); + return edges.ContainsKey((v, u)) ? edges[(v, u)] : Enumerable.Empty(); + } + + public bool Exists(TNode v, TNode u) + { + CheckNodes(v, u); + return edges.ContainsKey((v, u)); + } + + public TEdgeData EdgeData(Guid id) + { + if (!edgeToEdgeData.ContainsKey(id)) + { + throw new ArgumentException($"Edge {id} does not exist in the graph."); + } + + return edgeToEdgeData[id]; + } + } +} \ No newline at end of file diff --git a/Graph/SimpleGraph.cs b/Graph/SimpleGraph.cs index 2e9c6c7..bbb41fb 100644 --- a/Graph/SimpleGraph.cs +++ b/Graph/SimpleGraph.cs @@ -12,6 +12,17 @@ namespace MoonTools.Core.Graph public int Size => edges.Count; + protected void BaseAddEdge(TNode v, TNode u, TEdgeData edgeData) + { + CheckNodes(v, u); + + if (v.Equals(u)) { throw new ArgumentException("Self-edges are not allowed in a simple graph. Use a multigraph instead"); } + + neighbors[v].Add(u); + edges.Add((v, u)); + edgeToEdgeData.Add((v, u), edgeData); + } + public bool Exists(TNode v, TNode u) { CheckNodes(v, u);