Repository where I mostly put random python scripts.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
3.9 KiB

  1. class Graph:
  2. def __init__(self):
  3. self.vertices = {}
  4. def add_vertex(self, key):
  5. vertex = Vertex(key)
  6. self.vertices[key] = vertex
  7. def get_vertex(self, key):
  8. return self.vertices[key]
  9. def __contains__(self, key):
  10. return key in self.vertices
  11. def add_edge(self, src_key, dest_key, weight=1):
  12. self.vertices[src_key].add_neighbour(self.vertices[dest_key], weight)
  13. def does_edge_exist(self, src_key, dest_key):
  14. return self.vertices[src_key].does_it_point_to(self.vertices[dest_key])
  15. def __len__(self):
  16. return len(self.vertices)
  17. def __iter__(self):
  18. return iter(self.vertices.values())
  19. class Vertex:
  20. def __init__(self, key):
  21. self.key = key
  22. self.points_to = {}
  23. def get_key(self):
  24. return self.key
  25. def add_neighbour(self, dest, weight):
  26. self.points_to[dest] = weight
  27. def get_neighbours(self):
  28. return self.points_to.keys()
  29. def get_weight(self, dest):
  30. return self.points_to[dest]
  31. def does_it_point_to(self, dest):
  32. return dest in self.points_to
  33. def floyd_warshall(g):
  34. distance = {v:dict.fromkeys(g, float('inf')) for v in g}
  35. next_v = {v:dict.fromkeys(g, None) for v in g}
  36. for v in g:
  37. for n in v.get_neighbours():
  38. distance[v][n] = v.get_weight(n)
  39. next_v[v][n] = n
  40. for v in g:
  41. distance[v][v] = 0
  42. next_v[v][v] = None
  43. for p in g:
  44. for v in g:
  45. for w in g:
  46. if distance[v][w] > distance[v][p] + distance[p][w]:
  47. distance[v][w] = distance[v][p] + distance[p][w]
  48. next_v[v][w] = next_v[v][p]
  49. return distance, next_v
  50. def print_path(next_v, u, v):
  51. p = u
  52. while (next_v[p][v]):
  53. print('{} -> '.format(p.get_key()), end='')
  54. p = next_v[p][v]
  55. print('{} '.format(v.get_key()), end='')
  56. g = Graph()
  57. print('Menu')
  58. print('add vertex <key>')
  59. print('add edge <src> <dest> <weight>')
  60. print('floyd-warshall')
  61. print('display')
  62. print('quit')
  63. while True:
  64. do = input('What would you like to do? ').split()
  65. operation = do[0]
  66. if operation == 'add':
  67. suboperation = do[1]
  68. if suboperation == 'vertex':
  69. key = int(do[2])
  70. if key not in g:
  71. g.add_vertex(key)
  72. else:
  73. print('Vertex already exists.')
  74. elif suboperation == 'edge':
  75. src = int(do[2])
  76. dest = int(do[3])
  77. weight = int(do[4])
  78. if src not in g:
  79. print('Vertex {} does not exist.'.format(src))
  80. elif dest not in g:
  81. print('Vertex {} does not exist.'.format(dest))
  82. else:
  83. if not g.does_edge_exist(src, dest):
  84. g.add_edge(src, dest, weight)
  85. else:
  86. print('Edge already exists.')
  87. elif operation == 'floyd-warshall':
  88. distance, next_v = floyd_warshall(g)
  89. print('Shortest distances:')
  90. for start in g:
  91. for end in g:
  92. if next_v[start][end]:
  93. print('From {} to {}: '.format(start.get_key(),
  94. end.get_key()),
  95. end = '')
  96. print_path(next_v, start, end)
  97. print('(distance {})'.format(distance[start][end]))
  98. elif operation == 'display':
  99. print('Vertices: ', end='')
  100. for v in g:
  101. print(v.get_key(), end=' ')
  102. print()
  103. print('Edges: ')
  104. for v in g:
  105. for dest in v.get_neighbours():
  106. w = v.get_weight(dest)
  107. print('(src={}, dest={}, weight={}) '.format(v.get_key(),
  108. dest.get_key(), w))
  109. print()
  110. elif operation == 'quit':
  111. break