From e50b9758cf683103851dbc032f874c8bdb8a7dbd Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Tue, 18 Oct 2022 22:33:54 +0530 Subject: [PATCH 01/17] Update dijkstra.py --- graphs/dijkstra.py | 179 +++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 118 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index b0bdfab60649..effb259b8e6b 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -1,118 +1,61 @@ -""" -pseudo-code - -DIJKSTRA(graph G, start vertex s, destination vertex d): - -//all nodes initially unexplored - -1 - let H = min heap data structure, initialized with 0 and s [here 0 indicates - the distance from start vertex s] -2 - while H is non-empty: -3 - remove the first node and cost of H, call it U and cost -4 - if U has been previously explored: -5 - go to the while loop, line 2 //Once a node is explored there is no need - to make it again -6 - mark U as explored -7 - if U is d: -8 - return cost // total cost from start to destination vertex -9 - for each edge(U, V): c=cost of edge(U,V) // for V in graph[U] -10 - if V explored: -11 - go to next V in line 9 -12 - total_cost = cost + c -13 - add (total_cost,V) to H - -You can think at cost as a distance where Dijkstra finds the shortest distance -between vertices s and v in a graph G. The use of a min heap as H guarantees -that if a vertex has already been explored there will be no other path with -shortest distance, that happens because heapq.heappop will always return the -next vertex with the shortest distance, considering that the heap stores not -only the distance between previous vertex and current vertex but the entire -distance between each vertex that makes up the path from start vertex to target -vertex. -""" -import heapq - - -def dijkstra(graph, start, end): - """Return the cost of the shortest path between vertices start and end. - - >>> dijkstra(G, "E", "C") - 6 - >>> dijkstra(G2, "E", "F") - 3 - >>> dijkstra(G3, "E", "F") - 3 - """ - - heap = [(0, start)] # cost from start node,end node - visited = set() - while heap: - (cost, u) = heapq.heappop(heap) - if u in visited: - continue - visited.add(u) - if u == end: - return cost - for v, c in graph[u]: - if v in visited: - continue - next_item = cost + c - heapq.heappush(heap, (next_item, v)) - return -1 - - -G = { - "A": [["B", 2], ["C", 5]], - "B": [["A", 2], ["D", 3], ["E", 1], ["F", 1]], - "C": [["A", 5], ["F", 3]], - "D": [["B", 3]], - "E": [["B", 4], ["F", 3]], - "F": [["C", 3], ["E", 3]], -} - -r""" -Layout of G2: - -E -- 1 --> B -- 1 --> C -- 1 --> D -- 1 --> F - \ /\ - \ || - ----------------- 3 -------------------- -""" -G2 = { - "B": [["C", 1]], - "C": [["D", 1]], - "D": [["F", 1]], - "E": [["B", 1], ["F", 3]], - "F": [], -} - -r""" -Layout of G3: - -E -- 1 --> B -- 1 --> C -- 1 --> D -- 1 --> F - \ /\ - \ || - -------- 2 ---------> G ------- 1 ------ -""" -G3 = { - "B": [["C", 1]], - "C": [["D", 1]], - "D": [["F", 1]], - "E": [["B", 1], ["G", 2]], - "F": [], - "G": [["F", 1]], -} - -short_distance = dijkstra(G, "E", "C") -print(short_distance) # E -- 3 --> F -- 3 --> C == 6 - -short_distance = dijkstra(G2, "E", "F") -print(short_distance) # E -- 3 --> F == 3 - -short_distance = dijkstra(G3, "E", "F") -print(short_distance) # E -- 2 --> G -- 1 --> F == 3 - -if __name__ == "__main__": - import doctest - - doctest.testmod() +class Graph(): + + def __init__(self, vertices): + self.V = vertices + self.graph = [[0 for column in range(vertices)] + for row in range(vertices)] + + def printSolution(self, dist): + print("Vertex \t Distance from Source") + for node in range(self.V): + print(node, "\t\t", dist[node]) + + + def minDistance(self, dist, sptSet): + + + min = 1e7 + + + for v in range(self.V): + if dist[v] < min and sptSet[v] == False: + min = dist[v] + min_index = v + + return min_index + + def dijkstra(self, src): + + dist = [1e7] * self.V + dist[src] = 0 + sptSet = [False] * self.V + + for cout in range(self.V): + + u = self.minDistance(dist, sptSet) + sptSet[u] = True + + for v in range(self.V): + if (self.graph[u][v] > 0 and + sptSet[v] == False and + dist[v] > dist[u] + self.graph[u][v]): + dist[v] = dist[u] + self.graph[u][v] + + self.printSolution(dist) + +# Driver program +g = Graph(9) +g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0] + ] + +g.dijkstra(0) + + From 74c2f7990d816c698f7faa95cd17e6fac97c0a5b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 17:05:38 +0000 Subject: [PATCH 02/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/dijkstra.py | 85 ++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index effb259b8e6b..8bb4e423b454 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -1,61 +1,58 @@ -class Graph(): +class Graph: + def __init__(self, vertices): + self.V = vertices + self.graph = [[0 for column in range(vertices)] for row in range(vertices)] - def __init__(self, vertices): - self.V = vertices - self.graph = [[0 for column in range(vertices)] - for row in range(vertices)] + def printSolution(self, dist): + print("Vertex \t Distance from Source") + for node in range(self.V): + print(node, "\t\t", dist[node]) - def printSolution(self, dist): - print("Vertex \t Distance from Source") - for node in range(self.V): - print(node, "\t\t", dist[node]) + def minDistance(self, dist, sptSet): + min = 1e7 - def minDistance(self, dist, sptSet): + for v in range(self.V): + if dist[v] < min and sptSet[v] == False: + min = dist[v] + min_index = v - - min = 1e7 + return min_index - - for v in range(self.V): - if dist[v] < min and sptSet[v] == False: - min = dist[v] - min_index = v + def dijkstra(self, src): - return min_index + dist = [1e7] * self.V + dist[src] = 0 + sptSet = [False] * self.V - def dijkstra(self, src): + for cout in range(self.V): - dist = [1e7] * self.V - dist[src] = 0 - sptSet = [False] * self.V + u = self.minDistance(dist, sptSet) + sptSet[u] = True - for cout in range(self.V): + for v in range(self.V): + if ( + self.graph[u][v] > 0 + and sptSet[v] == False + and dist[v] > dist[u] + self.graph[u][v] + ): + dist[v] = dist[u] + self.graph[u][v] - u = self.minDistance(dist, sptSet) - sptSet[u] = True + self.printSolution(dist) - for v in range(self.V): - if (self.graph[u][v] > 0 and - sptSet[v] == False and - dist[v] > dist[u] + self.graph[u][v]): - dist[v] = dist[u] + self.graph[u][v] - - self.printSolution(dist) # Driver program g = Graph(9) -g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], - [4, 0, 8, 0, 0, 0, 0, 11, 0], - [0, 8, 0, 7, 0, 4, 0, 0, 2], - [0, 0, 7, 0, 9, 14, 0, 0, 0], - [0, 0, 0, 9, 0, 10, 0, 0, 0], - [0, 0, 4, 14, 10, 0, 2, 0, 0], - [0, 0, 0, 0, 0, 2, 0, 1, 6], - [8, 11, 0, 0, 0, 0, 1, 0, 7], - [0, 0, 2, 0, 0, 0, 6, 7, 0] - ] +g.graph = [ + [0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0], +] g.dijkstra(0) - - From 0a17d6a4a8fce54bcac91b881018cbe2ac5f4dab Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:34:05 +0530 Subject: [PATCH 03/17] Update dijkstra.py --- graphs/dijkstra.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 8bb4e423b454..846cb4d27fed 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -3,18 +3,18 @@ def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] - def printSolution(self, dist): + def printsolution(self, dist): print("Vertex \t Distance from Source") for node in range(self.V): print(node, "\t\t", dist[node]) - def minDistance(self, dist, sptSet): + def mindistance(self, dist, sptSet): - min = 1e7 + minm = 1e7 for v in range(self.V): - if dist[v] < min and sptSet[v] == False: - min = dist[v] + if dist[v] < minm and sptSet[v] == False: + minm = dist[v] min_index = v return min_index @@ -23,22 +23,22 @@ def dijkstra(self, src): dist = [1e7] * self.V dist[src] = 0 - sptSet = [False] * self.V + sptset = [False] * self.V for cout in range(self.V): - u = self.minDistance(dist, sptSet) - sptSet[u] = True + u = self.mindistance(dist, sptset) + sptset[u] = True for v in range(self.V): if ( self.graph[u][v] > 0 - and sptSet[v] == False + and sptset[v] == False and dist[v] > dist[u] + self.graph[u][v] ): dist[v] = dist[u] + self.graph[u][v] - self.printSolution(dist) + self.printsolution(dist) # Driver program From 52ae3d6c15accc64b6bb7152584a74df6468b26e Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Thu, 20 Oct 2022 00:08:30 +0530 Subject: [PATCH 04/17] Update graphs/dijkstra.py Co-authored-by: Christian Clauss --- graphs/dijkstra.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 846cb4d27fed..0546b6b3482a 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -8,7 +8,7 @@ def printsolution(self, dist): for node in range(self.V): print(node, "\t\t", dist[node]) - def mindistance(self, dist, sptSet): + def minimum_distance(self, distances, spt_set) -> int: minm = 1e7 From 60886b5d6d439ed04d3df3c475b132f0f4a784fe Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Thu, 20 Oct 2022 00:08:39 +0530 Subject: [PATCH 05/17] Update graphs/dijkstra.py Co-authored-by: Christian Clauss --- graphs/dijkstra.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 0546b6b3482a..95edb30ede71 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -1,7 +1,7 @@ class Graph: def __init__(self, vertices): self.V = vertices - self.graph = [[0 for column in range(vertices)] for row in range(vertices)] + self.graph = [[0] * vertices for row in range(vertices)] def printsolution(self, dist): print("Vertex \t Distance from Source") From 1a5eff0b48c53c0ae17f27c8b69b67ff013203d6 Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Thu, 20 Oct 2022 00:08:51 +0530 Subject: [PATCH 06/17] Update graphs/dijkstra.py Co-authored-by: Christian Clauss --- graphs/dijkstra.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 95edb30ede71..723ae08f9103 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -3,7 +3,7 @@ def __init__(self, vertices): self.V = vertices self.graph = [[0] * vertices for row in range(vertices)] - def printsolution(self, dist): + def print_solution(self, distances: list[int]): print("Vertex \t Distance from Source") for node in range(self.V): print(node, "\t\t", dist[node]) From 3f2b017eaa8440a6dddb41d99c4440063e3a2dd2 Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Thu, 20 Oct 2022 01:52:48 +0530 Subject: [PATCH 07/17] Update dijkstra.py --- graphs/dijkstra.py | 99 +++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 723ae08f9103..9f84bd3cc5b0 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -1,58 +1,75 @@ -class Graph: - def __init__(self, vertices): - self.V = vertices - self.graph = [[0] * vertices for row in range(vertices)] +class Graph(): - def print_solution(self, distances: list[int]): - print("Vertex \t Distance from Source") - for node in range(self.V): - print(node, "\t\t", dist[node]) + def __init__(self, vertices): + self.V = vertices + self.graph = [[0 for column in range(vertices)] + for row in range(vertices)] - def minimum_distance(self, distances, spt_set) -> int: + def printsolution(self, dist): + print("Vertex \t Distance from Source") + for node in range(self.V): + print(node, "\t\t", dist[node]) - minm = 1e7 + # A utility function to find the vertex with + # minimum distance value, from the set of vertices + # not yet included in shortest path tree + def mindistance(self, dist, sptset): - for v in range(self.V): - if dist[v] < minm and sptSet[v] == False: - minm = dist[v] - min_index = v + # Initialize minimum distance for next node + minimum = 1e7 - return min_index + # Search not nearest vertex not in the + # shortest path tree + for v in range(self.V): + if dist[v] < minimum and sptset[v] == False: + minimum = dist[v] + min_index = v - def dijkstra(self, src): + return min_index - dist = [1e7] * self.V - dist[src] = 0 - sptset = [False] * self.V + # Function that implements Dijkstra's single source + # shortest path algorithm for a graph represented + # using adjacency matrix representation + def dijkstra(self, src): - for cout in range(self.V): + dist = [1e7] * self.V + dist[src] = 0 + sptset = [False] * self.V - u = self.mindistance(dist, sptset) - sptset[u] = True + for cout in range(self.V): - for v in range(self.V): - if ( - self.graph[u][v] > 0 - and sptset[v] == False - and dist[v] > dist[u] + self.graph[u][v] - ): - dist[v] = dist[u] + self.graph[u][v] + # Pick the minimum distance vertex from + # the set of vertices not yet processed. + # u is always equal to src in first iteration + u = self.mindistance(dist, sptset) - self.printsolution(dist) + # Put the minimum distance vertex in the + # shortest path tree + sptset[u] = True + # Update dist value of the adjacent vertices + # of the picked vertex only if the current + # distance is greater than new distance and + # the vertex in not in the shortest path tree + for v in range(self.V): + if (self.graph[u][v] > 0 and + sptset[v] == False and + dist[v] > dist[u] + self.graph[u][v]): + dist[v] = dist[u] + self.graph[u][v] + + self.printsolution(dist) # Driver program g = Graph(9) -g.graph = [ - [0, 4, 0, 0, 0, 0, 0, 8, 0], - [4, 0, 8, 0, 0, 0, 0, 11, 0], - [0, 8, 0, 7, 0, 4, 0, 0, 2], - [0, 0, 7, 0, 9, 14, 0, 0, 0], - [0, 0, 0, 9, 0, 10, 0, 0, 0], - [0, 0, 4, 14, 10, 0, 2, 0, 0], - [0, 0, 0, 0, 0, 2, 0, 1, 6], - [8, 11, 0, 0, 0, 0, 1, 0, 7], - [0, 0, 2, 0, 0, 0, 6, 7, 0], -] +g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0] + ] g.dijkstra(0) From d3dc21c0d10861c24373a09d266562cd7cc4ca24 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 20:23:46 +0000 Subject: [PATCH 08/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/dijkstra.py | 116 +++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 9f84bd3cc5b0..fc041ce540af 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -1,75 +1,77 @@ -class Graph(): +class Graph: + def __init__(self, vertices): + self.V = vertices + self.graph = [[0 for column in range(vertices)] for row in range(vertices)] - def __init__(self, vertices): - self.V = vertices - self.graph = [[0 for column in range(vertices)] - for row in range(vertices)] + def printsolution(self, dist): + print("Vertex \t Distance from Source") + for node in range(self.V): + print(node, "\t\t", dist[node]) - def printsolution(self, dist): - print("Vertex \t Distance from Source") - for node in range(self.V): - print(node, "\t\t", dist[node]) + # A utility function to find the vertex with + # minimum distance value, from the set of vertices + # not yet included in shortest path tree + def mindistance(self, dist, sptset): - # A utility function to find the vertex with - # minimum distance value, from the set of vertices - # not yet included in shortest path tree - def mindistance(self, dist, sptset): + # Initialize minimum distance for next node + minimum = 1e7 - # Initialize minimum distance for next node - minimum = 1e7 + # Search not nearest vertex not in the + # shortest path tree + for v in range(self.V): + if dist[v] < minimum and sptset[v] == False: + minimum = dist[v] + min_index = v - # Search not nearest vertex not in the - # shortest path tree - for v in range(self.V): - if dist[v] < minimum and sptset[v] == False: - minimum = dist[v] - min_index = v + return min_index - return min_index + # Function that implements Dijkstra's single source + # shortest path algorithm for a graph represented + # using adjacency matrix representation + def dijkstra(self, src): - # Function that implements Dijkstra's single source - # shortest path algorithm for a graph represented - # using adjacency matrix representation - def dijkstra(self, src): + dist = [1e7] * self.V + dist[src] = 0 + sptset = [False] * self.V - dist = [1e7] * self.V - dist[src] = 0 - sptset = [False] * self.V + for cout in range(self.V): - for cout in range(self.V): + # Pick the minimum distance vertex from + # the set of vertices not yet processed. + # u is always equal to src in first iteration + u = self.mindistance(dist, sptset) - # Pick the minimum distance vertex from - # the set of vertices not yet processed. - # u is always equal to src in first iteration - u = self.mindistance(dist, sptset) + # Put the minimum distance vertex in the + # shortest path tree + sptset[u] = True - # Put the minimum distance vertex in the - # shortest path tree - sptset[u] = True + # Update dist value of the adjacent vertices + # of the picked vertex only if the current + # distance is greater than new distance and + # the vertex in not in the shortest path tree + for v in range(self.V): + if ( + self.graph[u][v] > 0 + and sptset[v] == False + and dist[v] > dist[u] + self.graph[u][v] + ): + dist[v] = dist[u] + self.graph[u][v] - # Update dist value of the adjacent vertices - # of the picked vertex only if the current - # distance is greater than new distance and - # the vertex in not in the shortest path tree - for v in range(self.V): - if (self.graph[u][v] > 0 and - sptset[v] == False and - dist[v] > dist[u] + self.graph[u][v]): - dist[v] = dist[u] + self.graph[u][v] + self.printsolution(dist) - self.printsolution(dist) # Driver program g = Graph(9) -g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], - [4, 0, 8, 0, 0, 0, 0, 11, 0], - [0, 8, 0, 7, 0, 4, 0, 0, 2], - [0, 0, 7, 0, 9, 14, 0, 0, 0], - [0, 0, 0, 9, 0, 10, 0, 0, 0], - [0, 0, 4, 14, 10, 0, 2, 0, 0], - [0, 0, 0, 0, 0, 2, 0, 1, 6], - [8, 11, 0, 0, 0, 0, 1, 0, 7], - [0, 0, 2, 0, 0, 0, 6, 7, 0] - ] +g.graph = [ + [0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0], +] g.dijkstra(0) From 0b28bf972570efff61da8aa41dd2b992ed975559 Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Thu, 20 Oct 2022 02:12:58 +0530 Subject: [PATCH 09/17] Update dijkstra.py --- graphs/dijkstra.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index fc041ce540af..65938090efbd 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -35,14 +35,7 @@ def dijkstra(self, src): sptset = [False] * self.V for cout in range(self.V): - - # Pick the minimum distance vertex from - # the set of vertices not yet processed. - # u is always equal to src in first iteration u = self.mindistance(dist, sptset) - - # Put the minimum distance vertex in the - # shortest path tree sptset[u] = True # Update dist value of the adjacent vertices From 1efce832d181fe19ea93ebcd33a909f4aab703ec Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 19 Oct 2022 22:48:17 +0200 Subject: [PATCH 10/17] Apply suggestions from code review --- graphs/dijkstra.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 65938090efbd..b825e79a10d7 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -19,7 +19,7 @@ def mindistance(self, dist, sptset): # Search not nearest vertex not in the # shortest path tree for v in range(self.V): - if dist[v] < minimum and sptset[v] == False: + if dist[v] < minimum and sptset[v] is False: minimum = dist[v] min_index = v @@ -34,7 +34,7 @@ def dijkstra(self, src): dist[src] = 0 sptset = [False] * self.V - for cout in range(self.V): + for _ in range(self.V): u = self.mindistance(dist, sptset) sptset[u] = True @@ -45,7 +45,7 @@ def dijkstra(self, src): for v in range(self.V): if ( self.graph[u][v] > 0 - and sptset[v] == False + and sptset[v] is False and dist[v] > dist[u] + self.graph[u][v] ): dist[v] = dist[u] + self.graph[u][v] From f7c813900b6d03e03053abfaaebe2c0d2d6678be Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 19 Oct 2022 23:52:07 +0200 Subject: [PATCH 11/17] Create dijkstra_alternate.py --- graphs/dijkstra_alternate.py | 100 +++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 graphs/dijkstra_alternate.py diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py new file mode 100644 index 000000000000..ac40875f224e --- /dev/null +++ b/graphs/dijkstra_alternate.py @@ -0,0 +1,100 @@ +from __future__ import annotations + + +class Graph: + def __init__(self, vertices: int) -> None: + """ + >>> graph = Graph(2) + >>> graph.vertices + 2 + >>> len(graph.graph) + 2 + >>> len(graph.graph[0]) + 2 + """ + self.vertices = vertices + self.graph = [[0] * vertices for _ in range(vertices)] + + def print_solution(self, distances_from_source: list[int]) -> None: + """ + >>> graph = Graph(0) + >>> graph.print_solution([]) # doctest: +NORMALIZE_WHITESPACE + Vertex Distance from Source + """ + print("Vertex \t Distance from Source") + for vertex in range(self.vertices): + print(vertex, "\t\t", distances_from_source[vertex]) + + def minimum_distance(self, distances_from_source: list[int], sptset: list[bool]) -> int: + """ + A utility function to find the vertex with minimum distance value, from the set + of vertices not yet included in shortest path tree. + + >>> graph = Graph(3) + >>> graph.minimum_distance([1, 2, 3], [False, False, True]) + 0 + """ + + # Initialize minimum distance for next node + minimum = 1e7 + min_index = 0 + + # Search not nearest vertex not in the shortest path tree + for vertex in range(self.vertices): + if distances_from_source[vertex] < minimum and sptset[vertex] is False: + minimum = distances_from_source[vertex] + min_index = vertex + return min_index + + def dijkstra(self, source: int) -> None: + """ + Function that implements Dijkstra's single source shortest path algorithm for a + graph represented using adjacency matrix representation. + + >>> graph = Graph(4) + >>> graph.dijkstra(1) # doctest: +NORMALIZE_WHITESPACE + Vertex Distance from Source + 0 10000000.0 + 1 0 + 2 10000000.0 + 3 10000000.0 + """ + + distances = [1e7] * self.vertices # distances from the source + distances[source] = 0 + sptset = [False] * self.vertices + + for _ in range(self.vertices): + u = self.minimum_distance(distances, sptset) + sptset[u] = True + + # Update dist value of the adjacent vertices + # of the picked vertex only if the current + # distance is greater than new distance and + # the vertex in not in the shortest path tree + for v in range(self.vertices): + if ( + self.graph[u][v] > 0 + and sptset[v] is False + and distances[v] > distances[u] + self.graph[u][v] + ): + distances[v] = distances[u] + self.graph[u][v] + + self.print_solution(distances) + + +# Driver program +g = Graph(9) +g.graph = [ + [0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0], +] + +g.dijkstra(0) From ce2e683e35866db8bf0b178a6cbc5ce720892b63 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 19 Oct 2022 23:53:07 +0200 Subject: [PATCH 12/17] Update dijkstra.py --- graphs/dijkstra.py | 188 ++++++++++++++++++++++++++++----------------- 1 file changed, 118 insertions(+), 70 deletions(-) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index b825e79a10d7..b0bdfab60649 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -1,70 +1,118 @@ -class Graph: - def __init__(self, vertices): - self.V = vertices - self.graph = [[0 for column in range(vertices)] for row in range(vertices)] - - def printsolution(self, dist): - print("Vertex \t Distance from Source") - for node in range(self.V): - print(node, "\t\t", dist[node]) - - # A utility function to find the vertex with - # minimum distance value, from the set of vertices - # not yet included in shortest path tree - def mindistance(self, dist, sptset): - - # Initialize minimum distance for next node - minimum = 1e7 - - # Search not nearest vertex not in the - # shortest path tree - for v in range(self.V): - if dist[v] < minimum and sptset[v] is False: - minimum = dist[v] - min_index = v - - return min_index - - # Function that implements Dijkstra's single source - # shortest path algorithm for a graph represented - # using adjacency matrix representation - def dijkstra(self, src): - - dist = [1e7] * self.V - dist[src] = 0 - sptset = [False] * self.V - - for _ in range(self.V): - u = self.mindistance(dist, sptset) - sptset[u] = True - - # Update dist value of the adjacent vertices - # of the picked vertex only if the current - # distance is greater than new distance and - # the vertex in not in the shortest path tree - for v in range(self.V): - if ( - self.graph[u][v] > 0 - and sptset[v] is False - and dist[v] > dist[u] + self.graph[u][v] - ): - dist[v] = dist[u] + self.graph[u][v] - - self.printsolution(dist) - - -# Driver program -g = Graph(9) -g.graph = [ - [0, 4, 0, 0, 0, 0, 0, 8, 0], - [4, 0, 8, 0, 0, 0, 0, 11, 0], - [0, 8, 0, 7, 0, 4, 0, 0, 2], - [0, 0, 7, 0, 9, 14, 0, 0, 0], - [0, 0, 0, 9, 0, 10, 0, 0, 0], - [0, 0, 4, 14, 10, 0, 2, 0, 0], - [0, 0, 0, 0, 0, 2, 0, 1, 6], - [8, 11, 0, 0, 0, 0, 1, 0, 7], - [0, 0, 2, 0, 0, 0, 6, 7, 0], -] - -g.dijkstra(0) +""" +pseudo-code + +DIJKSTRA(graph G, start vertex s, destination vertex d): + +//all nodes initially unexplored + +1 - let H = min heap data structure, initialized with 0 and s [here 0 indicates + the distance from start vertex s] +2 - while H is non-empty: +3 - remove the first node and cost of H, call it U and cost +4 - if U has been previously explored: +5 - go to the while loop, line 2 //Once a node is explored there is no need + to make it again +6 - mark U as explored +7 - if U is d: +8 - return cost // total cost from start to destination vertex +9 - for each edge(U, V): c=cost of edge(U,V) // for V in graph[U] +10 - if V explored: +11 - go to next V in line 9 +12 - total_cost = cost + c +13 - add (total_cost,V) to H + +You can think at cost as a distance where Dijkstra finds the shortest distance +between vertices s and v in a graph G. The use of a min heap as H guarantees +that if a vertex has already been explored there will be no other path with +shortest distance, that happens because heapq.heappop will always return the +next vertex with the shortest distance, considering that the heap stores not +only the distance between previous vertex and current vertex but the entire +distance between each vertex that makes up the path from start vertex to target +vertex. +""" +import heapq + + +def dijkstra(graph, start, end): + """Return the cost of the shortest path between vertices start and end. + + >>> dijkstra(G, "E", "C") + 6 + >>> dijkstra(G2, "E", "F") + 3 + >>> dijkstra(G3, "E", "F") + 3 + """ + + heap = [(0, start)] # cost from start node,end node + visited = set() + while heap: + (cost, u) = heapq.heappop(heap) + if u in visited: + continue + visited.add(u) + if u == end: + return cost + for v, c in graph[u]: + if v in visited: + continue + next_item = cost + c + heapq.heappush(heap, (next_item, v)) + return -1 + + +G = { + "A": [["B", 2], ["C", 5]], + "B": [["A", 2], ["D", 3], ["E", 1], ["F", 1]], + "C": [["A", 5], ["F", 3]], + "D": [["B", 3]], + "E": [["B", 4], ["F", 3]], + "F": [["C", 3], ["E", 3]], +} + +r""" +Layout of G2: + +E -- 1 --> B -- 1 --> C -- 1 --> D -- 1 --> F + \ /\ + \ || + ----------------- 3 -------------------- +""" +G2 = { + "B": [["C", 1]], + "C": [["D", 1]], + "D": [["F", 1]], + "E": [["B", 1], ["F", 3]], + "F": [], +} + +r""" +Layout of G3: + +E -- 1 --> B -- 1 --> C -- 1 --> D -- 1 --> F + \ /\ + \ || + -------- 2 ---------> G ------- 1 ------ +""" +G3 = { + "B": [["C", 1]], + "C": [["D", 1]], + "D": [["F", 1]], + "E": [["B", 1], ["G", 2]], + "F": [], + "G": [["F", 1]], +} + +short_distance = dijkstra(G, "E", "C") +print(short_distance) # E -- 3 --> F -- 3 --> C == 6 + +short_distance = dijkstra(G2, "E", "F") +print(short_distance) # E -- 3 --> F == 3 + +short_distance = dijkstra(G3, "E", "F") +print(short_distance) # E -- 2 --> G -- 1 --> F == 3 + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 2e26c751193d8a5544a3694ba0920fea14d51d26 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 21:53:56 +0000 Subject: [PATCH 13/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/dijkstra_alternate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py index ac40875f224e..bbdb45e0148f 100644 --- a/graphs/dijkstra_alternate.py +++ b/graphs/dijkstra_alternate.py @@ -25,7 +25,9 @@ def print_solution(self, distances_from_source: list[int]) -> None: for vertex in range(self.vertices): print(vertex, "\t\t", distances_from_source[vertex]) - def minimum_distance(self, distances_from_source: list[int], sptset: list[bool]) -> int: + def minimum_distance( + self, distances_from_source: list[int], sptset: list[bool] + ) -> int: """ A utility function to find the vertex with minimum distance value, from the set of vertices not yet included in shortest path tree. From 47d405c5ffc408b7f382653d1d26e8f8e720341b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 19 Oct 2022 23:57:47 +0200 Subject: [PATCH 14/17] int(1e7) --- graphs/dijkstra_alternate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py index bbdb45e0148f..b2cd6e590040 100644 --- a/graphs/dijkstra_alternate.py +++ b/graphs/dijkstra_alternate.py @@ -62,7 +62,7 @@ def dijkstra(self, source: int) -> None: 3 10000000.0 """ - distances = [1e7] * self.vertices # distances from the source + distances = [int(1e7)] * self.vertices # distances from the source distances[source] = 0 sptset = [False] * self.vertices From 8890161b06fc4265e02b6cb3261fc636aa2cd5bf Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 20 Oct 2022 00:05:44 +0200 Subject: [PATCH 15/17] Update dijkstra_alternate.py --- graphs/dijkstra_alternate.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py index b2cd6e590040..7c252a83ea85 100644 --- a/graphs/dijkstra_alternate.py +++ b/graphs/dijkstra_alternate.py @@ -17,8 +17,7 @@ def __init__(self, vertices: int) -> None: def print_solution(self, distances_from_source: list[int]) -> None: """ - >>> graph = Graph(0) - >>> graph.print_solution([]) # doctest: +NORMALIZE_WHITESPACE + >>> Graph(0).print_solution([]) # doctest: +NORMALIZE_WHITESPACE Vertex Distance from Source """ print("Vertex \t Distance from Source") @@ -32,8 +31,7 @@ def minimum_distance( A utility function to find the vertex with minimum distance value, from the set of vertices not yet included in shortest path tree. - >>> graph = Graph(3) - >>> graph.minimum_distance([1, 2, 3], [False, False, True]) + >>> Graph(3).minimum_distance([1, 2, 3], [False, False, True]) 0 """ @@ -53,13 +51,12 @@ def dijkstra(self, source: int) -> None: Function that implements Dijkstra's single source shortest path algorithm for a graph represented using adjacency matrix representation. - >>> graph = Graph(4) - >>> graph.dijkstra(1) # doctest: +NORMALIZE_WHITESPACE + >>> Graph(4).dijkstra(1) # doctest: +NORMALIZE_WHITESPACE Vertex Distance from Source - 0 10000000.0 + 0 10000000 1 0 - 2 10000000.0 - 3 10000000.0 + 2 10000000 + 3 10000000 """ distances = [int(1e7)] * self.vertices # distances from the source From 78ab169fffa4aa74f9e5cef1b5582e714d7ab199 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 20 Oct 2022 00:13:10 +0200 Subject: [PATCH 16/17] Update graphs/dijkstra_alternate.py --- graphs/dijkstra_alternate.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py index 7c252a83ea85..7f439a5b1148 100644 --- a/graphs/dijkstra_alternate.py +++ b/graphs/dijkstra_alternate.py @@ -82,18 +82,17 @@ def dijkstra(self, source: int) -> None: self.print_solution(distances) -# Driver program -g = Graph(9) -g.graph = [ - [0, 4, 0, 0, 0, 0, 0, 8, 0], - [4, 0, 8, 0, 0, 0, 0, 11, 0], - [0, 8, 0, 7, 0, 4, 0, 0, 2], - [0, 0, 7, 0, 9, 14, 0, 0, 0], - [0, 0, 0, 9, 0, 10, 0, 0, 0], - [0, 0, 4, 14, 10, 0, 2, 0, 0], - [0, 0, 0, 0, 0, 2, 0, 1, 6], - [8, 11, 0, 0, 0, 0, 1, 0, 7], - [0, 0, 2, 0, 0, 0, 6, 7, 0], -] - -g.dijkstra(0) +if __name__ == "__main__": + graph = Graph(9) + graph.graph = [ + [0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0], + ] + graph.dijkstra(0) From fa6d2ed2ffe7ea553e1aa1829a7d1b0c1a60142c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 20 Oct 2022 09:44:27 +0200 Subject: [PATCH 17/17] sptset --> visited --- graphs/dijkstra_alternate.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py index 7f439a5b1148..7beef6b04da1 100644 --- a/graphs/dijkstra_alternate.py +++ b/graphs/dijkstra_alternate.py @@ -25,7 +25,7 @@ def print_solution(self, distances_from_source: list[int]) -> None: print(vertex, "\t\t", distances_from_source[vertex]) def minimum_distance( - self, distances_from_source: list[int], sptset: list[bool] + self, distances_from_source: list[int], visited: list[bool] ) -> int: """ A utility function to find the vertex with minimum distance value, from the set @@ -41,7 +41,7 @@ def minimum_distance( # Search not nearest vertex not in the shortest path tree for vertex in range(self.vertices): - if distances_from_source[vertex] < minimum and sptset[vertex] is False: + if distances_from_source[vertex] < minimum and visited[vertex] is False: minimum = distances_from_source[vertex] min_index = vertex return min_index @@ -61,11 +61,11 @@ def dijkstra(self, source: int) -> None: distances = [int(1e7)] * self.vertices # distances from the source distances[source] = 0 - sptset = [False] * self.vertices + visited = [False] * self.vertices for _ in range(self.vertices): - u = self.minimum_distance(distances, sptset) - sptset[u] = True + u = self.minimum_distance(distances, visited) + visited[u] = True # Update dist value of the adjacent vertices # of the picked vertex only if the current @@ -74,7 +74,7 @@ def dijkstra(self, source: int) -> None: for v in range(self.vertices): if ( self.graph[u][v] > 0 - and sptset[v] is False + and visited[v] is False and distances[v] > distances[u] + self.graph[u][v] ): distances[v] = distances[u] + self.graph[u][v]