Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 561cc38

Browse files
mohiuddin-khan-shiamodiomarcelinoMaximSmolskiy
authored
Fix RuntimeError in bipartite-check DFS/BFS and clean up doctests (#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 d927d67 commit 561cc38

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)

AltStyle によって変換されたページ (->オリジナル) /