Compute PageRank for each vertex

Details of the algorithm can be found in:

L. Page, S. Brin, R. Motwani, and T.Winograd. The pagerank citation ranking: Bringing order to the web. Technical report, Stanford Digital Library Technologies Project, 1998

Example:

var g = new HashDigraph[String]
g.add_arc("A", "B")
g.add_arc("A", "C")
g.add_arc("B", "C")
g.add_arc("C", "A")
g.add_arc("D", "C")

assert g.pagerank.join(", ", ":") == "A:1.488, B:0.782, C:1.575, D:0.15"

Property definitions

graph :: pagerank $ Digraph :: pagerank
	# Compute PageRank for each vertex
	#
	# Details of the algorithm can be found in:
	# > L. Page, S. Brin, R. Motwani, and T.Winograd.
	# > **The pagerank citation ranking: Bringing order to the web.**
	# > *Technical report, Stanford Digital Library Technologies Project, 1998*
	#
	# Example:
	# ~~~
	# var g = new HashDigraph[String]
	# g.add_arc("A", "B")
	# g.add_arc("A", "C")
	# g.add_arc("B", "C")
	# g.add_arc("C", "A")
	# g.add_arc("D", "C")
	#
	# assert g.pagerank.join(", ", ":") == "A:1.488, B:0.782, C:1.575, D:0.15"
	# ~~~
	fun pagerank: PRMap[V] do
		# `d` constant such as `initial_pagerank(node) == (1 - d) != 0`
		var d = 0.85 # commonly-choosen value
		# Init each node page rank with an initial_value
		var values = new PRMap[V]
		var vertices = self.vertices
		for v in vertices do values[v] = 1.0 - d
		# Compute page rank until convergence
		var prev = new PRMap[V]
		while not values.is_approx(prev, 0.001) do
			prev = new PRMap[V].from(values)
			for v in vertices do
				var in_pr = 0.0
				for o in predecessors(v) do
					in_pr += values[o] / out_degree(o).to_f
				end
				values[v] = (1.0 - d) + d * in_pr
			end
		end
		return values
	end
lib/graph/pagerank.nit:22,2--60,4