structure for opting out of edge data
parent
0ccdf2768a
commit
50f7cda0fe
|
@ -5,7 +5,7 @@ using Collections.Pooled;
|
||||||
|
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
public class DirectedGraph<TNode, TEdgeData> : SimpleGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
|
public class DirectedGraph<TNode, TEdgeData> : SimpleGraph<TNode, TEdgeData>, IUnweightedGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
|
||||||
{
|
{
|
||||||
private class SimpleCycleComparer : IEqualityComparer<IEnumerable<TNode>>
|
private class SimpleCycleComparer : IEqualityComparer<IEnumerable<TNode>>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
public class DirectedMultiGraph<TNode, TEdgeData> : MultiGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
public class DirectedMultiGraph<TNode, TEdgeData> : MultiGraph<TNode, TEdgeData>, IUnweightedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
||||||
{
|
{
|
||||||
public void AddEdge(TNode v, TNode u, TEdgeData edgeData)
|
public void AddEdge(TNode v, TNode u, TEdgeData edgeData)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ using MoreLinq;
|
||||||
|
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
public class DirectedWeightedGraph<TNode, TEdgeData> : SimpleGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
public class DirectedWeightedGraph<TNode, TEdgeData> : SimpleGraph<TNode, TEdgeData>, IWeightedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
||||||
{
|
{
|
||||||
protected Dictionary<(TNode, TNode), int> weights = new Dictionary<(TNode, TNode), int>();
|
protected Dictionary<(TNode, TNode), int> weights = new Dictionary<(TNode, TNode), int>();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ using MoreLinq;
|
||||||
|
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
public class DirectedWeightedMultiGraph<TNode, TEdgeData> : MultiGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
|
public class DirectedWeightedMultiGraph<TNode, TEdgeData> : MultiGraph<TNode, TEdgeData>, IWeightedMultiGraph<TNode, TEdgeData> where TNode : IEquatable<TNode>
|
||||||
{
|
{
|
||||||
protected Dictionary<Guid, int> weights = new Dictionary<Guid, int>();
|
protected Dictionary<Guid, int> weights = new Dictionary<Guid, int>();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MoonTools.Core.Graph.Extensions
|
||||||
|
{
|
||||||
|
public static class UnweightedExtensions
|
||||||
|
{
|
||||||
|
public static void AddEdge<TGraph, TNode>(this TGraph g, TNode v, TNode u) where TGraph : Graph<TNode, Unit>, IUnweightedGraph<TNode, Unit> where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
g.AddEdge(v, u, default(Unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddEdges<TGraph, TNode>(this TGraph g, params (TNode, TNode)[] edges) where TGraph : Graph<TNode, Unit>, IUnweightedGraph<TNode, Unit> where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
foreach (var (v, u) in edges)
|
||||||
|
{
|
||||||
|
g.AddEdge(v, u, default(Unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MoonTools.Core.Graph.Extensions
|
||||||
|
{
|
||||||
|
public static class WeightedExtensions
|
||||||
|
{
|
||||||
|
public static void AddEdge<TGraph, TNode>(this TGraph g, TNode v, TNode u, int weight) where TGraph : Graph<TNode, Unit>, IWeightedGraph<TNode, Unit> where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
g.AddEdge(v, u, weight, default(Unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddEdges<TGraph, TNode>(this TGraph g, params (TNode, TNode, int)[] edges) where TGraph : Graph<TNode, Unit>, IWeightedGraph<TNode, Unit> where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
foreach (var (v, u, weight) in edges)
|
||||||
|
{
|
||||||
|
g.AddEdge(v, u, weight, default(Unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MoonTools.Core.Graph.Extensions
|
||||||
|
{
|
||||||
|
public static class WeightedMultiExtensions
|
||||||
|
{
|
||||||
|
public static void AddEdge<TGraph, TNode>(this TGraph g, TNode v, TNode u, int weight) where TGraph : Graph<TNode, Unit>, IWeightedMultiGraph<TNode, Unit> where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
g.AddEdge(v, u, weight, default(Unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddEdges<TGraph, TNode>(this TGraph g, params (TNode, TNode, int)[] edges) where TGraph : Graph<TNode, Unit>, IWeightedMultiGraph<TNode, Unit> where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
foreach (var (v, u, weight) in edges)
|
||||||
|
{
|
||||||
|
g.AddEdge(v, u, weight, default(Unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
namespace MoonTools.Core.Graph.Extensions
|
||||||
|
{
|
||||||
|
public static class GraphBuilder
|
||||||
|
{
|
||||||
|
public static DirectedGraph<TNode, Unit> DirectedGraph<TNode>() where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
return new DirectedGraph<TNode, Unit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectedMultiGraph<TNode, Unit> DirectedMultiGraph<TNode>() where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
return new DirectedMultiGraph<TNode, Unit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectedWeightedGraph<TNode, Unit> DirectedWeightedGraph<TNode>() where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
return new DirectedWeightedGraph<TNode, Unit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectedWeightedMultiGraph<TNode, Unit> DirectedWeightedMultiGraph<TNode>() where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
return new DirectedWeightedMultiGraph<TNode, Unit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UndirectedGraph<TNode, Unit> UndirectedGraph<TNode>() where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
return new UndirectedGraph<TNode, Unit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UndirectedWeightedGraph<TNode, Unit> UndirectedWeightedGraph<TNode>() where TNode : System.IEquatable<TNode>
|
||||||
|
{
|
||||||
|
return new UndirectedWeightedGraph<TNode, Unit>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace MoonTools.Core.Graph
|
||||||
|
{
|
||||||
|
public interface IUnweightedGraph<TNode, TEdgeData>
|
||||||
|
{
|
||||||
|
void AddEdge(TNode v, TNode u, TEdgeData edgeData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace MoonTools.Core.Graph
|
||||||
|
{
|
||||||
|
public interface IWeightedGraph<TNode, TEdgeData>
|
||||||
|
{
|
||||||
|
void AddEdge(TNode v, TNode u, int weight, TEdgeData edgeData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace MoonTools.Core.Graph
|
||||||
|
{
|
||||||
|
public interface IWeightedMultiGraph<TNode, TEdgeData>
|
||||||
|
{
|
||||||
|
System.Guid AddEdge(TNode v, TNode u, int weight, TEdgeData edgeData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ using Collections.Pooled;
|
||||||
|
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
public class UndirectedGraph<TNode, TEdgeData> : DirectedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
public class UndirectedGraph<TNode, TEdgeData> : DirectedGraph<TNode, TEdgeData>, IUnweightedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
||||||
{
|
{
|
||||||
enum Color { White, Gray, Black }
|
enum Color { White, Gray, Black }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
public class UndirectedWeightedGraph<TNode, TEdgeData> : DirectedWeightedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
public class UndirectedWeightedGraph<TNode, TEdgeData> : DirectedWeightedGraph<TNode, TEdgeData>, IWeightedGraph<TNode, TEdgeData> where TNode : System.IEquatable<TNode>
|
||||||
{
|
{
|
||||||
public override void AddEdge(TNode v, TNode u, int weight, TEdgeData edgeData)
|
public override void AddEdge(TNode v, TNode u, int weight, TEdgeData edgeData)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
namespace MoonTools.Core.Graph
|
||||||
|
{
|
||||||
|
public struct Unit { }
|
||||||
|
}
|
|
@ -18,6 +18,8 @@ A GC-friendly graph theory library for C# intended for use with games.
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
|
|
||||||
|
* change Neighbors tests to use Equal instead of Contains
|
||||||
|
* change Edge id from a Guid to an integer index on the edge
|
||||||
* Prim Minimum Spanning Tree
|
* Prim Minimum Spanning Tree
|
||||||
* Kruskal Minimum Spanning Tree
|
* Kruskal Minimum Spanning Tree
|
||||||
* Undirected Weighted Multigraph
|
* Undirected Weighted Multigraph
|
|
@ -0,0 +1,126 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
using MoonTools.Core.Graph.Extensions;
|
||||||
|
|
||||||
|
namespace Tests
|
||||||
|
{
|
||||||
|
public class GraphBuilderTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void DirectedGraph()
|
||||||
|
{
|
||||||
|
var directedGraph = GraphBuilder.DirectedGraph<int>();
|
||||||
|
directedGraph.AddNodes(1, 2, 3);
|
||||||
|
directedGraph.AddEdge(1, 2);
|
||||||
|
directedGraph.AddEdges(
|
||||||
|
(2, 1),
|
||||||
|
(1, 3)
|
||||||
|
);
|
||||||
|
|
||||||
|
directedGraph.Neighbors(1).Should().Equal(2, 3);
|
||||||
|
directedGraph.Neighbors(2).Should().Equal(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DirectedMultiGraph()
|
||||||
|
{
|
||||||
|
var directedMultiGraph = GraphBuilder.DirectedMultiGraph<int>();
|
||||||
|
directedMultiGraph.AddNodes(1, 2, 3, 4);
|
||||||
|
directedMultiGraph.AddEdge(1, 2);
|
||||||
|
directedMultiGraph.AddEdges(
|
||||||
|
(2, 3),
|
||||||
|
(3, 4),
|
||||||
|
(1, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
directedMultiGraph.Neighbors(1).Should().Equal(2);
|
||||||
|
directedMultiGraph.Neighbors(2).Should().Equal(3);
|
||||||
|
directedMultiGraph.Neighbors(3).Should().Equal(4);
|
||||||
|
directedMultiGraph.EdgeIDs(1, 2).Should().HaveCount(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DirectedWeightedGraph()
|
||||||
|
{
|
||||||
|
var directedWeightedGraph = GraphBuilder.DirectedWeightedGraph<int>();
|
||||||
|
directedWeightedGraph.AddNodes(1, 2, 3, 4);
|
||||||
|
directedWeightedGraph.AddEdge(1, 2, 10);
|
||||||
|
directedWeightedGraph.AddEdges(
|
||||||
|
(2, 3, 5),
|
||||||
|
(3, 4, 1),
|
||||||
|
(4, 2, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
directedWeightedGraph.Neighbors(1).Should().Equal(2);
|
||||||
|
directedWeightedGraph.Neighbors(2).Should().Equal(3);
|
||||||
|
directedWeightedGraph.Neighbors(3).Should().Equal(4);
|
||||||
|
directedWeightedGraph.Neighbors(4).Should().Equal(2);
|
||||||
|
directedWeightedGraph.Weight(1, 2).Should().Be(10);
|
||||||
|
directedWeightedGraph.Weight(2, 3).Should().Be(5);
|
||||||
|
directedWeightedGraph.Weight(3, 4).Should().Be(1);
|
||||||
|
directedWeightedGraph.Weight(4, 2).Should().Be(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DirectedWeightedMultiGraph()
|
||||||
|
{
|
||||||
|
var directedWeightedMultiGraph = GraphBuilder.DirectedWeightedMultiGraph<int>();
|
||||||
|
directedWeightedMultiGraph.AddNodes(1, 2, 3, 4);
|
||||||
|
directedWeightedMultiGraph.AddEdge(1, 2, 10);
|
||||||
|
directedWeightedMultiGraph.AddEdges(
|
||||||
|
(1, 2, 4),
|
||||||
|
(2, 3, 5),
|
||||||
|
(3, 4, 1),
|
||||||
|
(4, 2, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
directedWeightedMultiGraph.Neighbors(1).Should().Equal(2);
|
||||||
|
directedWeightedMultiGraph.Neighbors(2).Should().Equal(3);
|
||||||
|
directedWeightedMultiGraph.Neighbors(3).Should().Equal(4);
|
||||||
|
directedWeightedMultiGraph.Neighbors(4).Should().Equal(2);
|
||||||
|
directedWeightedMultiGraph.Weights(1, 2).Should().Equal(10, 4);
|
||||||
|
directedWeightedMultiGraph.Weights(2, 3).Should().Equal(5);
|
||||||
|
directedWeightedMultiGraph.Weights(3, 4).Should().Equal(1);
|
||||||
|
directedWeightedMultiGraph.Weights(4, 2).Should().Equal(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UndirectedGraph()
|
||||||
|
{
|
||||||
|
var undirectedGraph = GraphBuilder.UndirectedGraph<int>();
|
||||||
|
undirectedGraph.AddNodes(1, 2, 3, 4);
|
||||||
|
undirectedGraph.AddEdge(1, 2);
|
||||||
|
undirectedGraph.AddEdges(
|
||||||
|
(2, 3),
|
||||||
|
(1, 4)
|
||||||
|
);
|
||||||
|
|
||||||
|
undirectedGraph.Neighbors(1).Should().Equal(2, 4);
|
||||||
|
undirectedGraph.Neighbors(2).Should().Equal(1, 3);
|
||||||
|
undirectedGraph.Neighbors(3).Should().Equal(2);
|
||||||
|
undirectedGraph.Neighbors(4).Should().Equal(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UndirectedWeightedGraph()
|
||||||
|
{
|
||||||
|
var undirectedWeightedGraph = GraphBuilder.UndirectedWeightedGraph<int>();
|
||||||
|
undirectedWeightedGraph.AddNodes(1, 2, 3, 4);
|
||||||
|
undirectedWeightedGraph.AddEdge(1, 2, 10);
|
||||||
|
undirectedWeightedGraph.AddEdges(
|
||||||
|
(2, 3, 4),
|
||||||
|
(1, 4, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
undirectedWeightedGraph.Neighbors(1).Should().Equal(2, 4);
|
||||||
|
undirectedWeightedGraph.Neighbors(2).Should().Equal(1, 3);
|
||||||
|
undirectedWeightedGraph.Neighbors(3).Should().Equal(2);
|
||||||
|
undirectedWeightedGraph.Neighbors(4).Should().Equal(1);
|
||||||
|
undirectedWeightedGraph.Weight(1, 2).Should().Be(10);
|
||||||
|
undirectedWeightedGraph.Weight(2, 3).Should().Be(4);
|
||||||
|
undirectedWeightedGraph.Weight(3, 2).Should().Be(4);
|
||||||
|
undirectedWeightedGraph.Weight(4, 1).Should().Be(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue