From 8261cbad9aaf35d8360760f22ca2541eeb31e982 Mon Sep 17 00:00:00 2001 From: lee changwon <39148949+lcw921@users.noreply.github.com> Date: Wed, 11 Dec 2019 13:41:13 +0900 Subject: [PATCH] [ADD] Create maximum_flow_bfs.py (#603) * [ADD] Create maximum_flow_bfs.py * Update README.md * Update README.md * [ADD] Create maximum_flow_dfs.py * Update README.md * Add unittest * Fix no newline end of file --- README.md | 2 + algorithms/graph/__init__.py | 2 + algorithms/graph/maximum_flow_bfs.py | 84 ++++++++++++++++++++++++++++ algorithms/graph/maximum_flow_dfs.py | 84 ++++++++++++++++++++++++++++ tests/test_graph.py | 56 ++++++++++++++++++- 5 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 algorithms/graph/maximum_flow_bfs.py create mode 100644 algorithms/graph/maximum_flow_dfs.py diff --git a/README.md b/README.md index 723f85a28..8569d3b1a 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,8 @@ If you want to uninstall algorithms, it is as simple as: - [satisfiability](algorithms/graph/satisfiability.py) - [tarjan](algorithms/graph/tarjan.py) - [traversal](algorithms/graph/traversal.py) + - [maximum_flow_bfs](algorithms/graph/maximum_flow_bfs.py) + - [maximum_flow_dfs](algorithms/graph/maximum_flow_dfs.py) - [all_pairs_shortest_path](algorithms/graph/all_pairs_shortest_path.py) - [bellman_ford](algorithms/graph/bellman_ford.py) - [heap](algorithms/heap) diff --git a/algorithms/graph/__init__.py b/algorithms/graph/__init__.py index a155c77ea..43cab3d0c 100644 --- a/algorithms/graph/__init__.py +++ b/algorithms/graph/__init__.py @@ -1,4 +1,6 @@ from .tarjan import * from .check_bipartite import * +from .maximum_flow_bfs import * +from .maximum_flow_dfs import * from .all_pairs_shortest_path import * from .bellman_ford import * diff --git a/algorithms/graph/maximum_flow_bfs.py b/algorithms/graph/maximum_flow_bfs.py new file mode 100644 index 000000000..4d2d032ff --- /dev/null +++ b/algorithms/graph/maximum_flow_bfs.py @@ -0,0 +1,84 @@ +""" +Given a n*n adjacency array. +it will give you a maximum flow. +This version use BFS to search path. + +Assume the first is the source and the last is the sink. + +Time complexity - O(Ef) + +example + +graph = [[0, 16, 13, 0, 0, 0], + [0, 0, 10, 12, 0, 0], + [0, 4, 0, 0, 14, 0], + [0, 0, 9, 0, 0, 20], + [0, 0, 0, 7, 0, 4], + [0, 0, 0, 0, 0, 0]] + +answer should be + +23 + +""" +import copy +import queue +import math + +def maximum_flow_bfs(adjacency_matrix): + #initial setting + new_array = copy.deepcopy(adjacency_matrix) + total = 0 + + while(1): + #setting min to max_value + min = math.inf + #save visited nodes + visited = [0]*len(new_array) + #save parent nodes + path = [0]*len(new_array) + + #initialize queue for BFS + bfs = queue.Queue() + + #initial setting + visited[0] = 1 + bfs.put(0) + + #BFS to find path + while(bfs.qsize() > 0): + #pop from queue + src = bfs.get() + for k in range(len(new_array)): + #checking capacity and visit + if(new_array[src][k] > 0 and visited[k] == 0 ): + #if not, put into queue and chage to visit and save path + visited[k] = 1 + bfs.put(k) + path[k] = src + + #if there is no path from src to sink + if(visited[len(new_array) - 1] == 0): + break + + #initial setting + tmp = len(new_array) - 1 + + #Get minimum flow + while(tmp != 0): + #find minimum flow + if(min > new_array[path[tmp]][tmp]): + min = new_array[path[tmp]][tmp] + tmp = path[tmp] + + #initial setting + tmp = len(new_array) - 1 + + #reduce capacity + while(tmp != 0): + new_array[path[tmp]][tmp] = new_array[path[tmp]][tmp] - min + tmp = path[tmp] + + total = total + min + + return total diff --git a/algorithms/graph/maximum_flow_dfs.py b/algorithms/graph/maximum_flow_dfs.py new file mode 100644 index 000000000..2d89d6b56 --- /dev/null +++ b/algorithms/graph/maximum_flow_dfs.py @@ -0,0 +1,84 @@ +""" +Given a n*n adjacency array. +it will give you a maximum flow. +This version use DFS to search path. + +Assume the first is the source and the last is the sink. + +Time complexity - O(Ef) + +example + +graph = [[0, 16, 13, 0, 0, 0], + [0, 0, 10, 12, 0, 0], + [0, 4, 0, 0, 14, 0], + [0, 0, 9, 0, 0, 20], + [0, 0, 0, 7, 0, 4], + [0, 0, 0, 0, 0, 0]] + +answer should be + +23 + +""" +import copy +import math + +def maximum_flow_dfs(adjacency_matrix): + #initial setting + new_array = copy.deepcopy(adjacency_matrix) + total = 0 + + while(1): + #setting min to max_value + min = math.inf + #save visited nodes + visited = [0]*len(new_array) + #save parent nodes + path = [0]*len(new_array) + + #initialize stack for DFS + stack = [] + + #initial setting + visited[0] = 1 + stack.append(0) + + #DFS to find path + while(len(stack) > 0): + #pop from queue + src = stack.pop() + for k in range(len(new_array)): + #checking capacity and visit + if(new_array[src][k] > 0 and visited[k] == 0 ): + #if not, put into queue and chage to visit and save path + visited[k] = 1 + stack.append(k) + path[k] = src + + #if there is no path from src to sink + if(visited[len(new_array) - 1] == 0): + break + + #initial setting + tmp = len(new_array) - 1 + + #Get minimum flow + while(tmp != 0): + #find minimum flow + if(min > new_array[path[tmp]][tmp]): + min = new_array[path[tmp]][tmp] + tmp = path[tmp] + + #initial setting + tmp = len(new_array) - 1 + + #reduce capacity + while(tmp != 0): + new_array[path[tmp]][tmp] = new_array[path[tmp]][tmp] - min + tmp = path[tmp] + + total = total + min + + return total + \ No newline at end of file diff --git a/tests/test_graph.py b/tests/test_graph.py index 48c2bbb4e..47d5afae0 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -1,9 +1,12 @@ from algorithms.graph import Tarjan from algorithms.graph import check_bipartite from algorithms.graph.dijkstra import Dijkstra +from algorithms.graph import maximum_flow_bfs +from algorithms.graph import maximum_flow_dfs from algorithms.graph import all_pairs_shortest_path from algorithms.graph import bellman_ford + import unittest @@ -78,6 +81,49 @@ def test_dijkstra(self): self.assertEqual(g.dijkstra(0), [0, 4, 12, 19, 21, 11, 9, 8, 14]) +class TestMaximum_Flow_Bfs(unittest.TestCase): + + """ + Test for the file def maximum_flow_bfs.py + Arguments: + unittest {[type]} -- [description] + """ + + def test_maximum_flow_bfs(self): + graph = [ + [0, 16, 13, 0, 0, 0], + [0, 0, 10, 12, 0, 0], + [0, 4, 0, 0, 14, 0], + [0, 0, 9, 0, 0, 20], + [0, 0, 0, 7, 0, 4], + [0, 0, 0, 0, 0, 0] + ] + maximum_flow = maximum_flow_bfs(graph) + + self.assertEqual(maximum_flow, 23) + +class TestMaximum_Flow_Dfs(unittest.TestCase): + + """ + Test for the file def maximum_flow_dfs.py + Arguments: + unittest {[type]} -- [description] + """ + + def test_maximum_flow_dfs(self): + graph = [ + [0, 16, 13, 0, 0, 0], + [0, 0, 10, 12, 0, 0], + [0, 4, 0, 0, 14, 0], + [0, 0, 9, 0, 0, 20], + [0, 0, 0, 7, 0, 4], + [0, 0, 0, 0, 0, 0] + ] + maximum_flow = maximum_flow_dfs(graph) + + self.assertEqual(maximum_flow, 23) + + class TestAll_Pairs_Shortest_Path(unittest.TestCase): def test_all_pairs_shortest_path(self): @@ -88,7 +134,14 @@ def test_all_pairs_shortest_path(self): [0.867, 0.119, 0.352, 0.398, 0]] result = all_pairs_shortest_path(graph) - self.assertEqual(result, [[0, 0.1, 0.101, 0.142, 0.277], [0.436, 0, 0.191, 0.192, 0.34299999999999997], [0.245, 0.345, 0, 0.333, 0.484], [0.706, 0.27, 0.46099999999999997, 0, 0.151], [0.5549999999999999, 0.119, 0.31, 0.311, 0]]) + self.assertEqual(result, [ + [0, 0.1, 0.101, 0.142, 0.277], + [0.436, 0, 0.191, 0.192, 0.34299999999999997], + [0.245, 0.345, 0, 0.333, 0.484], + [0.706, 0.27, 0.46099999999999997, 0, 0.151], + [0.5549999999999999, 0.119, 0.31, 0.311, 0], + ]) + class TestBellmanFord(unittest.TestCase): def test_bellman_ford(self): @@ -111,3 +164,4 @@ def test_bellman_ford(self): } self.assertEqual(True, bellman_ford(graph2, 'a')) +