From 457af3b6de260160695ae55e1b7e71b55ad1417c Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 21:46:32 +0400 Subject: [PATCH 01/15] add skeleton code --- backtracking/coloring.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 backtracking/coloring.py diff --git a/backtracking/coloring.py b/backtracking/coloring.py new file mode 100644 index 000000000000..0d014846e305 --- /dev/null +++ b/backtracking/coloring.py @@ -0,0 +1,8 @@ +""" + Graph Coloring also called "m coloring problem" + consists of coloring given graph with at most m colors + such that no adjacent vertices are assigned same color +""" + +def color(graph, m): + pass \ No newline at end of file From 46127ee992ae8bc08ea6178a07e3adae58e076d1 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 21:50:43 +0400 Subject: [PATCH 02/15] add doctests --- backtracking/coloring.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 0d014846e305..3f53202fb636 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,4 +5,19 @@ """ def color(graph, m): + """ + >>> graph = [[0, 1, 0, 0, 0], + ... [1, 0, 1, 0, 1], + ... [0, 1, 0, 1, 0], + ... [0, 1, 1, 0, 0], + ... [0, 1, 0, 0, 0]] + + >>> total_colors = 3 + >>> color(graph, total_colors) + (True, [1, 2, 1, 3, 1]) + + >>> total_colors = 2 + >>> color(graph, total_colors) + (False, None) + """ pass \ No newline at end of file From 2d821c867b2cc7663398933ad90eb64b437558e3 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 22:13:11 +0400 Subject: [PATCH 03/15] add mainc function pseudo code and tests (ToDo: write Implementation) --- backtracking/coloring.py | 43 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 3f53202fb636..577d020e29c2 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -4,8 +4,42 @@ such that no adjacent vertices are assigned same color """ -def color(graph, m): + +def util_color(graph, max_colors, colored_vertices, index): + """ + Pseudo-Code + + Itterates over each color: + Check if coloring is possible: + 1. Color given vertex + 2. Do recursive call check if this coloring leads to solving problem + 4. if coloring is valid return + 5. Uncolor given vertex + + >>> graph = [[0, 1, 0, 0, 0], + ... [1, 0, 1, 0, 1], + ... [0, 1, 0, 1, 0], + ... [0, 1, 1, 0, 0], + ... [0, 1, 0, 0, 0]] + >>> total_colors = 3 + >>> colored_vertices = [0, 1, 0, 0, 0] + >>> index = 3 + + >>> util_color(graph, max_colors, colored_vertices, index) + True + + >>> total_colors = 2 + >>> util_color(graph, max_colors, colored_vertices, index) + False """ + pass + + +def color(graph, max_colors): + """ Wrapper function to call subroutine called util_color + which will either return True or False. + If True is returned colored_vertices list is filled with correct colorings + >>> graph = [[0, 1, 0, 0, 0], ... [1, 0, 1, 0, 1], ... [0, 1, 0, 1, 0], @@ -20,4 +54,9 @@ def color(graph, m): >>> color(graph, total_colors) (False, None) """ - pass \ No newline at end of file + colored_vertices = [-1] * len(graph) + + if util_color(graph, max_colors, colored_vertices, 0): + return True, colored_vertices + + return False, None From 15585f1e3bdf9a4ba9f5892ef71e35601780ba2e Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 22:23:42 +0400 Subject: [PATCH 04/15] typo fixes --- backtracking/coloring.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 577d020e29c2..999494f75d2d 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -9,12 +9,17 @@ def util_color(graph, max_colors, colored_vertices, index): """ Pseudo-Code - Itterates over each color: - Check if coloring is possible: - 1. Color given vertex - 2. Do recursive call check if this coloring leads to solving problem - 4. if coloring is valid return - 5. Uncolor given vertex + BaseCase: + 1. Check if coloring is complete + 1.1 If complete return True (meaning that we successfully colored graph) + + RecursiveStep: + 2. Itterates over each color: + Check if current coloring is valid: + 2.1. Color given vertex + 2.2. Do recursive call check if this coloring leads to solving problem + 2.4. if current coloring leads to solution return + 2.5. Uncolor given vertex >>> graph = [[0, 1, 0, 0, 0], ... [1, 0, 1, 0, 1], @@ -32,13 +37,13 @@ def util_color(graph, max_colors, colored_vertices, index): >>> util_color(graph, max_colors, colored_vertices, index) False """ - pass def color(graph, max_colors): - """ Wrapper function to call subroutine called util_color - which will either return True or False. - If True is returned colored_vertices list is filled with correct colorings + """ + Wrapper function to call subroutine called util_color + which will either return True or False. + If True is returned colored_vertices list is filled with correct colorings >>> graph = [[0, 1, 0, 0, 0], ... [1, 0, 1, 0, 1], From b60da84b402fda8f9160ba7335601cec25450a41 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 22:49:23 +0400 Subject: [PATCH 05/15] implement algorithm --- backtracking/coloring.py | 59 ++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 999494f75d2d..b822094bf597 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,15 +5,40 @@ """ +def valid_coloring(neighbours, colored_vertices, color): + """ + For each neighbour check if coloring constraint is satisfied + If any of the neighbours fail the contraint return False + If all neighbours validate constraint return True + + >>> neighbours = [0,1,0,1,0] + >>> colored_vertices = [0, 2, 1, 2, 0] + + >>> color = 1 + >>> valid_coloring(neighbours, colored_vertices, color) + True + + >>> color = 2 + >>> valid_coloring(neighbours, colored_vertices, color) + False + """ + for i in range(len(neighbours)): + # Constraint Failed + if neighbours[i] == 1 and colored_vertices[i] == color: + return False + # All neighbours satisfy constraint + return True + + def util_color(graph, max_colors, colored_vertices, index): """ Pseudo-Code - BaseCase: + Base Case: 1. Check if coloring is complete 1.1 If complete return True (meaning that we successfully colored graph) - RecursiveStep: + Recursive Step: 2. Itterates over each color: Check if current coloring is valid: 2.1. Color given vertex @@ -26,18 +51,34 @@ def util_color(graph, max_colors, colored_vertices, index): ... [0, 1, 0, 1, 0], ... [0, 1, 1, 0, 0], ... [0, 1, 0, 0, 0]] - >>> total_colors = 3 + >>> max_colors = 3 >>> colored_vertices = [0, 1, 0, 0, 0] >>> index = 3 >>> util_color(graph, max_colors, colored_vertices, index) True - >>> total_colors = 2 + >>> max_colors = 2 >>> util_color(graph, max_colors, colored_vertices, index) False """ + # Base Case + if index == len(graph): + return True + + # Recursive Step + for i in range(0, max_colors): + if valid_coloring(graph[index], colored_vertices, i): + # Color current vertex + colored_vertices[index] = i + # Validate coloring + if util_color(graph, max_colors, colored_vertices, index + 1): + return True + # Backtrack + colored_vertices[index] = -1 + return False + def color(graph, max_colors): """ @@ -51,12 +92,12 @@ def color(graph, max_colors): ... [0, 1, 1, 0, 0], ... [0, 1, 0, 0, 0]] - >>> total_colors = 3 - >>> color(graph, total_colors) - (True, [1, 2, 1, 3, 1]) + >>> max_colors = 3 + >>> color(graph, max_colors) + (True, [0, 1, 0, 2, 0]) - >>> total_colors = 2 - >>> color(graph, total_colors) + >>> max_colors = 2 + >>> color(graph, max_colors) (False, None) """ colored_vertices = [-1] * len(graph) From aeecd32db6cea7ae5d6798c3dc9c6f64b7548bd9 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 23:04:05 +0400 Subject: [PATCH 06/15] add type checking --- backtracking/coloring.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index b822094bf597..9f05d9835f5f 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -1,3 +1,5 @@ +from typing import List, Tuple, Union + """ Graph Coloring also called "m coloring problem" consists of coloring given graph with at most m colors @@ -5,7 +7,9 @@ """ -def valid_coloring(neighbours, colored_vertices, color): +def valid_coloring( + neighbours: List[int], colored_vertices: List[int], color: int +) -> bool: """ For each neighbour check if coloring constraint is satisfied If any of the neighbours fail the contraint return False @@ -30,7 +34,9 @@ def valid_coloring(neighbours, colored_vertices, color): return True -def util_color(graph, max_colors, colored_vertices, index): +def util_color( + graph: List[List[int]], max_colors: int, colored_vertices: List[int], index: int +) -> bool: """ Pseudo-Code @@ -80,7 +86,9 @@ def util_color(graph, max_colors, colored_vertices, index): return False -def color(graph, max_colors): +def color( + graph: List[List[int]], max_colors: int +) -> Tuple[bool, Union[List[int], None]]: """ Wrapper function to call subroutine called util_color which will either return True or False. From 0dbcf676e008ec5dc322f420a2daa469cb4bd6f3 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 23:18:03 +0400 Subject: [PATCH 07/15] add wikipedia link --- backtracking/coloring.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 9f05d9835f5f..f269dccb0495 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -4,6 +4,8 @@ Graph Coloring also called "m coloring problem" consists of coloring given graph with at most m colors such that no adjacent vertices are assigned same color + + Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ From d097d276a9c9a654b78bb908555aa6125c4f081c Mon Sep 17 00:00:00 2001 From: CSenshi Date: Thu, 30 Apr 2020 23:24:13 +0400 Subject: [PATCH 08/15] typo fix --- backtracking/coloring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index f269dccb0495..ddd48464b792 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -14,7 +14,7 @@ def valid_coloring( ) -> bool: """ For each neighbour check if coloring constraint is satisfied - If any of the neighbours fail the contraint return False + If any of the neighbours fail the constraint return False If all neighbours validate constraint return True >>> neighbours = [0,1,0,1,0] From d6723aee6b4d510290d73c476b7c5d41235a9cb1 Mon Sep 17 00:00:00 2001 From: Saba Pochkhua Date: Fri, 1 May 2020 00:00:08 +0400 Subject: [PATCH 09/15] update range syntax Co-authored-by: Christian Clauss --- backtracking/coloring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index ddd48464b792..27fd87e3ec61 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -76,7 +76,7 @@ def util_color( return True # Recursive Step - for i in range(0, max_colors): + for i in range(max_colors): if valid_coloring(graph[index], colored_vertices, i): # Color current vertex colored_vertices[index] = i From bf04f4dc08ed46511c2deaf8a92cfa32c75ee3ff Mon Sep 17 00:00:00 2001 From: Saba Pochkhua Date: Fri, 1 May 2020 00:02:13 +0400 Subject: [PATCH 10/15] change indexed iteration checking to any() Co-authored-by: Christian Clauss --- backtracking/coloring.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 27fd87e3ec61..f888bd42c153 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -28,12 +28,9 @@ def valid_coloring( >>> valid_coloring(neighbours, colored_vertices, color) False """ - for i in range(len(neighbours)): - # Constraint Failed - if neighbours[i] == 1 and colored_vertices[i] == color: - return False - # All neighbours satisfy constraint - return True + # Does any neighbour not satisfy the constraints + return not any(neighbour == 1 and colored_vertices[i] == color + for i, neighbour in enumerate(neighbours)) def util_color( From de5253828185b83c5b5f1021db0379ab174a8c4e Mon Sep 17 00:00:00 2001 From: CSenshi Date: Fri, 1 May 2020 00:21:44 +0400 Subject: [PATCH 11/15] fix: swap import and documentation sections --- backtracking/coloring.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index f888bd42c153..fe87e7237d67 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -1,5 +1,3 @@ -from typing import List, Tuple, Union - """ Graph Coloring also called "m coloring problem" consists of coloring given graph with at most m colors @@ -7,6 +5,7 @@ Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ +from typing import List, Tuple, Union def valid_coloring( @@ -29,8 +28,10 @@ def valid_coloring( False """ # Does any neighbour not satisfy the constraints - return not any(neighbour == 1 and colored_vertices[i] == color - for i, neighbour in enumerate(neighbours)) + return not any( + neighbour == 1 and colored_vertices[i] == color + for i, neighbour in enumerate(neighbours) + ) def util_color( From 87be0fc44c40b348064cb938459e063aeffe6d7f Mon Sep 17 00:00:00 2001 From: CSenshi Date: Fri, 1 May 2020 00:23:19 +0400 Subject: [PATCH 12/15] fix: change return none to return empty list --- backtracking/coloring.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index fe87e7237d67..1ae2a5b6e674 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -86,9 +86,7 @@ def util_color( return False -def color( - graph: List[List[int]], max_colors: int -) -> Tuple[bool, Union[List[int], None]]: +def color(graph: List[List[int]], max_colors: int) -> Tuple[bool, List[int]]: """ Wrapper function to call subroutine called util_color which will either return True or False. @@ -113,4 +111,4 @@ def color( if util_color(graph, max_colors, colored_vertices, 0): return True, colored_vertices - return False, None + return False, [] From b99434922d4e3789b113758598d33d74709640cf Mon Sep 17 00:00:00 2001 From: CSenshi Date: Fri, 1 May 2020 00:44:57 +0400 Subject: [PATCH 13/15] remove unnecessary import (Union) --- backtracking/coloring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 1ae2a5b6e674..626bbf084ff9 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,7 +5,7 @@ Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ -from typing import List, Tuple, Union +from typing import List, Tuple def valid_coloring( From e3316563dccaef319017da60eaae2b6dc1b5a916 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Fri, 1 May 2020 01:10:21 +0400 Subject: [PATCH 14/15] change: remove returning boolean indicating problem was solved or not --- backtracking/coloring.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 626bbf084ff9..6f6c8fe729e2 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -86,7 +86,7 @@ def util_color( return False -def color(graph: List[List[int]], max_colors: int) -> Tuple[bool, List[int]]: +def color(graph: List[List[int]], max_colors: int) -> List[int]: """ Wrapper function to call subroutine called util_color which will either return True or False. @@ -100,15 +100,15 @@ def color(graph: List[List[int]], max_colors: int) -> Tuple[bool, List[int]]: >>> max_colors = 3 >>> color(graph, max_colors) - (True, [0, 1, 0, 2, 0]) + [0, 1, 0, 2, 0] >>> max_colors = 2 >>> color(graph, max_colors) - (False, None) + [] """ colored_vertices = [-1] * len(graph) if util_color(graph, max_colors, colored_vertices, 0): - return True, colored_vertices + return colored_vertices - return False, [] + return [] From 04b72cbc2ea096fc1d649ab4fa6dc11e84135dc9 Mon Sep 17 00:00:00 2001 From: CSenshi Date: Fri, 1 May 2020 01:16:56 +0400 Subject: [PATCH 15/15] remove unnecessary import (Tuple) --- backtracking/coloring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 6f6c8fe729e2..77beb5fc1956 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,7 +5,7 @@ Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ -from typing import List, Tuple +from typing import List def valid_coloring(