page-rank #
import networkx as nx
import matplotlib.pyplot as plt
import random
def pagerank(A, d, iterations):
nodes = len(A)
M = [[0 for j in range(0,nodes)] for i in range(0,nodes)]
# Calculate M from A
for i in range(0,nodes):
count = 0
for j in range(0,nodes):
count += A[i][j]
for j in range(0,nodes):
if(A[i][j] == 1):
M[i][j] = 1/count
# Calculate M' = d * M + ...
for i in range(0,nodes):
for j in range(0,nodes):
M[i][j] = M[i][j]*d + (1-d)*1/nodes
# Normalize
for i in range(0,nodes):
count = 0
for j in range(0,nodes):
count += M[i][j]
for j in range(0,nodes):
M[i][j] /= count
#Transponiere
MT = [[0 for j in range(0,nodes)] for i in range(0,nodes)]
for i in range(0,nodes):
for j in range(0,nodes):
MT[j][i] = M[i][j]
# Initialize PR
PR = [1/nodes for i in range(0,nodes)]
# Power Iteration
for l in range(0,iterations):
PRsafe = [0 for i in range(0,nodes)]
for i in range(0,nodes):
for j in range(0,nodes):
PRsafe[i] += MT[i][j]*PR[j]
count = 0
PR=PRsafe
for i in range(0,nodes):
count += PR[i]
for i in range(0,nodes):
PR[i] /= count
return PR
def plot_graph(adj_matrix, pageranks):
# create directed graph from adjacency matrix
edges = []
for i in range(len(adj_matrix)):
for j in range(len(adj_matrix[i])):
if adj_matrix[i][j] != 0:
edges.append((i, j))
G = nx.DiGraph(edges)
for i in range(len(pageranks)):
if not G.has_node(i):
G.add_node(i)
# set node labels and sizes based on pageranks
node_sizes, node_labels = [], {}
for i in G.nodes:
node_labels[i] = f'{i}\n{pageranks[i]:.2f}'
node_sizes.append(max(1000, int(10000 * pageranks[i])))
# set node colors based on pageranks
node_colors = [(0.0 + pageranks[i], 0.0, 1.0 - pageranks[i], 1.0) for i in G.nodes]
# plot graph
pos = nx.spring_layout(G, seed=42, k=1, iterations=10)
nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color=node_colors)
nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=10)
nx.draw_networkx_edges(G, pos, connectionstyle='arc3,rad=.1', node_size=node_sizes)
plt.axis('off')
plt.show()
def generate_random_digraph(V, E):
adj_matrix = [[0 for j in range(V)] for i in range(V)]
edges = set()
while len(edges) < E:
start_node, end_node = random.randint(0, V-1), random.randint(0, V-1)
if start_node != end_node:
edges.add((start_node, end_node))
for start_node, end_node in edges:
adj_matrix[start_node][end_node] = 1
return adj_matrix
d, iterations = 0.85, 1000
# Wikipedia:
# Die Ergebnisse fuer das englische und deutsche wiki
# sind fuer den gleichen Graphen scheinbar different
# Dies koennte an der (fehlender) Normierung liegen
adj_matrix_wiki = [
[0,0,0,0,0,0,0,0,0,0,0],#A
[0,0,1,0,0,0,0,0,0,0,0],#B
[0,1,0,0,0,0,0,0,0,0,0],#C
[1,1,0,0,0,0,0,0,0,0,0],#D
[0,1,0,1,0,1,0,0,0,0,0],#E
[0,1,0,0,1,0,0,0,0,0,0],#F
[0,1,0,0,1,0,0,0,0,0,0],#G
[0,1,0,0,1,0,0,0,0,0,0],#H
[0,1,0,0,1,0,0,0,0,0,0],#I
[0,0,0,0,1,0,0,0,0,0,0],#J
[0,0,0,0,1,0,0,0,0,0,0],#K
]
adj_matrix_standford = [
[0,1,1],
[1,0,1],
[1,0,0],
]
adj_matrix = generate_random_digraph(8,12)
pageranks = pagerank(adj_matrix_wiki, d, iterations)
plot_graph(adj_matrix_wiki, pageranks)
ford fulkerson #
from train_max_flow_backend import *
#
# 3.6 (a)
#
def ford_fulkerson_max_flow(graph, source, sink):
#So in der Art ist die Methode
flow = 0
maxFlow = 0
graph = transform_graph(graph.copy())
resgraph = create_residual_graph(graph)
path = find_augmenting_path(resgraph, source, sink)
bahnhoefe = set()
while len(path)>0:
path = find_augmenting_path(resgraph, source, sink)
flow = calculate_path_flow(resgraph, path)
maxFlow += flow
update_residual_graph(resgraph, path, flow)
for bahnhof in path:
bahnhoefe.add(bahnhof)
return (maxFlow, bahnhoefe, resgraph)
#
# 3.6 (b)
#
def create_residual_graph(graph):
dictPath = {}
for node in graph:
#Edge
if not node["source"] in dictPath:
dictPath[node["source"]] = {}
dictPath[node["source"]][node["target"]] = node["capacity"]
#Backedge
if not node["target"] in dictPath:
dictPath[node["target"]] = {}
dictPath[node["target"]][node["source"]] = 0
return dictPath
#
# 3.6 (c)
#
def find_augmenting_path(graph, source, sink):
path = []
visited = set()
def dfs(u):
visited.add(u)
path.append(u)
if u == sink:
return True
for v in graph[u].keys():
if v not in visited and graph[u][v] > 0:
if dfs(v):
return True
path.pop()
return
dfs(source)
return path
#
# 3.6 (d)
#
def calculate_path_flow(graph, path):
if len(path) == 0:
return 0
smallestFlow = graph[path[0]][path[1]]
for i in range(len(path)-1):
if graph[path[i]][path[i+1]] < smallestFlow:
smallestFlow = graph[path[i]][path[i+1]]
return smallestFlow
#
# 3.6 (e)
#
def update_residual_graph(graph, path, path_flow):
for i in range(len(path)-1):
u = path[i]
v = path[i+1]
graph[u][v] -= path_flow
graph[v][u] += path_flow
#
# 3.6 (f)
#
def transform_graph(graph):
for u in graph:
for v in graph:
if u["source"] == v["target"] and v["source"] == u["target"]:
helper = {"source": u["source"] + u["target"] + "helper", "target": u["target"]}
graph.append(helper)
x = city_positions[u["target"]][0] + (city_positions[u["source"]][0] - city_positions[u["target"]][0])/2
y = city_positions[u["target"]][1] + (city_positions[u["source"]][1] - city_positions[u["target"]][1])/2
city_positions[u["source"] + u["target"] + "helper"] = (x,y)
u["target"] = u["source"] + u["target"] + "helper"
add_capacities(graph)
return graph
############################################################
# Testbereich beginnt:
############################################################
from train_data import Routes_Bavaria as Routes, city_positions_bavaria as city_positions
#from train_data import Routes_Bavaria_Extended as Routes
#from train_data import city_positions_bavaria_extended as city_positions
#from train_data import Routes, city_positions
add_capacities(Routes)
maxflow = ford_fulkerson_max_flow(Routes, "Würzburg", "Passau")
print(maxflow)
#maxflow = ford_fulkerson_max_flow(Routes, "Vancouver", "Miami")
#from train_data import Simple_Test_Case as Routes
#from train_data import simple_test_case_positions as city_positions
#maxflow= ford_fulkerson_max_flow(Routes, "A", "D")
plot_routes(Routes, city_positions, maxflow)