-
-
Notifications
You must be signed in to change notification settings - Fork 48.7k
First Implementation of Johnson Graph Algorithm #12281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 14 commits
11bfe18
da0717b
18319a8
8286b58
346a955
e3db05b
a1ff5c9
5a87d4f
4982ff0
f80afa3
b8c6bea
f62921c
8006d48
1fca8c6
9a4e1d3
a00d41c
af534ad
14ddb93
32b9b8f
b911a55
6269fd6
8fc6818
debba8c
65f0d0c
bcf5bed
f9bf655
39fdc02
5fe9e9b
3d4acaa
2fb5bec
2584473
81fb07b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import heapq | ||
import sys | ||
|
||
|
||
# First implementation of johnson algorithm | ||
# Steps followed to implement this algorithm is given in the below link: | ||
# https://brilliant.org/wiki/johnsons-algorithm/ | ||
class JohnsonGraph: | ||
def __init__(self) -> None: | ||
self.edges: list[str] = [] | ||
self.graph: dict[str, int] = {} | ||
|
||
# add vertices for a graph | ||
def add_vertices(self, u) -> None: | ||
|
||
self.graph[u] = [] | ||
|
||
# assign weights for each edges formed of the directed graph | ||
def add_edge(self, u, v, w) -> None: | ||
|
||
self.edges.append((u, v, w)) | ||
self.graph[u].append((v, w)) | ||
|
||
# perform a dijkstra algorithm on a directed graph | ||
def dijkstra(self, s) -> dict: | ||
|
||
distances = {vertex: sys.maxsize - 1 for vertex in self.graph} | ||
pq = [(0, s)] | ||
distances[s] = 0 | ||
while pq: | ||
weight, v = heapq.heappop(pq) | ||
|
||
if weight > distances[v]: | ||
continue | ||
|
||
for node, w in self.graph[v]: | ||
if distances[v] + w < distances[node]: | ||
distances[node] = distances[v] + w | ||
heapq.heappush(pq, (distances[node], node)) | ||
return distances | ||
|
||
# carry out the bellman ford algorithm for a node and estimate its distance vector | ||
def bellman_ford(self, s) -> dict: | ||
|
||
distances = {vertex: sys.maxsize - 1 for vertex in self.graph} | ||
distances[s] = 0 | ||
|
||
for u in self.graph: | ||
for u, v, w in self.edges: | ||
if distances[u] != sys.maxsize - 1 and distances[u] + w < distances[v]: | ||
distances[v] = distances[u] + w | ||
|
||
return distances | ||
|
||
# perform the johnson algorithm to handle the negative weights that | ||
# could not be handled by either the dijkstra | ||
# or the bellman ford algorithm efficiently | ||
def johnson_algo(self) -> dict: | ||
|
||
self.add_vertices("#") | ||
for v in self.graph: | ||
if v != "#": | ||
self.add_edge("#", v, 0) | ||
|
||
n = self.bellman_ford("#") | ||
|
||
for i in range(len(self.edges)): | ||
u, v, weight = self.edges[i] | ||
self.edges[i] = (u, v, weight + n[u] - n[v]) | ||
|
||
self.graph.pop("#") | ||
self.edges = [(u, v, w) for u, v, w in self.edges if u != "#"] | ||
|
||
for u in self.graph: | ||
self.graph[u] = [(v, weight) for x, v, weight in self.edges if x == u] | ||
|
||
distances = [] | ||
for u in self.graph: | ||
new_dist = self.dijkstra(u) | ||
for v in self.graph: | ||
if new_dist[v] < sys.maxsize - 1: | ||
new_dist[v] += n[v] - n[u] | ||
distances.append(new_dist) | ||
return distances | ||
|
||
|
||
g = JohnsonGraph() | ||
# this a complete connected graph | ||
g.add_vertices("A") | ||
g.add_vertices("B") | ||
g.add_vertices("C") | ||
g.add_vertices("D") | ||
g.add_vertices("E") | ||
|
||
g.add_edge("A", "B", 1) | ||
g.add_edge("A", "C", 3) | ||
g.add_edge("B", "D", 4) | ||
g.add_edge("D", "E", 2) | ||
g.add_edge("E", "C", -2) | ||
|
||
|
||
optimal_paths = g.johnson_algo() | ||
print("Print all optimal paths of a graph using Johnson Algorithm") | ||
for i, row in enumerate(optimal_paths): | ||
print(f"{i}: {row}") |
Uh oh!
There was an error while loading. Please reload this page.