|
|
@ -0,0 +1,142 @@ |
|
|
|
class Graph: |
|
|
|
def __init__(self): |
|
|
|
self.vertices = {} |
|
|
|
|
|
|
|
def add_vertex(self, key): |
|
|
|
vertex = Vertex(key) |
|
|
|
self.vertices[key] = vertex |
|
|
|
|
|
|
|
def get_vertex(self, key): |
|
|
|
return self.vertices[key] |
|
|
|
|
|
|
|
def __contains__(self, key): |
|
|
|
return key in self.vertices |
|
|
|
|
|
|
|
def add_edge(self, src_key, dest_key, weight=1): |
|
|
|
self.vertices[src_key].add_neighbour(self.vertices[dest_key], weight) |
|
|
|
|
|
|
|
def does_edge_exist(self, src_key, dest_key): |
|
|
|
return self.vertices[src_key].does_it_point_to(self.vertices[dest_key]) |
|
|
|
|
|
|
|
def __len__(self): |
|
|
|
return len(self.vertices) |
|
|
|
|
|
|
|
def __iter__(self): |
|
|
|
return iter(self.vertices.values()) |
|
|
|
|
|
|
|
|
|
|
|
class Vertex: |
|
|
|
def __init__(self, key): |
|
|
|
self.key = key |
|
|
|
self.points_to = {} |
|
|
|
|
|
|
|
def get_key(self): |
|
|
|
return self.key |
|
|
|
|
|
|
|
def add_neighbour(self, dest, weight): |
|
|
|
self.points_to[dest] = weight |
|
|
|
|
|
|
|
def get_neighbours(self): |
|
|
|
return self.points_to.keys() |
|
|
|
|
|
|
|
def get_weight(self, dest): |
|
|
|
return self.points_to[dest] |
|
|
|
|
|
|
|
def does_it_point_to(self, dest): |
|
|
|
return dest in self.points_to |
|
|
|
|
|
|
|
|
|
|
|
def floyd_warshall(g): |
|
|
|
distance = {v:dict.fromkeys(g, float('inf')) for v in g} |
|
|
|
next_v = {v:dict.fromkeys(g, None) for v in g} |
|
|
|
|
|
|
|
for v in g: |
|
|
|
for n in v.get_neighbours(): |
|
|
|
distance[v][n] = v.get_weight(n) |
|
|
|
next_v[v][n] = n |
|
|
|
|
|
|
|
for v in g: |
|
|
|
distance[v][v] = 0 |
|
|
|
next_v[v][v] = None |
|
|
|
|
|
|
|
for p in g: |
|
|
|
for v in g: |
|
|
|
for w in g: |
|
|
|
if distance[v][w] > distance[v][p] + distance[p][w]: |
|
|
|
distance[v][w] = distance[v][p] + distance[p][w] |
|
|
|
next_v[v][w] = next_v[v][p] |
|
|
|
|
|
|
|
return distance, next_v |
|
|
|
|
|
|
|
|
|
|
|
def print_path(next_v, u, v): |
|
|
|
|
|
|
|
p = u |
|
|
|
while (next_v[p][v]): |
|
|
|
print('{} -> '.format(p.get_key()), end='') |
|
|
|
p = next_v[p][v] |
|
|
|
print('{} '.format(v.get_key()), end='') |
|
|
|
|
|
|
|
|
|
|
|
g = Graph() |
|
|
|
print('Menu') |
|
|
|
print('add vertex <key>') |
|
|
|
print('add edge <src> <dest> <weight>') |
|
|
|
print('floyd-warshall') |
|
|
|
print('display') |
|
|
|
print('quit') |
|
|
|
|
|
|
|
while True: |
|
|
|
do = input('What would you like to do? ').split() |
|
|
|
|
|
|
|
operation = do[0] |
|
|
|
if operation == 'add': |
|
|
|
suboperation = do[1] |
|
|
|
if suboperation == 'vertex': |
|
|
|
key = int(do[2]) |
|
|
|
if key not in g: |
|
|
|
g.add_vertex(key) |
|
|
|
else: |
|
|
|
print('Vertex already exists.') |
|
|
|
elif suboperation == 'edge': |
|
|
|
src = int(do[2]) |
|
|
|
dest = int(do[3]) |
|
|
|
weight = int(do[4]) |
|
|
|
if src not in g: |
|
|
|
print('Vertex {} does not exist.'.format(src)) |
|
|
|
elif dest not in g: |
|
|
|
print('Vertex {} does not exist.'.format(dest)) |
|
|
|
else: |
|
|
|
if not g.does_edge_exist(src, dest): |
|
|
|
g.add_edge(src, dest, weight) |
|
|
|
else: |
|
|
|
print('Edge already exists.') |
|
|
|
|
|
|
|
elif operation == 'floyd-warshall': |
|
|
|
distance, next_v = floyd_warshall(g) |
|
|
|
print('Shortest distances:') |
|
|
|
for start in g: |
|
|
|
for end in g: |
|
|
|
if next_v[start][end]: |
|
|
|
print('From {} to {}: '.format(start.get_key(), |
|
|
|
end.get_key()), |
|
|
|
end = '') |
|
|
|
print_path(next_v, start, end) |
|
|
|
print('(distance {})'.format(distance[start][end])) |
|
|
|
|
|
|
|
elif operation == 'display': |
|
|
|
print('Vertices: ', end='') |
|
|
|
for v in g: |
|
|
|
print(v.get_key(), end=' ') |
|
|
|
print() |
|
|
|
|
|
|
|
print('Edges: ') |
|
|
|
for v in g: |
|
|
|
for dest in v.get_neighbours(): |
|
|
|
w = v.get_weight(dest) |
|
|
|
print('(src={}, dest={}, weight={}) '.format(v.get_key(), |
|
|
|
dest.get_key(), w)) |
|
|
|
print() |
|
|
|
|
|
|
|
elif operation == 'quit': |
|
|
|
break |