Skip to content

Commit a3effe2

Browse files
committed
Merge remote-tracking branch 'origin/feature/pagerank' into text_rank
2 parents e0f5c8b + 0887503 commit a3effe2

16 files changed

Lines changed: 1376 additions & 0 deletions

PageRank/Graph/DirectedGraph.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
3+
namespace PageRank.Graph
4+
{
5+
public class DirectedGraph<T> : Graph<T>
6+
{
7+
public override bool IsDirected
8+
{
9+
get
10+
{
11+
return true;
12+
}
13+
}
14+
15+
public DirectedGraph() : base()
16+
{ }
17+
18+
public DirectedGraph(NodeSet<T> nodeSet) : base(nodeSet)
19+
{ }
20+
21+
public void AddEdge(T source, T destination, double weight = 1.0)
22+
{
23+
base.AddEdges(source, destination, weight);
24+
}
25+
26+
/// <summary>
27+
///
28+
/// </summary>
29+
/// <param name="soruce"></param>
30+
/// <param name="destination"></param>
31+
/// <param name="weight"></param>
32+
public void AddEdge(GraphNode<T> soruce, GraphNode<T> destination, double weight = 1.0)
33+
{
34+
base.AddEdges(soruce, destination, weight);
35+
}
36+
37+
/// <summary>
38+
///
39+
/// </summary>
40+
/// <param name="edges"></param>
41+
/// <param name="weight"></param>
42+
public void AddEdges(Tuple<GraphNode<T>, GraphNode<T>>[] edges, double weight = 1.0)
43+
{
44+
foreach (Tuple<GraphNode<T>, GraphNode<T>> edge in edges)
45+
{
46+
base.AddEdges(edge.Item1, edge.Item2, weight);
47+
}
48+
}
49+
}
50+
}

PageRank/Graph/Graph.cs

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace PageRank.Graph
7+
{
8+
/// <summary>
9+
///
10+
/// </summary>
11+
/// <typeparam name="T"></typeparam>
12+
public abstract class Graph<T> : IEnumerable<GraphNode<T>>
13+
{
14+
protected NodeSet<T> _nodeSet;
15+
protected LookUp<T> _lookupTable;
16+
protected int _capacity = Int32.MaxValue;
17+
18+
protected Graph()
19+
{
20+
_lookupTable = new LookUp<T>();
21+
_nodeSet = new NodeSet<T>();
22+
_capacity = Int32.MaxValue;
23+
}
24+
25+
internal Graph(NodeSet<T> nodeSet) : this()
26+
{
27+
// add all node to lookup list
28+
foreach (var node in _nodeSet)
29+
{
30+
if (node != null)
31+
{
32+
_lookupTable.Add(node.Value, node);
33+
_nodeSet.Add(node);
34+
}
35+
}
36+
}
37+
38+
/// <summary>
39+
///
40+
/// </summary>
41+
/// <param name="source"></param>
42+
/// <param name="destination"></param>
43+
/// <returns></returns>
44+
public double this[GraphNode<T> source, GraphNode<T> destination] => GetWeight(source, destination);
45+
46+
private double GetWeight(GraphNode<T> source, GraphNode<T> destination)
47+
{
48+
if (!(_nodeSet.Contains(source) && _nodeSet.Contains(destination)))
49+
return -1;
50+
51+
//weight = Graph[Source][destination]
52+
double nabs = source[destination];
53+
return nabs;
54+
}
55+
56+
/// <summary>
57+
///
58+
/// </summary>
59+
/// <param name="source"></param>
60+
/// <returns></returns>
61+
public Neighbors<T> this[GraphNode<T> source] => GetNeighbors(source);
62+
63+
/// <summary>
64+
///
65+
/// </summary>
66+
/// <param name="source"></param>
67+
/// <returns></returns>
68+
private Neighbors<T> GetNeighbors(GraphNode<T> source)
69+
{
70+
return source.Neighbors;
71+
}
72+
73+
/// <summary>
74+
///
75+
/// </summary>
76+
/// <param name="node"></param>
77+
/// <returns></returns>
78+
internal bool Remove(T node)
79+
{
80+
//check the node in lookup table
81+
if (node == null && !_lookupTable.Contains(node))
82+
return false;
83+
84+
// first remove the node from the nodeset
85+
var nodeToRemove = _nodeSet.Get(node);
86+
87+
// node wasn't found
88+
if (nodeToRemove == null)
89+
return false;
90+
91+
var danglingNeighbors = nodeToRemove.Neighbors.Where(nab => nab.Weight == 0).ToDictionary(nab => nab.GraphNode);
92+
93+
// otherwise, the node was found
94+
bool status = _nodeSet.Remove(nodeToRemove);
95+
96+
// enumerate through each node in the nodeSet, removing edges to this node
97+
// if its neighbor is dangling node then
98+
// we remove the neighbor but if its neighbor is not dengling then then preserve it in graph.
99+
// if we not want forest.
100+
101+
return status;
102+
}
103+
104+
/// <summary>
105+
///
106+
/// </summary>
107+
internal List<GraphNode<T>> DanglingNodes
108+
{
109+
get
110+
{
111+
List<GraphNode<T>> _danglinNodes = new List<GraphNode<T>>();
112+
foreach (var node in this.OutDegree)
113+
{
114+
if (node.Value == 0)
115+
_danglinNodes.Add(node.Key);
116+
}
117+
118+
return _danglinNodes;
119+
}
120+
}
121+
122+
internal bool Contains(T value)
123+
{
124+
return _nodeSet.FindByValue(value) != null;
125+
}
126+
127+
public IEnumerator<GraphNode<T>> GetEnumerator()
128+
{
129+
return (IEnumerator<GraphNode<T>>)_nodeSet.GetEnumerator();
130+
}
131+
132+
IEnumerator IEnumerable.GetEnumerator()
133+
{
134+
return GetEnumerator();
135+
}
136+
137+
public List<GraphNode<T>> Nodes
138+
{
139+
get
140+
{
141+
return _nodeSet.ToList;
142+
}
143+
}
144+
145+
public bool IsEmpty
146+
{
147+
get
148+
{
149+
return this.Count > 0 ? false : true;
150+
}
151+
}
152+
153+
public int Count
154+
{
155+
get { return _nodeSet.Count; }
156+
}
157+
158+
public Dictionary<GraphNode<T>, double> OutDegree
159+
{
160+
get
161+
{
162+
if (this.IsEmpty)
163+
return null;
164+
else
165+
return GetOutDegree();
166+
}
167+
}
168+
169+
public abstract bool IsDirected { get; }
170+
171+
private Dictionary<GraphNode<T>, double> GetOutDegree()
172+
{
173+
Dictionary<GraphNode<T>, double> outDegree = new Dictionary<GraphNode<T>, double>();
174+
175+
//build graph outdegree dictionary
176+
foreach (GraphNode<T> node in this)
177+
outDegree.Add(node, node.OutDegree);
178+
179+
return outDegree;
180+
}
181+
182+
internal GraphNode<T> FindByValue(T value)
183+
{
184+
GraphNode<T> node = null;
185+
node = this._nodeSet.FindByValue(value);
186+
187+
return node;
188+
}
189+
190+
/// <summary>
191+
///
192+
/// </summary>
193+
/// <param name="value"></param>
194+
/// <returns></returns>
195+
protected GraphNode<T> Add(T value)
196+
{
197+
if (value == null)
198+
return null;
199+
try
200+
{
201+
//first check the value in _lookup table
202+
if (_lookupTable.Contains(value))
203+
{
204+
var lookup = _lookupTable.Get(value);
205+
return lookup;
206+
}
207+
208+
GraphNode<T> node = new GraphNode<T>();
209+
node.Value = value;
210+
_lookupTable.Add(value, node);
211+
_nodeSet.Add(node);
212+
return node;
213+
}
214+
catch (Exception ex)
215+
{
216+
return null;
217+
}
218+
}
219+
220+
/// <summary>
221+
///
222+
/// </summary>
223+
/// <param name="source"></param>
224+
/// <param name="destination"></param>
225+
/// <param name="weight"></param>
226+
protected void AddEdges(GraphNode<T> source, GraphNode<T> destination, double weight = 1.0)
227+
{
228+
if (source == null || destination == null)
229+
return;
230+
231+
var lookup = _lookupTable.Get(source.Value);
232+
233+
if (lookup == null || !(source == lookup))
234+
{
235+
_lookupTable.Add(source.Value, source);
236+
_nodeSet.Add(source);
237+
}
238+
if (!(destination == _lookupTable.Get(destination.Value)))
239+
{
240+
_lookupTable.Add(destination.Value, destination);
241+
_nodeSet.Add(destination);
242+
}
243+
244+
source.Neighbors.Add(destination as GraphNode<T>, weight);
245+
}
246+
247+
/// <summary>
248+
///
249+
/// </summary>
250+
/// <param name="source"></param>
251+
/// <param name="destination"></param>
252+
/// <param name="weight"></param>
253+
protected void AddEdges(T source, T destination, double weight = 1.0)
254+
{
255+
if (source == null || destination == null)
256+
return;
257+
258+
var gsource = this.Add(source);
259+
var gdestination = this.Add(destination);
260+
261+
this.AddEdges(gsource, gdestination, weight);
262+
}
263+
}
264+
}

0 commit comments

Comments
 (0)