import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import random
import operator

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


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


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)
	
	pageranks = np.full((len(A), 1), 1.0 / len(A))
	
	for i in range(0, numIter):
		pageranks = M * pageranks
		
	return pageranks


def pageranks_personalized(G, numIter, root):
	alpha = 0.1
	stops = {}
	for v in G.nodes():
		stops[v] = 0
	
	for i in range(0, numIter):
		v = root
		stop = False
		while stop == False:
			if random.random() < alpha:
				stop = True
			else:
				v = random.choice(list(G.successors(v)))
		
		stops[v] += 1
	
	pageranks = {}
	for v in G.nodes():
		pageranks[v] = stops[v] / numIter
	
	return pageranks


# Data from https://www.pro-football-reference.com/years/2019/games.htm
G = nx.read_edgelist("nfl.data", create_using=nx.MultiDiGraph(), data = (("pL", int),("pW",int), ("ydsL",int), ("ydsW",int), ("toL", int),("toW", int)) )


D = nx.MultiDiGraph()
for e in G.edges():
	E = G.get_edge_data(e[0],e[1])
	
	for i in range(0, E[0]['pW']):
		D.add_edge(e[0], e[1]);
		
	for i in range(0, E[0]['pL']):
		D.add_edge(e[1], e[0]);
		
		
P = pageranks_calc(G, 100)
P = pageranks_algebraic(G, 100)
P = pageranks_walk(G, 1000000)
P = pageranks_personalized(G, 1000000, '49ers')
P = sorted(P.items(), key=operator.itemgetter(1), reverse=True)


