import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import operator
import random
# Here, we'll simulate a random surfer stepping from page to page numIter times
def pageranks_walk(G, numIter):
visits = {}
for v in G.nodes():
visits[v] = 0
v = random.choice(list(G.nodes()))
for i in range(0, numIter):
visits[v] += 1
if G.out_degree(v) > 0:
v = random.choice(list(G.successors(v)))
else:
v = random.choice(list(G.nodes()))
pageranks = {}
for v in G.nodes():
pageranks[v] = visits[v] / numIter
return pageranks
# Here, we'll explicitly calculate PageRanks in a vertex-centric iterative way
def pageranks_calc(G, numIter):
pageranks = {}
sinks = 0
sinksNext = 0
for v in G.nodes():
pageranks[v] = 1.0 / G.order()
if G.out_degree(v) == 0:
sinks += pageranks[v]
for i in range(0, numIter):
for v in G.nodes():
pageranks[v] = sinks / G.order()
for e in G.in_edges(v):
u = e[0]
pageranks[v] += pageranks[u] / G.out_degree(u)
if G.out_degree(v) == 0:
sinksNext += pageranks[v]
sinks = sinksNext
sinksNext = 0
return pageranks
# Here, we'll use a linear algebraic approach that is similar to the computation
# that we're doing above for the vertex-centric approach
def pageranks_algebraic(G, numIter):
A = nx.to_numpy_matrix(G)
D = np.zeros(len(A))
for i in range(0, len(A)):
D[i] = A.sum(axis=1)[i]
D = np.linalg.inv(np.diag(D))
M = np.transpose(D * A)
p = np.full((len(A), 1), 1.0 / len(A))
for i in range(0, numIter):
p = M * p
pageranks = {}
count = 0
for i in G.nodes:
pageranks[i] = p[count]
count += 1
return pageranks
# Data from https://www.pro-football-reference.com/years/2022/games.htm
# Read it in and convert it into a graph of directed edges where the loser of
# each game points to the winner.
G = nx.read_edgelist("nfl.data", create_using=nx.DiGraph(), data = (("PtsL", int),("PtsW",int), ("YdsL",int), ("YdsW",int), ("TOL", int), ("TOW", int)) )
# We'll consider a couple ways to represent this competition network. First,
# we'll only use the winner/loser relationship. Next, we can effectively
# 'weight' the edges by the scores that resulted from the game. The greater the
# point differential, the more weight we'll effectively give to the edges going
# from the loser to the winner.
D = nx.MultiDiGraph()
for e in G.edges():
E = G.get_edge_data(e[0],e[1])
#D.add_edge(e[0], e[1]);
for i in range(0, E['PtsW']):
D.add_edge(e[0], e[1]);
for i in range(0, E['PtsL']):
D.add_edge(e[1], e[0]);
P = pageranks_walk(D, 100)
P = pageranks_calc(D, 100)
P = pageranks_algebraic(D, 100)
P = sorted(P.items(), key=operator.itemgetter(1), reverse=True)