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,64 @@ public static int[] findColoring(Graph graph) {
83
141
return colors ;
84
142
}
85
143
144
+ /** Helper method to check if a color is unassigned
145
+ *
146
+ * @param color the color to check
147
+ * @return {@code true} if the color is unassigned, {@code false} otherwise
148
+ */
86
149
private static boolean isBlank (int color ) {
87
150
return color == BLANK_COLOR ;
88
151
}
89
152
153
+ /** Checks if a vertex has adjacent colored vertices
154
+ *
155
+ * @param graph the input graph
156
+ * @param vertex the vertex to check
157
+ * @param colors the array of colors assigned to the vertices
158
+ * @return {@code true} if the vertex has adjacent colored vertices, {@code false} otherwise
159
+ */
90
160
private static boolean isAdjacentToColored (Graph graph , int vertex , int [] colors ) {
91
161
return graph .getAdjacencyList (vertex ).stream ().anyMatch (otherVertex -> !isBlank (colors [otherVertex ]));
92
162
}
93
163
164
+ /** Initializes the colors array with blank color
165
+ *
166
+ * @param numberOfVertices the number of vertices in the graph
167
+ * @return an array of integers representing the colors assigned to the vertices
168
+ */
94
169
private static int [] initializeColors (int numberOfVertices ) {
95
170
int [] colors = new int [numberOfVertices ];
96
171
Arrays .fill (colors , BLANK_COLOR );
97
172
return colors ;
98
173
}
99
174
175
+ /** Sorts the vertices by their degree in descending order
176
+ *
177
+ * @param graph the input graph
178
+ * @return an array of integers representing the vertices sorted by degree
179
+ */
100
180
private static Integer [] getSortedNodes (final Graph graph ) {
101
181
return IntStream .range (0 , graph .getNumVertices ()).boxed ().sorted (Comparator .comparingInt (v -> - graph .getAdjacencyList (v ).size ())).toArray (Integer [] ::new );
102
182
}
103
183
184
+ /** Computes the colors already used by the adjacent vertices
185
+ *
186
+ * @param graph the input graph
187
+ * @param vertex the vertex to check
188
+ * @param colors the array of colors assigned to the vertices
189
+ * @return an array of booleans representing the colors used by the adjacent vertices
190
+ */
104
191
private static boolean [] computeUsedColors (final Graph graph , final int vertex , final int [] colors ) {
105
192
boolean [] usedColors = new boolean [graph .getNumVertices ()];
106
193
graph .getAdjacencyList (vertex ).stream ().map (neighbor -> colors [neighbor ]).filter (color -> !isBlank (color )).forEach (color -> usedColors [color ] = true );
107
194
return usedColors ;
108
195
}
109
196
197
+ /** Finds the first unused color
198
+ *
199
+ * @param usedColors the array of colors used by the adjacent vertices
200
+ * @return the first unused color
201
+ */
110
202
private static int firstUnusedColor (boolean [] usedColors ) {
111
203
return IntStream .range (0 , usedColors .length ).filter (color -> !usedColors [color ]).findFirst ().getAsInt ();
112
204
}
0 commit comments