Skip to content

Commit c8a7506

Browse files
committed
Implemented FordFulkerson Algorithm with tests
1 parent f34b7d6 commit c8a7506

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

pydatastructs/graphs/algorithms.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,68 @@ def _breadth_first_search_max_flow(graph: Graph, source_node, sink_node, flow_pa
11431143
return (0, parent)
11441144

11451145

1146+
def _copy_graph_with_residual_edges(graph: Graph) -> Graph:
1147+
vertices = [graph.__getattribute__(v) for v in graph.vertices]
1148+
new_graph = type(graph)(*vertices)
1149+
1150+
for key, edge in graph.edge_weights.items():
1151+
new_graph.add_edge(edge.source.name, edge.target.name, edge.value)
1152+
1153+
1154+
for key, edge in list(new_graph.edge_weights.items()):
1155+
src = edge.source.name
1156+
tgt = edge.target.name
1157+
if new_graph.get_edge(tgt, src) is None:
1158+
new_graph.add_edge(tgt, src, 0)
1159+
1160+
return new_graph
1161+
1162+
1163+
def _dfs_max_flow(graph: Graph, node, sink, flow_passed, visited, flow):
1164+
if node == sink:
1165+
return flow
1166+
1167+
visited[node] = True
1168+
1169+
for next_node in graph.neighbors(node):
1170+
capacity = graph.get_edge(node, next_node.name).value
1171+
fp = flow_passed.get((node, next_node.name), 0)
1172+
residual_capacity = capacity - fp
1173+
1174+
if residual_capacity > 0 and next_node.name not in visited:
1175+
bottleneck_flow = _dfs_max_flow(
1176+
graph, next_node.name, sink, flow_passed, visited, min(flow, residual_capacity)
1177+
)
1178+
if bottleneck_flow > 0:
1179+
flow_passed[(node, next_node.name)] = fp + bottleneck_flow
1180+
flow_passed[(next_node.name, node)] = flow_passed.get((next_node.name, node), 0) - bottleneck_flow
1181+
return bottleneck_flow
1182+
1183+
return 0
1184+
1185+
def _max_flow_ford_fulkerson_(graph: Graph, source, sink):
1186+
graph_copy = _copy_graph_with_residual_edges(graph)
1187+
1188+
m_flow = 0
1189+
flow_passed = {}
1190+
1191+
# Add residual edges to the graph.
1192+
print(graph.neighbors('a'))
1193+
1194+
while True:
1195+
# Use a dictionary for visited nodes. Reset for each new DFS call.
1196+
visited = {}
1197+
new_flow = _dfs_max_flow(graph_copy, source, sink, flow_passed, visited, float('inf'))
1198+
1199+
# If no augmenting path is found, exit the loop.
1200+
if new_flow == 0:
1201+
break
1202+
1203+
m_flow += new_flow
1204+
1205+
return m_flow
1206+
1207+
11461208
def _max_flow_edmonds_karp_(graph: Graph, source, sink):
11471209
m_flow = 0
11481210
flow_passed = {}

pydatastructs/graphs/tests/test_algorithms.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,3 +448,4 @@ def _test_max_flow(ds, algorithm):
448448
_test_max_flow("Matrix", "edmonds_karp")
449449
_test_max_flow("List", "dinic")
450450
_test_max_flow("Matrix", "dinic")
451+
_test_max_flow("List", "ford_fulkerson")

0 commit comments

Comments
 (0)