From 8c41bdec6d757cf6fe36ce7507c1a5b6075c333f Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Tue, 1 Oct 2024 18:41:11 +0530 Subject: [PATCH 1/4] Improve comments, add doctests for kahns_algorithm_topo.py --- graphs/kahns_algorithm_topo.py | 58 ++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index b1260bd5bd9b..ed2e5d7b8c4c 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -1,36 +1,66 @@ -def topological_sort(graph): +def topological_sort(graph: dict[int, list[int]] + ) -> list[int] | None: """ - Kahn's Algorithm is used to find Topological ordering of Directed Acyclic Graph - using BFS + Perform topological sorting of a Directed Acyclic Graph (DAG) + using Kahn's Algorithm. + + Topological sorting is a linear ordering of vertices in a graph such that for + every directed edge u → v, vertex u comes before vertex v in the ordering. + This function uses Kahn's algorithm to achieve this + via Breadth-First Search (BFS). + + Parameters: + graph: Adjacency list representing the directed graph where keys are + vertices, and values are lists of adjacent vertices. + + Returns: + The topologically sorted order of vertices if the graph is a DAG. + Returns None if the graph contains a cycle. + + Example: + >>> graph = {0: [1, 2], 1: [3], 2: [3], 3: [4, 5], 4: [], 5: []} + >>> topological_sort(graph) + [0, 1, 2, 3, 4, 5] + + >>> graph_with_cycle = {0: [1], 1: [2], 2: [0]} + >>> topological_sort(graph_with_cycle) + Cycle exists """ + + # Initialize indegree array indegree = [0] * len(graph) queue = [] - topo = [] - cnt = 0 + topo = [] # topological order of vertices + cnt = 0 # no. of vertices processed + # Calculate the indegree of each vertex for values in graph.values(): for i in values: indegree[i] += 1 + # Add all vertices with 0 indegree to the queue for i in range(len(indegree)): if indegree[i] == 0: queue.append(i) + # Perform BFS while queue: vertex = queue.pop(0) cnt += 1 topo.append(vertex) - for x in graph[vertex]: - indegree[x] -= 1 - if indegree[x] == 0: - queue.append(x) + + # Traverse neighbors + for neighbor in graph[vertex]: + indegree[neighbor] -= 1 + if indegree[neighbor] == 0: + queue.append(neighbor) if cnt != len(graph): print("Cycle exists") - else: - print(topo) + return None # no topological ordering exists + return topo # valid topological ordering -# Adjacency List of Graph -graph = {0: [1, 2], 1: [3], 2: [3], 3: [4, 5], 4: [], 5: []} -topological_sort(graph) +if __name__ == "__main__": + import doctest + doctest.testmod() From a505c67fc6588d1d779123e9071546d9bc2c863b Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Wed, 2 Oct 2024 12:43:35 +0530 Subject: [PATCH 2/4] Improve function docstring --- graphs/kahns_algorithm_topo.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index ed2e5d7b8c4c..b9ea447a9424 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -2,12 +2,10 @@ def topological_sort(graph: dict[int, list[int]] ) -> list[int] | None: """ Perform topological sorting of a Directed Acyclic Graph (DAG) - using Kahn's Algorithm. + using Kahn's Algorithm via Breadth-First Search (BFS). Topological sorting is a linear ordering of vertices in a graph such that for every directed edge u → v, vertex u comes before vertex v in the ordering. - This function uses Kahn's algorithm to achieve this - via Breadth-First Search (BFS). Parameters: graph: Adjacency list representing the directed graph where keys are From 899a8f27a4d73d27ea9ca0423de8efc720eb1c94 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 07:15:20 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/kahns_algorithm_topo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index b9ea447a9424..50756798b1ef 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -1,5 +1,4 @@ -def topological_sort(graph: dict[int, list[int]] - ) -> list[int] | None: +def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: """ Perform topological sorting of a Directed Acyclic Graph (DAG) using Kahn's Algorithm via Breadth-First Search (BFS). @@ -61,4 +60,5 @@ def topological_sort(graph: dict[int, list[int]] if __name__ == "__main__": import doctest + doctest.testmod() From 278619acc4f3e00395f211f3504a4b0e4121e8a8 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Thu, 3 Oct 2024 09:18:35 +0530 Subject: [PATCH 4/4] Rename variables, remove print --- graphs/kahns_algorithm_topo.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index 50756798b1ef..c956cf9f48fd 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -21,14 +21,12 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: >>> graph_with_cycle = {0: [1], 1: [2], 2: [0]} >>> topological_sort(graph_with_cycle) - Cycle exists """ - # Initialize indegree array indegree = [0] * len(graph) queue = [] - topo = [] # topological order of vertices - cnt = 0 # no. of vertices processed + topo_order = [] + processed_vertices_count = 0 # Calculate the indegree of each vertex for values in graph.values(): @@ -43,8 +41,8 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: # Perform BFS while queue: vertex = queue.pop(0) - cnt += 1 - topo.append(vertex) + processed_vertices_count += 1 + topo_order.append(vertex) # Traverse neighbors for neighbor in graph[vertex]: @@ -52,10 +50,9 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: if indegree[neighbor] == 0: queue.append(neighbor) - if cnt != len(graph): - print("Cycle exists") - return None # no topological ordering exists - return topo # valid topological ordering + if processed_vertices_count != len(graph): + return None # no topological ordering exists due to cycle + return topo_order # valid topological ordering if __name__ == "__main__":