-
-
Save iklobato/cf3b0c0cac08db5dce05044db178ea73 to your computer and use it in GitHub Desktop.
Python implementation of dijkstra algorithm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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