11"""
2- Graph Coloring also called "m coloring problem"
3- consists of coloring a given graph with at most m colors
4- such that no adjacent vertices are assigned the same color
2+ Graph Coloring ( also called the "m coloring problem") is the problem of
3+ assigning at most 'm' colors to the vertices of a graph such that
4+ no two adjacent vertices share the same color.
55
66Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring
77"""
@@ -11,22 +11,42 @@ def valid_coloring(
1111 neighbours : list [int ], colored_vertices : list [int ], color : int
1212) -> bool :
1313 """
14+ This function checks if a given vertex can be assigned the specified color
15+ without violating the graph coloring constraints (i.e., no two adjacent vertices
16+ have the same color).
17+
18+ Procedure:
1419 For each neighbour check if the coloring constraint is satisfied
1520 If any of the neighbours fail the constraint return False
1621 If all neighbours validate the constraint return True
1722
18- >>> neighbours = [0,1,0,1,0]
19- >>> colored_vertices = [0, 2, 1, 2, 0]
23+ Parameters:
24+ neighbours (list[int]): The list representing which vertices are adjacent to the current vertex.
25+ 1 indicates an edge between the current vertex and the neighbour.
26+ colored_vertices (list[int]): List of current color assignments for all vertices (-1 means uncolored).
27+ color (int): The color we are trying to assign to the current vertex.
28+
29+ Returns:
30+ bool: True if the vertex can be safely colored with the given color, otherwise False.
2031
32+ Examples:
33+ >>> neighbours = [0, 1, 0, 1, 0]
34+ >>> colored_vertices = [0, 2, 1, 2, 0]
2135 >>> color = 1
2236 >>> valid_coloring(neighbours, colored_vertices, color)
2337 True
2438
2539 >>> color = 2
2640 >>> valid_coloring(neighbours, colored_vertices, color)
2741 False
42+
43+ >>> neighbors = [1, 0, 1, 0]
44+ >>> colored_vertices = [-1, -1, -1, -1]
45+ >>> color = 0
46+ >>> valid_coloring(neighbors, colored_vertices, color)
47+ True
2848 """
29- # Does any neighbour not satisfy the constraints
49+ # Check if any adjacent vertex has already been colored with the same color
3050 return not any (
3151 neighbour == 1 and colored_vertices [i ] == color
3252 for i , neighbour in enumerate (neighbours )
@@ -37,7 +57,7 @@ def util_color(
3757 graph : list [list [int ]], max_colors : int , colored_vertices : list [int ], index : int
3858) -> bool :
3959 """
40- Pseudo-Code
60+ Recursive function to try and color the graph using backtracking.
4161
4262 Base Case:
4363 1. Check if coloring is complete
@@ -51,6 +71,18 @@ def util_color(
5171 2.4. if current coloring leads to a solution return
5272 2.5. Uncolor given vertex
5373
74+ Parameters:
75+ graph (list of list of int): Adjacency matrix representing the graph.
76+ graph[i][j] is 1 if there is an edge between vertex i and j.
77+ max_colors (int): Maximum number of colors allowed (m in the m-coloring problem).
78+ colored_vertices (list of int): Current color assignments for each vertex.
79+ -1 indicates that the vertex has not been colored yet.
80+ index (int): The current vertex index being processed.
81+
82+ Returns:
83+ bool: True if the graph can be colored using at most max_colors, otherwise False.
84+
85+ Examples:
5486 >>> graph = [[0, 1, 0, 0, 0],
5587 ... [1, 0, 1, 0, 1],
5688 ... [0, 1, 0, 1, 0],
@@ -67,47 +99,72 @@ def util_color(
6799 >>> util_color(graph, max_colors, colored_vertices, index)
68100 False
69101 """
70-
71- # Base Case
102+ # Base Case: If all vertices have been assigned a color, we have a valid solution
72103 if index == len (graph ):
73104 return True
74105
75- # Recursive Step
76- for i in range (max_colors ):
77- if valid_coloring ( graph [ index ], colored_vertices , i ):
78- # Color current vertex
79- colored_vertices [index ] = i
80- # Validate coloring
106+ # Try each color for the current vertex
107+ for color in range (max_colors ):
108+ # Check if it's valid to color the current vertex with 'color'
109+ if valid_coloring ( graph [ index ], colored_vertices , color ):
110+ colored_vertices [index ] = color # Assign color
111+ # Recur to color the rest of the vertices
81112 if util_color (graph , max_colors , colored_vertices , index + 1 ):
82113 return True
83- # Backtrack
114+ # Backtrack if no solution found with the current assignment
84115 colored_vertices [index ] = - 1
85- return False
116+
117+ return False # Return False if no valid coloring is possible
86118
87119
88120def color (graph : list [list [int ]], max_colors : int ) -> list [int ]:
89121 """
90- Wrapper function to call subroutine called util_color
91- which will either return True or False.
92- If True is returned colored_vertices list is filled with correct colorings
122+ Attempts to color the graph with at most max_colors colors such that no two adjacent
123+ vertices have the same color. If it is possible, returns the list of color assignments;
124+ otherwise, returns an empty list.
125+
126+ Parameters:
127+ graph (list of list of int): Adjacency matrix representing the graph.
128+ max_colors (int): Maximum number of colors allowed.
129+
130+ Returns:
131+ list of int: List of color assignments if the graph can be colored using max_colors.
132+ Each index in the list represents the color assigned to the corresponding vertex.
133+ If coloring is not possible, returns an empty list.
93134
135+ Examples:
94136 >>> graph = [[0, 1, 0, 0, 0],
95137 ... [1, 0, 1, 0, 1],
96138 ... [0, 1, 0, 1, 0],
97139 ... [0, 1, 1, 0, 0],
98140 ... [0, 1, 0, 0, 0]]
99-
100141 >>> max_colors = 3
101142 >>> color(graph, max_colors)
102143 [0, 1, 0, 2, 0]
103144
104145 >>> max_colors = 2
105146 >>> color(graph, max_colors)
106147 []
148+
149+ >>> graph = [[0, 1], [1, 0]] # Simple 2-node graph
150+ >>> max_colors = 2
151+ >>> color(graph, max_colors)
152+ [0, 1]
153+
154+ >>> graph = [[0, 1, 1], [1, 0, 1], [1, 1, 0]] # Complete graph of 3 vertices
155+ >>> max_colors = 2
156+ >>> color(graph, max_colors)
157+ []
158+
159+ >>> max_colors = 3
160+ >>> color(graph, max_colors)
161+ [0, 1, 2]
107162 """
163+ # Initialize all vertices as uncolored (-1)
108164 colored_vertices = [- 1 ] * len (graph )
109165
166+ # Use the utility function to try and color the graph starting from vertex 0
110167 if util_color (graph , max_colors , colored_vertices , 0 ):
111- return colored_vertices
168+ return colored_vertices # Return the successful color assignment
112169
113- return []
170+ return [] # Return an empty list if no valid coloring is possible
0 commit comments