Skip to content

Commit b01e5b7

Browse files
CSenshicclauss
andauthored
Graph coloring (#1921)
* add skeleton code * add doctests * add mainc function pseudo code and tests (ToDo: write Implementation) * typo fixes * implement algorithm * add type checking * add wikipedia link * typo fix * update range syntax Co-authored-by: Christian Clauss <[email protected]> * change indexed iteration checking to any() Co-authored-by: Christian Clauss <[email protected]> * fix: swap import and documentation sections * fix: change return none to return empty list * remove unnecessary import (Union) * change: remove returning boolean indicating problem was solved or not * remove unnecessary import (Tuple) Co-authored-by: Christian Clauss <[email protected]>
1 parent 1ad78b2 commit b01e5b7

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

backtracking/coloring.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""
2+
Graph Coloring also called "m coloring problem"
3+
consists of coloring given graph with at most m colors
4+
such that no adjacent vertices are assigned same color
5+
6+
Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring
7+
"""
8+
from typing import List
9+
10+
11+
def valid_coloring(
12+
neighbours: List[int], colored_vertices: List[int], color: int
13+
) -> bool:
14+
"""
15+
For each neighbour check if coloring constraint is satisfied
16+
If any of the neighbours fail the constraint return False
17+
If all neighbours validate constraint return True
18+
19+
>>> neighbours = [0,1,0,1,0]
20+
>>> colored_vertices = [0, 2, 1, 2, 0]
21+
22+
>>> color = 1
23+
>>> valid_coloring(neighbours, colored_vertices, color)
24+
True
25+
26+
>>> color = 2
27+
>>> valid_coloring(neighbours, colored_vertices, color)
28+
False
29+
"""
30+
# Does any neighbour not satisfy the constraints
31+
return not any(
32+
neighbour == 1 and colored_vertices[i] == color
33+
for i, neighbour in enumerate(neighbours)
34+
)
35+
36+
37+
def util_color(
38+
graph: List[List[int]], max_colors: int, colored_vertices: List[int], index: int
39+
) -> bool:
40+
"""
41+
Pseudo-Code
42+
43+
Base Case:
44+
1. Check if coloring is complete
45+
1.1 If complete return True (meaning that we successfully colored graph)
46+
47+
Recursive Step:
48+
2. Itterates over each color:
49+
Check if current coloring is valid:
50+
2.1. Color given vertex
51+
2.2. Do recursive call check if this coloring leads to solving problem
52+
2.4. if current coloring leads to solution return
53+
2.5. Uncolor given vertex
54+
55+
>>> graph = [[0, 1, 0, 0, 0],
56+
... [1, 0, 1, 0, 1],
57+
... [0, 1, 0, 1, 0],
58+
... [0, 1, 1, 0, 0],
59+
... [0, 1, 0, 0, 0]]
60+
>>> max_colors = 3
61+
>>> colored_vertices = [0, 1, 0, 0, 0]
62+
>>> index = 3
63+
64+
>>> util_color(graph, max_colors, colored_vertices, index)
65+
True
66+
67+
>>> max_colors = 2
68+
>>> util_color(graph, max_colors, colored_vertices, index)
69+
False
70+
"""
71+
72+
# Base Case
73+
if index == len(graph):
74+
return True
75+
76+
# Recursive Step
77+
for i in range(max_colors):
78+
if valid_coloring(graph[index], colored_vertices, i):
79+
# Color current vertex
80+
colored_vertices[index] = i
81+
# Validate coloring
82+
if util_color(graph, max_colors, colored_vertices, index + 1):
83+
return True
84+
# Backtrack
85+
colored_vertices[index] = -1
86+
return False
87+
88+
89+
def color(graph: List[List[int]], max_colors: int) -> List[int]:
90+
"""
91+
Wrapper function to call subroutine called util_color
92+
which will either return True or False.
93+
If True is returned colored_vertices list is filled with correct colorings
94+
95+
>>> graph = [[0, 1, 0, 0, 0],
96+
... [1, 0, 1, 0, 1],
97+
... [0, 1, 0, 1, 0],
98+
... [0, 1, 1, 0, 0],
99+
... [0, 1, 0, 0, 0]]
100+
101+
>>> max_colors = 3
102+
>>> color(graph, max_colors)
103+
[0, 1, 0, 2, 0]
104+
105+
>>> max_colors = 2
106+
>>> color(graph, max_colors)
107+
[]
108+
"""
109+
colored_vertices = [-1] * len(graph)
110+
111+
if util_color(graph, max_colors, colored_vertices, 0):
112+
return colored_vertices
113+
114+
return []

0 commit comments

Comments
 (0)