Last active
September 26, 2016 20:50
-
-
Save alexhwoods/cfa4197724a01580a68971ec25f6dbd9 to your computer and use it in GitHub Desktop.
Dijkstra's Algorithm (commented)
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
# python 3 only!!! | |
import collections | |
import math | |
class Graph: | |
''' graph class inspired by https://gist.github.com/econchick/4666413 | |
''' | |
def __init__(self): | |
self.vertices = set() | |
# makes the default value for all vertices an empty list | |
self.edges = collections.defaultdict(list) | |
self.weights = {} | |
def add_vertex(self, value): | |
self.vertices.add(value) | |
def add_edge(self, from_vertex, to_vertex, distance): | |
if from_vertex == to_vertex: pass # no cycles allowed | |
self.edges[from_vertex].append(to_vertex) | |
self.weights[(from_vertex, to_vertex)] = distance | |
def __str__(self): | |
string = "Vertices: " + str(self.vertices) + "\n" | |
string += "Edges: " + str(self.edges) + "\n" | |
string += "Weights: " + str(self.weights) | |
return string | |
def dijkstra(graph, start): | |
# initializations | |
S = set() | |
# delta represents the length shortest distance paths from start -> v, for v in delta. | |
# We initialize it so that every vertex has a path of infinity (this line will break if you run python 2) | |
delta = dict.fromkeys(list(graph.vertices), math.inf) | |
previous = dict.fromkeys(list(graph.vertices), None) | |
# then we set the path length of the start vertex to 0 | |
delta[start] = 0 | |
# while there exists a vertex v not in S | |
while S != graph.vertices: | |
# let v be the closest vertex that has not been visited...it will begin at 'start' | |
v = min((set(delta.keys()) - S), key=delta.get) | |
# for each neighbor of v not in S | |
for neighbor in set(graph.edges[v]) - S: | |
new_path = delta[v] + graph.weights[v,neighbor] | |
# is the new path from neighbor through | |
if new_path < delta[neighbor]: | |
# since it's optimal, update the shortest path for neighbor | |
delta[neighbor] = new_path | |
# set the previous vertex of neighbor to v | |
previous[neighbor] = v | |
S.add(v) | |
return (delta, previous) | |
def shortest_path(graph, start, end): | |
'''Uses dijkstra function in order to output the shortest path from start to end | |
''' | |
delta, previous = dijkstra(graph, start) | |
path = [] | |
vertex = end | |
while vertex is not None: | |
path.append(vertex) | |
vertex = previous[vertex] | |
path.reverse() | |
return path | |
# To run an example | |
# G = Graph() | |
# G.add_vertex('a') | |
# G.add_vertex('b') | |
# G.add_vertex('c') | |
# G.add_vertex('d') | |
# G.add_vertex('e') | |
# G.add_edge('a', 'b', 2) | |
# G.add_edge('a', 'c', 8) | |
# G.add_edge('a', 'd', 5) | |
# G.add_edge('b', 'c', 1) | |
# G.add_edge('c', 'e', 3) | |
# G.add_edge('d', 'e', 4) | |
# print(G) | |
# print(dijkstra(G, 'a')) | |
# print(shortest_path(G, 'a', 'e')) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment