Skip to content

Commit 95a9b10

Browse files
committed
i20 pr implementation
1 parent 348d913 commit 95a9b10

File tree

14 files changed

+210
-48
lines changed

14 files changed

+210
-48
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using Dijkstra.NET.Graph;
3+
using Dijkstra.NET.PageRank;
4+
using Xunit;
5+
6+
namespace Dijkstra.NET.Tests.PageRank
7+
{
8+
public class PageRankExtensionsTests
9+
{
10+
[Fact]
11+
public void CalculatePageRank_Should_Calculate_Correct_PageRank()
12+
{
13+
var g = new Graph<string, byte>();
14+
15+
uint a = g.AddNode("A");
16+
uint b = g.AddNode("B");
17+
uint c = g.AddNode("C");
18+
uint d = g.AddNode("D");
19+
20+
g.Connect(a, b, 0, 0);
21+
g.Connect(a, c, 0, 0);
22+
g.Connect(b, d, 0, 0);
23+
g.Connect(c, a, 0, 0);
24+
g.Connect(c, b, 0, 0);
25+
g.Connect(c, d, 0, 0);
26+
g.Connect(d, c, 0, 0);
27+
28+
29+
var result = g.CalculatePageRank();
30+
31+
Assert.True(Math.Abs(result[c] - 0.35625) < 0.0001);
32+
}
33+
}
34+
}

src/Dijkstra.NET/Graph/ChildAction.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/Dijkstra.NET/Graph/Graph.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using Dijkstra.NET.PageRank;
6+
using Dijkstra.NET.ShortestPath;
57

68
namespace Dijkstra.NET.Graph
79
{
8-
public class Graph<T, TEdgeCustom>: IGraph<T, TEdgeCustom>, IEnumerable<INode<T, TEdgeCustom>> where TEdgeCustom : IEquatable<TEdgeCustom>
10+
public class Graph<T, TEdgeCustom>: IDijkstraGraph, IPageRankGraph, IGraph<T, TEdgeCustom>, IEnumerable<INode<T, TEdgeCustom>> where TEdgeCustom : IEquatable<TEdgeCustom>
911
{
1012
private readonly IDictionary<uint, Node<T, TEdgeCustom>> _nodes = new Dictionary<uint, Node<T, TEdgeCustom>>();
1113

@@ -44,16 +46,25 @@ public bool Connect(uint from, uint to, int cost, TEdgeCustom custom)
4446

4547
Node<T,TEdgeCustom> nodeFrom = _nodes[from];
4648
Node<T, TEdgeCustom> nodeTo = _nodes[to];
47-
48-
nodeFrom.AddChild(new Edge<T, TEdgeCustom>(nodeTo, cost, custom));
49+
50+
nodeTo.AddParent(nodeFrom);
51+
nodeFrom.AddEdge(new Edge<T, TEdgeCustom>(nodeTo, cost, custom));
4952

5053
return true;
5154
}
5255

56+
IEnumerator<IPageRank> IEnumerable<IPageRank>.GetEnumerator() => _nodes.Select(x => x.Value).GetEnumerator();
57+
5358
public IEnumerator<INode<T, TEdgeCustom>> GetEnumerator() => _nodes.Select(x => x.Value).GetEnumerator();
5459

5560
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
5661

5762
public INode<T, TEdgeCustom> this[uint node] => _nodes[node];
63+
64+
public int NodesCount => _nodes.Count;
65+
66+
IPageRank IPageRankGraph.this[uint node] => _nodes[node];
67+
68+
IDijkstra IDijkstraGraph.this[uint node] => _nodes[node];
5869
}
5970
}

src/Dijkstra.NET/Graph/INode.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
namespace Dijkstra.NET.Graph
44
{
5-
public interface INode<T,TEdgeCustom> where TEdgeCustom : IEquatable<TEdgeCustom>
5+
public interface INode
66
{
7-
T Item { get; }
8-
97
uint Key { get; }
10-
11-
void EachChild(ChildAction<T, TEdgeCustom> action);
8+
}
9+
10+
public interface INode<T, TEdgeCustom> : INode where TEdgeCustom : IEquatable<TEdgeCustom>
11+
{
12+
T Item { get; }
1213
}
1314
}

src/Dijkstra.NET/Graph/Node.cs

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,50 @@
11
using System;
2+
using System.Collections.Generic;
3+
using Dijkstra.NET.PageRank;
4+
using Dijkstra.NET.ShortestPath;
25

36
namespace Dijkstra.NET.Graph
47
{
5-
public class Node<T, TEdgeCustom>: INode<T, TEdgeCustom> where TEdgeCustom: IEquatable<TEdgeCustom>
8+
public class Node<T, TEdgeCustom>: IPageRank, IDijkstra, INode<T, TEdgeCustom> where TEdgeCustom: IEquatable<TEdgeCustom>
69
{
7-
private Edge<T, TEdgeCustom>[] _children;
10+
private readonly HashSet<Node<T,TEdgeCustom>> _parents = new HashSet<Node<T, TEdgeCustom>>();
11+
private readonly HashSet<uint> _children = new HashSet<uint>();
12+
private Edge<T, TEdgeCustom>[] _edges;
813

914
public Node(uint key, T item)
1015
{
1116
Key = key;
1217
Item = item;
13-
_children = new Edge<T, TEdgeCustom>[5];
18+
_edges = new Edge<T, TEdgeCustom>[5];
1419
}
1520

1621
public uint Key { get; }
1722

1823
public T Item { get; }
1924

20-
public int ChildrenCount { get; internal set; }
25+
public int EdgesCount { get; internal set; }
26+
27+
public int NumberOfEdges => _children.Count;
2128

22-
internal void AddChild(in Edge<T, TEdgeCustom> edge)
29+
public IEnumerable<IPageRank> Parents => _parents;
30+
31+
public void EachEdge(Edge edge)
2332
{
24-
if (_children.Length == ChildrenCount)
33+
for (int i = 0; i < EdgesCount; i++)
2534
{
26-
int newSize = _children.Length;
35+
ref Edge<T, TEdgeCustom> e = ref _edges[i];
2736

28-
if (ChildrenCount < NodeConstants.MaxSize)
37+
edge(e.Node.Key, e.Cost);
38+
}
39+
}
40+
41+
internal void AddEdge(in Edge<T, TEdgeCustom> edge)
42+
{
43+
if (_edges.Length == EdgesCount)
44+
{
45+
int newSize = _edges.Length;
46+
47+
if (EdgesCount < NodeConstants.MaxSize)
2948
{
3049
newSize *= 2;
3150
}
@@ -36,21 +55,34 @@ internal void AddChild(in Edge<T, TEdgeCustom> edge)
3655
newSize = bigSize < Int32.MaxValue ? (int)bigSize : Int32.MaxValue;
3756
}
3857

39-
Array.Resize(ref _children, newSize);
58+
Array.Resize(ref _edges, newSize);
4059
}
4160

42-
_children[ChildrenCount] = edge;
43-
ChildrenCount++;
61+
_edges[EdgesCount] = edge;
62+
EdgesCount++;
63+
_children.Add(edge.Node.Key);
4464
}
4565

46-
public void EachChild(ChildAction<T, TEdgeCustom> action)
66+
internal void AddParent(Node<T, TEdgeCustom> parent)
4767
{
48-
for (int i = 0; i < ChildrenCount; i++)
49-
{
50-
ref Edge<T, TEdgeCustom> e = ref _children[i];
68+
_parents.Add(parent);
69+
}
5170

52-
action(in e);
53-
}
71+
public override int GetHashCode()
72+
{
73+
return Key.GetHashCode();
74+
}
75+
76+
public override bool Equals(object obj)
77+
{
78+
var node = obj as INode;
79+
80+
return node?.Key == Key;
81+
}
82+
83+
public override string ToString()
84+
{
85+
return $"[{Key}({Item?.ToString()})]";
5486
}
5587
}
5688
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Collections.Generic;
2+
using Dijkstra.NET.Graph;
3+
4+
namespace Dijkstra.NET.PageRank
5+
{
6+
public interface IPageRank : INode
7+
{
8+
int NumberOfEdges { get; }
9+
10+
IEnumerable<IPageRank> Parents { get; }
11+
}
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Collections.Generic;
2+
3+
namespace Dijkstra.NET.PageRank
4+
{
5+
public interface IPageRankGraph : IEnumerable<IPageRank>
6+
{
7+
IPageRank this[uint node] { get; }
8+
9+
int NodesCount { get; }
10+
}
11+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Dijkstra.NET.PageRank
5+
{
6+
public static class PageRankExtensions
7+
{
8+
public static PageRankResult CalculatePageRank(this IPageRankGraph graph, double d = 0.85)
9+
{
10+
var pageRank0 = new Dictionary<uint, double>();
11+
var pageRank1 = new Dictionary<uint, double>();
12+
var pageRank2 = new Dictionary<uint, double>();
13+
14+
// 0
15+
foreach (var node in graph)
16+
{
17+
pageRank0[node.Key] = 1.0 / graph.NodesCount;
18+
}
19+
20+
// 1
21+
foreach (var node in graph)
22+
{
23+
pageRank1[node.Key] = (1 - d) / graph.NodesCount + d * node.Parents.Sum(x => pageRank0[x.Key] / x.NumberOfEdges);
24+
}
25+
26+
// 2
27+
foreach (var node in graph)
28+
{
29+
pageRank2[node.Key] = (1 - d) / graph.NodesCount + d * node.Parents.Sum(x => pageRank1[x.Key] / x.NumberOfEdges);
30+
}
31+
32+
return new PageRankResult(pageRank2);
33+
}
34+
}
35+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Collections.Generic;
2+
3+
namespace Dijkstra.NET.PageRank
4+
{
5+
public struct PageRankResult
6+
{
7+
private readonly Dictionary<uint, double> _pageRank;
8+
9+
public PageRankResult(Dictionary<uint, double> pageRank)
10+
{
11+
_pageRank = pageRank;
12+
}
13+
14+
public double this[uint node] => _pageRank[node];
15+
}
16+
}

src/Dijkstra.NET/ShortestPath/Dijkstra.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ namespace Dijkstra.NET.ShortestPath
66
{
77
internal static class Dijkstra
88
{
9-
public static ShortestPathResult GetShortestPath<T, TEdgeCustom>(IGraph<T, TEdgeCustom> graph, uint from, uint to,
10-
int depth, int modulo = 1, int r = 0)
11-
where TEdgeCustom : IEquatable<TEdgeCustom>
9+
public static ShortestPathResult GetShortestPath(IDijkstraGraph graph, uint from, uint to, int depth)
1210
{
1311
var path = new Dictionary<uint, uint>();
1412
var distance = new Dictionary<uint, int> {[from] = 0};
@@ -37,20 +35,20 @@ int Distance(uint key)
3735
continue;
3836
}
3937

40-
graph[u].EachChild((in Edge<T, TEdgeCustom> e) =>
38+
graph[u].EachEdge((node, cost) =>
4139
{
42-
if (e.Node.Key % modulo == r && Distance(e.Node.Key) > Distance(u) + e.Cost)
40+
if (Distance(node) > Distance(u) + cost)
4341
{
44-
if (current.Contains(e.Node.Key))
42+
if (current.Contains(node))
4543
{
46-
q.Remove(e.Node.Key);
44+
q.Remove(node);
4745
}
4846

49-
distance[e.Node.Key] = Distance(u) + e.Cost;
50-
q.Add(e.Node.Key);
51-
current.Add(e.Node.Key);
52-
path[e.Node.Key] = u;
53-
d[e.Node.Key] = d[u] + 1;
47+
distance[node] = Distance(u) + cost;
48+
q.Add(node);
49+
current.Add(node);
50+
path[node] = u;
51+
d[node] = d[u] + 1;
5452
}
5553
});
5654

0 commit comments

Comments
 (0)