5
5
import java .util .HashSet ;
6
6
import java .util .stream .IntStream ;
7
7
8
- /*
9
- * The Welsh-Powell algorithm is a graph coloring algorithm
10
- * used for coloring a graph with the minimum number of colors.
11
- * https://en.wikipedia.org/wiki/Graph_coloring
8
+ /**
9
+ * The Welsh-Powell algorithm is a graph coloring algorithm that aims to color a graph
10
+ * using the minimum number of colors such that no two adjacent vertices share the same color.
11
+ *
12
+ * <p>
13
+ * The algorithm works by:
14
+ * <ol>
15
+ * <li>Sorting the vertices in descending order based on their degrees (number of edges connected).</li>
16
+ * <li>Iterating through each vertex and assigning it the smallest available color that has not been used by its adjacent vertices.</li>
17
+ * <li>Coloring adjacent vertices with the same color is avoided.</li>
18
+ * </ol>
19
+ * </p>
20
+ *
21
+ * <p>
22
+ * For more information, see <a href="https://en.wikipedia.org/wiki/Graph_coloring">Graph Coloring</a>.
23
+ * </p>
12
24
*/
13
-
14
25
public final class WelshPowell {
15
- private static final int BLANK_COLOR = -1 ; // Representing uncolored state
26
+ private static final int BLANK_COLOR = -1 ; // Constant representing an uncolored state
16
27
17
28
private WelshPowell () {
18
29
}
19
30
31
+ /**
32
+ * Represents a graph using an adjacency list.
33
+ */
20
34
static final class Graph {
21
- private HashSet <Integer >[] adjacencyLists ;
22
-
35
+ private final HashSet <Integer >[] adjacencyLists ;
36
+
37
+ /**
38
+ * Initializes a graph with a specified number of vertices.
39
+ *
40
+ * @param vertices the number of vertices in the graph
41
+ * @throws IllegalArgumentException if the number of vertices is negative
42
+ */
23
43
private Graph (int vertices ) {
24
44
if (vertices < 0 ) {
25
45
throw new IllegalArgumentException ("Number of vertices cannot be negative" );
@@ -29,6 +49,13 @@ private Graph(int vertices) {
29
49
Arrays .setAll (adjacencyLists , i -> new HashSet <>());
30
50
}
31
51
52
+ /**
53
+ * Adds an edge between two vertices in the graph.
54
+ *
55
+ * @param nodeA one end of the edge
56
+ * @param nodeB the other end of the edge
57
+ * @throws IllegalArgumentException if the vertices are out of bounds or if a self-loop is attempted
58
+ */
32
59
private void addEdge (int nodeA , int nodeB ) {
33
60
validateVertex (nodeA );
34
61
validateVertex (nodeB );
@@ -39,21 +66,46 @@ private void addEdge(int nodeA, int nodeB) {
39
66
adjacencyLists [nodeB ].add (nodeA );
40
67
}
41
68
69
+ /**
70
+ * Validates that the vertex index is within the bounds of the graph.
71
+ *
72
+ * @param vertex the index of the vertex to validate
73
+ * @throws IllegalArgumentException if the vertex is out of bounds
74
+ */
42
75
private void validateVertex (int vertex ) {
43
76
if (vertex < 0 || vertex >= getNumVertices ()) {
44
77
throw new IllegalArgumentException ("Vertex " + vertex + " is out of bounds" );
45
78
}
46
79
}
47
80
81
+ /**
82
+ * Returns the adjacency list for a specific vertex.
83
+ *
84
+ * @param vertex the index of the vertex
85
+ * @return the set of adjacent vertices
86
+ */
48
87
HashSet <Integer > getAdjacencyList (int vertex ) {
49
88
return adjacencyLists [vertex ];
50
89
}
51
90
91
+ /**
92
+ * Returns the number of vertices in the graph.
93
+ *
94
+ * @return the number of vertices
95
+ */
52
96
int getNumVertices () {
53
97
return adjacencyLists .length ;
54
98
}
55
99
}
56
100
101
+ /**
102
+ * Creates a graph with the specified number of vertices and edges.
103
+ *
104
+ * @param numberOfVertices the total number of vertices
105
+ * @param listOfEdges a 2D array representing edges where each inner array contains two vertex indices
106
+ * @return a Graph object representing the created graph
107
+ * @throws IllegalArgumentException if the edge array is invalid or vertices are out of bounds
108
+ */
57
109
public static Graph makeGraph (int numberOfVertices , int [][] listOfEdges ) {
58
110
Graph graph = new Graph (numberOfVertices );
59
111
for (int [] edge : listOfEdges ) {
@@ -65,6 +117,12 @@ public static Graph makeGraph(int numberOfVertices, int[][] listOfEdges) {
65
117
return graph ;
66
118
}
67
119
120
+ /**
121
+ * Finds the coloring of the given graph using the Welsh-Powell algorithm.
122
+ *
123
+ * @param graph the input graph to color
124
+ * @return an array of integers where each index represents a vertex and the value represents the color assigned
125
+ */
68
126
public static int [] findColoring (Graph graph ) {
69
127
int [] colors = initializeColors (graph .getNumVertices ());
70
128
Integer [] sortedVertices = getSortedNodes (graph );
@@ -83,30 +141,70 @@ public static int[] findColoring(Graph graph) {
83
141
return colors ;
84
142
}
85
143
144
+ /**
145
+ * Helper method to check if a color is unassigned
146
+ *
147
+ * @param color the color to check
148
+ * @return {@code true} if the color is unassigned, {@code false} otherwise
149
+ */
86
150
private static boolean isBlank (int color ) {
87
151
return color == BLANK_COLOR ;
88
152
}
89
153
154
+ /**
155
+ * Checks if a vertex has adjacent colored vertices
156
+ *
157
+ * @param graph the input graph
158
+ * @param vertex the vertex to check
159
+ * @param colors the array of colors assigned to the vertices
160
+ * @return {@code true} if the vertex has adjacent colored vertices, {@code false} otherwise
161
+ */
90
162
private static boolean isAdjacentToColored (Graph graph , int vertex , int [] colors ) {
91
163
return graph .getAdjacencyList (vertex ).stream ().anyMatch (otherVertex -> !isBlank (colors [otherVertex ]));
92
164
}
93
165
166
+ /**
167
+ * Initializes the colors array with blank color
168
+ *
169
+ * @param numberOfVertices the number of vertices in the graph
170
+ * @return an array of integers representing the colors assigned to the vertices
171
+ */
94
172
private static int [] initializeColors (int numberOfVertices ) {
95
173
int [] colors = new int [numberOfVertices ];
96
174
Arrays .fill (colors , BLANK_COLOR );
97
175
return colors ;
98
176
}
99
177
178
+ /**
179
+ * Sorts the vertices by their degree in descending order
180
+ *
181
+ * @param graph the input graph
182
+ * @return an array of integers representing the vertices sorted by degree
183
+ */
100
184
private static Integer [] getSortedNodes (final Graph graph ) {
101
185
return IntStream .range (0 , graph .getNumVertices ()).boxed ().sorted (Comparator .comparingInt (v -> - graph .getAdjacencyList (v ).size ())).toArray (Integer [] ::new );
102
186
}
103
187
188
+ /**
189
+ * Computes the colors already used by the adjacent vertices
190
+ *
191
+ * @param graph the input graph
192
+ * @param vertex the vertex to check
193
+ * @param colors the array of colors assigned to the vertices
194
+ * @return an array of booleans representing the colors used by the adjacent vertices
195
+ */
104
196
private static boolean [] computeUsedColors (final Graph graph , final int vertex , final int [] colors ) {
105
197
boolean [] usedColors = new boolean [graph .getNumVertices ()];
106
198
graph .getAdjacencyList (vertex ).stream ().map (neighbor -> colors [neighbor ]).filter (color -> !isBlank (color )).forEach (color -> usedColors [color ] = true );
107
199
return usedColors ;
108
200
}
109
201
202
+ /**
203
+ * Finds the first unused color
204
+ *
205
+ * @param usedColors the array of colors used by the adjacent vertices
206
+ * @return the first unused color
207
+ */
110
208
private static int firstUnusedColor (boolean [] usedColors ) {
111
209
return IntStream .range (0 , usedColors .length ).filter (color -> !usedColors [color ]).findFirst ().getAsInt ();
112
210
}
0 commit comments