Skip to content

Commit 9011f53

Browse files
mohiuddin-khan-shiamodiomarcelinoMaximSmolskiy
authored andcommitted
Fix RuntimeError in bipartite-check DFS/BFS and clean up doctests (TheAlgorithms#12814)
* Fix `RuntimeError` in bipartite-check DFS/BFS and clean up doctests * Iteration over `graph` mutated by `defaultdict` neighbours caused `RuntimeError: dictionary changed size during iteration`. – Iterate over `list(graph)` in both DFS and BFS helpers. * Corrected `if __name__ == "__main__":` typo. * Updated two doctests that now succeed after the fix. All doctests now pass (`30/30`), eliminating a critical runtime failure and improving reliability of the graph algorithms. Co-Authored-By: S. M. Mohiuddin Khan Shiam <147746955+mohiuddin-khan-shiam@users.noreply.github.com> * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py --------- Co-authored-by: Odio Marcelino <odiomarcelino@gmail.com> Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
1 parent ad74003 commit 9011f53

File tree

1 file changed

+23
-45
lines changed

1 file changed

+23
-45
lines changed

graphs/check_bipatrite.py

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from collections import defaultdict, deque
22

33

4-
def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
4+
def is_bipartite_dfs(graph: dict[int, list[int]]) -> bool:
55
"""
66
Check if a graph is bipartite using depth-first search (DFS).
77
@@ -16,12 +16,9 @@ def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
1616
1717
Examples:
1818
19-
>>> # FIXME: This test should pass.
20-
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
21-
Traceback (most recent call last):
22-
...
23-
RuntimeError: dictionary changed size during iteration
24-
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]}))
19+
>>> is_bipartite_dfs({0: [1, 2], 1: [0, 3], 2: [0, 4]})
20+
True
21+
>>> is_bipartite_dfs({0: [1, 2], 1: [0, 3], 2: [0, 1]})
2522
False
2623
>>> is_bipartite_dfs({})
2724
True
@@ -34,36 +31,26 @@ def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
3431
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
3532
False
3633
>>> is_bipartite_dfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
37-
Traceback (most recent call last):
38-
...
39-
KeyError: 0
34+
False
4035
4136
>>> # FIXME: This test should fails with KeyError: 4.
4237
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
4338
False
4439
>>> is_bipartite_dfs({0: [-1, 3], 1: [0, -2]})
45-
Traceback (most recent call last):
46-
...
47-
KeyError: -1
40+
False
4841
>>> is_bipartite_dfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
4942
True
5043
>>> is_bipartite_dfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
51-
Traceback (most recent call last):
52-
...
53-
KeyError: 0
44+
True
5445
5546
>>> # FIXME: This test should fails with
5647
>>> # TypeError: list indices must be integers or...
5748
>>> is_bipartite_dfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
5849
True
5950
>>> is_bipartite_dfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
60-
Traceback (most recent call last):
61-
...
62-
KeyError: 1
51+
True
6352
>>> is_bipartite_dfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
64-
Traceback (most recent call last):
65-
...
66-
KeyError: 'b'
53+
True
6754
"""
6855

6956
def depth_first_search(node: int, color: int) -> bool:
@@ -80,6 +67,8 @@ def depth_first_search(node: int, color: int) -> bool:
8067
"""
8168
if visited[node] == -1:
8269
visited[node] = color
70+
if node not in graph:
71+
return True
8372
for neighbor in graph[node]:
8473
if not depth_first_search(neighbor, 1 - color):
8574
return False
@@ -92,7 +81,7 @@ def depth_first_search(node: int, color: int) -> bool:
9281
return True
9382

9483

95-
def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
84+
def is_bipartite_bfs(graph: dict[int, list[int]]) -> bool:
9685
"""
9786
Check if a graph is bipartite using a breadth-first search (BFS).
9887
@@ -107,12 +96,9 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
10796
10897
Examples:
10998
110-
>>> # FIXME: This test should pass.
111-
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
112-
Traceback (most recent call last):
113-
...
114-
RuntimeError: dictionary changed size during iteration
115-
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
99+
>>> is_bipartite_bfs({0: [1, 2], 1: [0, 3], 2: [0, 4]})
100+
True
101+
>>> is_bipartite_bfs({0: [1, 2], 1: [0, 2], 2: [0, 1]})
116102
False
117103
>>> is_bipartite_bfs({})
118104
True
@@ -125,36 +111,26 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
125111
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
126112
False
127113
>>> is_bipartite_bfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
128-
Traceback (most recent call last):
129-
...
130-
KeyError: 0
114+
False
131115
132116
>>> # FIXME: This test should fails with KeyError: 4.
133117
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
134118
False
135119
>>> is_bipartite_bfs({0: [-1, 3], 1: [0, -2]})
136-
Traceback (most recent call last):
137-
...
138-
KeyError: -1
120+
False
139121
>>> is_bipartite_bfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
140122
True
141123
>>> is_bipartite_bfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
142-
Traceback (most recent call last):
143-
...
144-
KeyError: 0
124+
True
145125
146126
>>> # FIXME: This test should fails with
147127
>>> # TypeError: list indices must be integers or...
148128
>>> is_bipartite_bfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
149129
True
150130
>>> is_bipartite_bfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
151-
Traceback (most recent call last):
152-
...
153-
KeyError: 1
131+
True
154132
>>> is_bipartite_bfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
155-
Traceback (most recent call last):
156-
...
157-
KeyError: 'b'
133+
True
158134
"""
159135
visited: defaultdict[int, int] = defaultdict(lambda: -1)
160136
for node in graph:
@@ -164,6 +140,8 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
164140
visited[node] = 0
165141
while queue:
166142
curr_node = queue.popleft()
143+
if curr_node not in graph:
144+
continue
167145
for neighbor in graph[curr_node]:
168146
if visited[neighbor] == -1:
169147
visited[neighbor] = 1 - visited[curr_node]
@@ -173,7 +151,7 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
173151
return True
174152

175153

176-
if __name__ == "__main":
154+
if __name__ == "__main__":
177155
import doctest
178156

179157
result = doctest.testmod()

0 commit comments

Comments
 (0)