Skip to content

Commit f2c1a66

Browse files
committed
i-20 start implementing simple graph
1 parent 5d72b2e commit f2c1a66

File tree

21 files changed

+444
-63
lines changed

21 files changed

+444
-63
lines changed

src/Dijkstra.NET.Benchmark/BenchmarkIt.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public int DijkstraExtensionBenchmark()
4040
[Benchmark]
4141
public double PageRankExtensionBenchmark()
4242
{
43-
var result = Graph.CalculatePageRank();
43+
var result = Graph.PageRank();
4444

4545
return result[BenchmarkBase.First];
4646
}

src/Dijkstra.NET.Tests/PageRank/PageRankExtensionsTests.cs

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,34 @@ public void CalculatePageRank_Should_Calculate_Correct_PageRank()
2626
g.Connect(d, c, 0, 0);
2727

2828

29-
var result = g.CalculatePageRank();
30-
29+
var result = g.PageRank();
30+
31+
Assert.True(Math.Abs(result[c] - 0.35625) < 0.0001);
32+
}
33+
34+
[Fact]
35+
public void SimpleGraph_CalculatePageRank_Should_Calculate_Correct_PageRank()
36+
{
37+
var g = new Graph.Simple.Graph();
38+
39+
uint a = g.AddNode();
40+
uint b = g.AddNode();
41+
uint c = g.AddNode();
42+
uint d = g.AddNode();
43+
44+
g.Connect(a, b);
45+
g.Connect(a, c);
46+
g.Connect(b, d);
47+
g.Connect(c, a);
48+
g.Connect(c, b);
49+
g.Connect(c, d);
50+
g.Connect(d, c);
51+
52+
var result = g.PageRank();
53+
3154
Assert.True(Math.Abs(result[c] - 0.35625) < 0.0001);
3255
}
33-
56+
3457
[Fact]
3558
public void CalculatePageRank_Should_Calculate_Correct_PageRank_Wiki()
3659
{
@@ -49,8 +72,33 @@ public void CalculatePageRank_Should_Calculate_Correct_PageRank_Wiki()
4972
g.Connect(d, c, 0, 0);
5073

5174

52-
var result = g.CalculatePageRank();
53-
75+
var result = g.PageRank();
76+
77+
Assert.True(Math.Abs(result[a] - 0.35) < 0.01);
78+
Assert.True(Math.Abs(result[b] - 0.29) < 0.01);
79+
Assert.True(Math.Abs(result[c] - 0.15) < 0.01);
80+
Assert.True(Math.Abs(result[d] - 0.18) < 0.01);
81+
}
82+
83+
[Fact]
84+
public void SimpleGraph_CalculatePageRank_Should_Calculate_Correct_PageRank_Wiki()
85+
{
86+
var g = new Graph.Simple.Graph();
87+
88+
uint a = g.AddNode();
89+
uint b = g.AddNode();
90+
uint c = g.AddNode();
91+
uint d = g.AddNode();
92+
93+
g.Connect(a, b);
94+
g.Connect(a, d);
95+
g.Connect(b, a);
96+
g.Connect(c, b);
97+
g.Connect(c, a);
98+
g.Connect(d, c);
99+
100+
var result = g.PageRank();
101+
54102
Assert.True(Math.Abs(result[a] - 0.35) < 0.01);
55103
Assert.True(Math.Abs(result[b] - 0.29) < 0.01);
56104
Assert.True(Math.Abs(result[c] - 0.15) < 0.01);

src/Dijkstra.NET.Tests/ShortestPath/DijkstraExtensionsTests.cs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,38 @@ public void DijkstraGraphShould_Find_Path_In_Override_Node()
6363
Assert.True(result.IsFounded);
6464
}
6565

66+
[Fact]
67+
public void DijkstraSimpleGraphShould_Find_Path_In_Override_Node()
68+
{
69+
var graph = new Graph.Simple.Graph();
70+
71+
graph.AddNode();
72+
graph.AddNode();
73+
graph.AddNode();
74+
graph.AddNode();
75+
graph.AddNode();
76+
graph.AddNode();
77+
78+
graph.Connect(1, 2, 2);
79+
graph.Connect(1, 3, 6);
80+
graph.Connect(2, 3, 2);
81+
graph.Connect(3, 4, 1);
82+
graph.Connect(4, 5, 1);
83+
graph.Connect(1, 6, 5);
84+
85+
var result = graph.Dijkstra(1, 5);
86+
uint[] path = result.GetPath().ToArray();
87+
88+
Assert.Equal<uint>(1, path[0]);
89+
Assert.Equal<uint>(2, path[1]);
90+
Assert.Equal<uint>(3, path[2]);
91+
Assert.Equal<uint>(4, path[3]);
92+
Assert.Equal<uint>(5, path[4]);
93+
94+
Assert.Equal(6, result.Distance);
95+
Assert.True(result.IsFounded);
96+
}
97+
6698
[Fact]
6799
public void DijkstraGraphShould_Find_Path_With_One_Vertex_In_Graph()
68100
{
@@ -140,6 +172,39 @@ public void DijkstraGraphShould_Find_Path_In_Multi_Edges_Graph()
140172
Assert.True(result.IsFounded);
141173
}
142174

175+
[Fact]
176+
public void DijkstraGraphShould_Find_Path_In_Multi_Edges_SimpleGraph()
177+
{
178+
var graph = new Graph.Simple.Graph();
179+
180+
graph.AddNode();
181+
graph.AddNode();
182+
graph.AddNode();
183+
graph.AddNode();
184+
graph.AddNode();
185+
graph.AddNode();
186+
187+
graph.Connect(1, 2, 2);
188+
graph.Connect(1, 3, 3);
189+
graph.Connect(2, 4, 4);
190+
graph.Connect(3, 4, 3);
191+
graph.Connect(3, 4, 2);
192+
graph.Connect(3, 4, 4);
193+
graph.Connect(3, 5, 1);
194+
graph.Connect(4, 6, 6);
195+
196+
var result = graph.Dijkstra(1, 6);
197+
uint[] path = result.GetPath().ToArray();
198+
199+
Assert.Equal<uint>(1, path[0]);
200+
Assert.Equal<uint>(3, path[1]);
201+
Assert.Equal<uint>(4, path[2]);
202+
Assert.Equal<uint>(6, path[3]);
203+
204+
Assert.Equal(11, result.Distance);
205+
Assert.True(result.IsFounded);
206+
}
207+
143208
[Fact]
144209
public void DijkstraGraphNot_Should_Find_Path_In_Graph()
145210
{
@@ -163,6 +228,29 @@ public void DijkstraGraphNot_Should_Find_Path_In_Graph()
163228
Assert.False(result.IsFounded);
164229
}
165230

231+
[Fact]
232+
public void DijkstraGraphNot_Should_Find_Path_In_SimpleGraph()
233+
{
234+
var graph = new Graph.Simple.Graph();
235+
236+
graph.AddNode();
237+
graph.AddNode();
238+
graph.AddNode();
239+
graph.AddNode();
240+
graph.AddNode();
241+
graph.AddNode();
242+
243+
graph.Connect(1, 2, 2);
244+
graph.Connect(1, 3, 3);
245+
graph.Connect(2, 4, 4);
246+
graph.Connect(3, 4, 2);
247+
graph.Connect(3, 5, 1);
248+
249+
var result = graph.Dijkstra(1, 6);
250+
251+
Assert.False(result.IsFounded);
252+
}
253+
166254
[Fact]
167255
public void Dijkstra_Should_Concern_Depth_In_Graph()
168256
{
@@ -188,5 +276,31 @@ public void Dijkstra_Should_Concern_Depth_In_Graph()
188276
Assert.Equal((uint)1, path[0]);
189277
Assert.Equal((uint)4, path[1]);
190278
}
279+
280+
[Fact]
281+
public void Dijkstra_Should_Concern_Depth_In_SimpleGraph()
282+
{
283+
var graph = new Graph.Simple.Graph();
284+
285+
graph.AddNode();
286+
graph.AddNode();
287+
graph.AddNode();
288+
graph.AddNode();
289+
290+
graph.Connect(1, 2, 1);
291+
graph.Connect(1, 3, 1);
292+
graph.Connect(1, 4, 5);
293+
graph.Connect(3, 4, 2);
294+
295+
var result = graph.Dijkstra(1, 4, 1);
296+
297+
Assert.True(result.IsFounded);
298+
Assert.Equal(5, result.Distance);
299+
300+
uint[] path = result.GetPath().ToArray();
301+
302+
Assert.Equal((uint)1, path[0]);
303+
Assert.Equal((uint)4, path[1]);
304+
}
191305
}
192306
}

src/Dijkstra.NET/Dijkstra.NET.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,4 @@
1212
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1313
<LangVersion>7.3</LangVersion>
1414
</PropertyGroup>
15-
1615
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Dijkstra.NET.Extensions
5+
{
6+
internal static class EnumerableExtensions
7+
{
8+
public static void Each<T>(this IEnumerable<T> iterator, Action<T> action)
9+
{
10+
foreach (var t in iterator)
11+
{
12+
action(t);
13+
}
14+
}
15+
}
16+
}

src/Dijkstra.NET/Graph/EdgeTemp.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Dijkstra.NET.Graph
44
{
5-
public struct EdgeTemp<T, TCustom> where TCustom: IEquatable<TCustom>
5+
public readonly struct EdgeTemp<T, TCustom> where TCustom: IEquatable<TCustom>
66
{
77
internal EdgeTemp(uint nodeFrom, uint nodeTo, Graph<T, TCustom> graph)
88
{
@@ -19,7 +19,7 @@ internal EdgeTemp(uint nodeFrom, uint nodeTo, Graph<T, TCustom> graph, int cost)
1919
Graph = graph;
2020
Cost = cost;
2121
}
22-
22+
2323
/// <summary>
2424
/// Define cost of edge
2525
/// </summary>
@@ -30,7 +30,7 @@ public static EdgeTemp<T, TCustom> operator>>(EdgeTemp<T, TCustom> edge, int cos
3030
{
3131
return new EdgeTemp<T, TCustom>(edge.NodeFrom, edge.NodeTo, edge.Graph, cost);
3232
}
33-
33+
3434
/// <summary>
3535
/// Create edge between two nodes
3636
/// </summary>
@@ -43,16 +43,16 @@ public static EdgeTemp<T, TCustom> operator>>(EdgeTemp<T, TCustom> edge, int cos
4343
{
4444
throw new InvalidOperationException("Cost of edge is not defined. Use >> operator to define it.");
4545
}
46-
46+
4747
return edge.Graph.Connect(edge.NodeFrom, edge.NodeTo, edge.Cost, edgeCustom);
4848
}
49-
49+
5050
public uint NodeFrom { get; }
5151

5252
public uint NodeTo { get; }
53-
53+
5454
public Graph<T, TCustom> Graph { get; }
55-
55+
5656
public int Cost { get; }
5757
}
5858
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
3+
namespace Dijkstra.NET.Graph.Exceptions
4+
{
5+
public class EdgeNotFoundException: Exception
6+
{
7+
internal EdgeNotFoundException(uint node)
8+
:base($"Edge with {node} nod key doesn't exist.")
9+
{
10+
}
11+
}
12+
}

src/Dijkstra.NET/Graph/Graph.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static Node<T, TEdgeCustom> operator >>(Graph<T, TEdgeCustom> graph, int
3333
{
3434
return (Node<T, TEdgeCustom>) graph[(uint)node];
3535
}
36-
36+
3737
/// <summary>
3838
/// Add node to graph
3939
/// </summary>
@@ -48,6 +48,7 @@ public uint AddNode(T item)
4848

4949
/// <summary>
5050
/// Connect node from with node to
51+
/// (from)-[cost, custom]->(to)
5152
/// </summary>
5253
/// <param name="from">First node</param>
5354
/// <param name="to">Second node</param>
@@ -61,15 +62,13 @@ public bool Connect(uint from, uint to, int cost, TEdgeCustom custom)
6162

6263
Node<T,TEdgeCustom> nodeFrom = _nodes[from];
6364
Node<T, TEdgeCustom> nodeTo = _nodes[to];
64-
65+
6566
nodeTo.AddParent(nodeFrom);
6667
nodeFrom.AddEdge(new Edge<T, TEdgeCustom>(nodeTo, cost, custom));
6768

6869
return true;
6970
}
7071

71-
IEnumerator<IPageRank> IEnumerable<IPageRank>.GetEnumerator() => _nodes.Select(x => x.Value).GetEnumerator();
72-
7372
public IEnumerator<INode<T, TEdgeCustom>> GetEnumerator() => _nodes.Select(x => x.Value).GetEnumerator();
7473

7574
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
@@ -78,21 +77,31 @@ public bool Connect(uint from, uint to, int cost, TEdgeCustom custom)
7877

7978
public int NodesCount => _nodes.Count;
8079

81-
IPageRank IPageRankGraph.this[uint node] => _nodes[node];
80+
public int EdgesCount(uint node) => _nodes[node].EdgesCount;
81+
82+
public IEnumerable<uint> Parents(uint node) => _nodes[node].Parents.Select(x => x.Key);
8283

83-
IDijkstra IDijkstraGraph.this[uint node] => _nodes[node];
84+
IEnumerator<uint> IEnumerable<uint>.GetEnumerator()
85+
{
86+
foreach (var node in _nodes)
87+
{
88+
yield return node.Key;
89+
}
90+
}
8491

8592
public override string ToString()
8693
{
8794
return $"Graph({_nodes.Count})";
8895
}
89-
96+
9097
protected void AddNode(uint key, T item)
9198
{
9299
if (_nodes.ContainsKey(key))
93100
throw new InvalidOperationException("Node have to be unique.", new Exception("The same key of node."));
94101

95102
_nodes.Add(key, new Node<T, TEdgeCustom>(key, item, this));
96103
}
104+
105+
Action<Edge> IDijkstraGraph.this[uint node] => _nodes[node].EachEdge;
97106
}
98107
}

src/Dijkstra.NET/Graph/INode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23

34
namespace Dijkstra.NET.Graph
45
{
@@ -7,7 +8,7 @@ public interface INode
78
uint Key { get; }
89
}
910

10-
public interface INode<T, TEdgeCustom> : INode where TEdgeCustom : IEquatable<TEdgeCustom>
11+
public interface INode<T, TEdgeCustom> : INode, IEnumerable<Edge<T, TEdgeCustom>> where TEdgeCustom : IEquatable<TEdgeCustom>
1112
{
1213
T Item { get; }
1314
}

0 commit comments

Comments
 (0)