Skip to content

Commit c4246f0

Browse files
lighting9999pre-commit-ci[bot]cclauss
authored
Optimize Ford-Fulkerson algorithm with type annotations and performance improvements (#13128)
* change ford_fulkerson.py * fix ford_fulkerson.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typo for ford_fulkerson.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Change ford_fulkerson.py * fix I001 Error for ford_fulkerson.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix ford_fulkerson.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent a3806f7 commit c4246f0

1 file changed

Lines changed: 40 additions & 31 deletions

File tree

networking_flow/ford_fulkerson.py

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,33 @@ def breadth_first_search(graph: list, source: int, sink: int, parents: list) ->
2828
parents: Parent list
2929
3030
Returns:
31-
True if there is a node that has not iterated.
31+
True if there is a path from source to sink
3232
3333
>>> breadth_first_search(graph, 0, 5, [-1, -1, -1, -1, -1, -1])
3434
True
35-
>>> breadth_first_search(graph, 0, 6, [-1, -1, -1, -1, -1, -1])
36-
Traceback (most recent call last):
37-
...
38-
IndexError: list index out of range
3935
"""
40-
visited = [False] * len(graph) # Mark all nodes as not visited
41-
queue = [] # breadth-first search queue
36+
num_nodes = len(graph)
37+
visited = [False] * num_nodes
38+
queue = [] # Using list instead of deque
4239

43-
# Source node
4440
queue.append(source)
4541
visited[source] = True
4642

4743
while queue:
48-
u = queue.pop(0) # Pop the front node
49-
# Traverse all adjacent nodes of u
50-
for ind, node in enumerate(graph[u]):
51-
if visited[ind] is False and node > 0:
52-
queue.append(ind)
53-
visited[ind] = True
54-
parents[ind] = u
44+
# Use pop(0) to simulate deque's popleft()
45+
current_node = queue.pop(0)
46+
47+
# If we reached the sink, we can stop early
48+
if current_node == sink:
49+
return True
50+
51+
# Check all adjacent nodes
52+
for neighbor, capacity in enumerate(graph[current_node]):
53+
if not visited[neighbor] and capacity > 0:
54+
visited[neighbor] = True
55+
parents[neighbor] = current_node
56+
queue.append(neighbor)
57+
5558
return visited[sink]
5659

5760

@@ -80,28 +83,34 @@ def ford_fulkerson(graph: list, source: int, sink: int) -> int:
8083
>>> ford_fulkerson(test_graph, 0, 5)
8184
23
8285
"""
83-
# This array is filled by breadth-first search and to store path
84-
parent = [-1] * (len(graph))
86+
# Create a copy of the graph to avoid modifying the original
87+
residual_graph = [row[:] for row in graph]
88+
num_nodes = len(residual_graph)
89+
parents = [-1] * num_nodes
8590
max_flow = 0
8691

87-
# While there is a path from source to sink
88-
while breadth_first_search(graph, source, sink, parent):
89-
path_flow = int(1e9) # Infinite value
90-
s = sink
92+
# Augment the flow while there is a path from source to sink
93+
while breadth_first_search(residual_graph, source, sink, parents):
94+
# Find the minimum residual capacity along the path
95+
path_flow = float("inf")
96+
current_node = sink
9197

92-
while s != source:
93-
# Find the minimum value in the selected path
94-
path_flow = min(path_flow, graph[parent[s]][s])
95-
s = parent[s]
98+
# Find the minimum capacity in the path
99+
while current_node != source:
100+
parent_node = parents[current_node]
101+
path_flow = min(path_flow, residual_graph[parent_node][current_node])
102+
current_node = parent_node
96103

104+
# Add path flow to overall flow
97105
max_flow += path_flow
98-
v = sink
99106

100-
while v != source:
101-
u = parent[v]
102-
graph[u][v] -= path_flow
103-
graph[v][u] += path_flow
104-
v = parent[v]
107+
# Update residual capacities of the edges and reverse edges
108+
current_node = sink
109+
while current_node != source:
110+
parent_node = parents[current_node]
111+
residual_graph[parent_node][current_node] -= path_flow
112+
residual_graph[current_node][parent_node] += path_flow
113+
current_node = parent_node
105114

106115
return max_flow
107116

0 commit comments

Comments
 (0)