Skip to content

Instantly share code, notes, and snippets.

@iklobato
Forked from mdiener21/dikstra_graph.py
Last active December 13, 2019 22:04
Show Gist options
  • Save iklobato/cf3b0c0cac08db5dce05044db178ea73 to your computer and use it in GitHub Desktop.
Save iklobato/cf3b0c0cac08db5dce05044db178ea73 to your computer and use it in GitHub Desktop.
Python implementation of dijkstra algorithm
# source: https://dev.to/mariamxl
# https://dev.to/mariamxl/dijkstras-algorithm-in-python-algorithms-for-beginners-dkc
from collections import deque, namedtuple
inf = float('inf')
Edge = namedtuple('Edge', 'start, end, cost')
def make_edge(start, end, cost=1):
return Edge(start, end, cost)
class Graph:
def __init__(self, edges):
self.nodes = []
self.edges = edges
temp_edge = []
for a,b in edges:
temp_edge.append((a,b))
temp_edge.append((b,a))
wrong_edges = [i for i in temp_edge if len(i) not in [2, 3]]
if wrong_edges:
raise ValueError('Wrong edges data: {}'.format(wrong_edges))
self.edges = [make_edge(*edge) for edge in temp_edge]
def get_graph_nodes(self):
# nodes_list = [{'id':i, 'label':edge[0]} for i,edge in enumerate(self.edges)]
nodes_list = []
root_node = True
for i,edge in enumerate(self.edges):
put_on_list = True
for j in nodes_list:
if edge[0] == j['label']:
put_on_list = False
break
if put_on_list:
# TODO busca tipo equipamento no banco para inserção da imagem
if root_node:
nodes_list.append({'id':i, 'label':edge[0], 'image':'/media/images/router.png', 'shape': 'image'})
root_node = False
else:
nodes_list.append({'id':i, 'label':edge[0]})
self.nodes = nodes_list[:]
return nodes_list
def get_graph_edges(self):
temp_list = []
for start,end,cost in self.edges:
id_start = self.get_id_by_label(start)
id_end = self.get_id_by_label(end)
temp_list.append({'from':id_start, 'to':id_end})
return temp_list
def get_id_by_label(self,label):
for i in self.nodes:
if i['label'] == label:
return i['id']
def get_label_by_id(self, id):
for i in self.nodes:
if i['id'] == label:
return i['label']
@property
def vertices(self):
return set(
sum(
([edge.start, edge.end] for edge in self.edges), []
)
)
def get_node_pairs(self, n1, n2, both_ends=True):
if both_ends:
node_pairs = [[n1, n2], [n2, n1]]
else:
node_pairs = [[n1, n2]]
return node_pairs
def remove_edge(self, n1, n2, both_ends=True):
node_pairs = self.get_node_pairs(n1, n2, both_ends)
edges = self.edges[:]
for edge in edges:
if [edge.start, edge.end] in node_pairs:
self.edges.remove(edge)
def add_edge(self, n1, n2, cost=1, both_ends=True):
node_pairs = self.get_node_pairs(n1, n2, both_ends)
for edge in self.edges:
if [edge.start, edge.end] in node_pairs:
return ValueError('Edge {} {} already exists'.format(n1, n2))
self.edges.append(Edge(start=n1, end=n2, cost=cost))
if both_ends:
self.edges.append(Edge(start=n2, end=n1, cost=cost))
@property
def neighbours(self):
neighbours = {vertex: set() for vertex in self.vertices}
for edge in self.edges:
neighbours[edge.start].add((edge.end, edge.cost))
return neighbours
def dijkstra(self, source, dest):
assert source in self.vertices, 'Such source node doesn\'t exist'
distances = {vertex: inf for vertex in self.vertices}
previous_vertices = {
vertex: None for vertex in self.vertices
}
distances[source] = 0
vertices = self.vertices.copy()
while vertices:
current_vertex = min(
vertices, key=lambda vertex: distances[vertex])
vertices.remove(current_vertex)
if distances[current_vertex] == inf:
break
for neighbour, cost in self.neighbours[current_vertex]:
alternative_route = distances[current_vertex] + cost
if alternative_route < distances[neighbour]:
distances[neighbour] = alternative_route
previous_vertices[neighbour] = current_vertex
path, current_vertex = deque(), dest
while previous_vertices[current_vertex] is not None:
path.appendleft(current_vertex)
current_vertex = previous_vertices[current_vertex]
if path:
path.appendleft(current_vertex)
return path
if __name__ == '__main__':
graph_rede2 = Graph([
('a','c'),('a','d'),('b','d'),
('c','e'),('c','f'),('d','m'),('d','g'),('d','h'),('d','i'),
('e','j'),('e','k'),('f','l'),('f','m'),('g','n'),('h','n'),('h','o'),('i','p'),
('k','q'),('k','r'),('l','z'),('m','s'),('m','t'),('m','u'),('n','u'),('n','v'),('n','x'),('o','w'),('o','y'),
])
print(graph_rede2.dijkstra('a', 'g'))
graph_rede2.get_nodes()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment