Repository navigation
Expand file tree
/
Copy pathThreeTenColor.java
More file actions
321 lines (243 loc) · 7.63 KB
/
Copy pathThreeTenColor.java
File metadata and controls
321 lines (243 loc) · 7.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.EdgeType;
import java.awt.Color;
import javax.swing.JPanel;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.LinkedList;
/**
* Simulation of our coloring algorithm.
*
*/
class ThreeTenColor implements ThreeTenAlg {
/**
* The graph the algorithm will run on.
*/
Graph<GraphNode, GraphEdge> graph;
/**
* The priority queue of nodes for the algorithm.
*/
WeissPriorityQueue<GraphNode> queue;
/**
* The stack of nodes for the algorithm.
*/
LinkedList<GraphNode> stack;
/**
* Whether or not the algorithm has been started.
*/
private boolean started = false;
/**
* Whether or not the algorithm is in the coloring stage or not.
*/
private boolean coloring = false;
/**
* The color when a node has "no color".
*/
public static final Color COLOR_NONE_NODE = Color.WHITE;
/**
* The color when an edge has "no color".
*/
public static final Color COLOR_NONE_EDGE = Color.BLACK;
/**
* The color when a node is inactive.
*/
public static final Color COLOR_INACTIVE_NODE = Color.LIGHT_GRAY;
/**
* The color when an edge is inactive.
*/
public static final Color COLOR_INACTIVE_EDGE = Color.LIGHT_GRAY;
/**
* The color when a node is highlighted.
*/
public static final Color COLOR_HIGHLIGHT = new Color(255,204,51);
/**
* The color when a node is in warning.
*/
public static final Color COLOR_WARNING = new Color(255,51,51);
/**
* The colors used to assign to nodes.
*/
public static final Color[] COLORS =
{Color.PINK, Color.GREEN, Color.CYAN, Color.ORANGE,
Color.MAGENTA, Color.YELLOW, Color.DARK_GRAY, Color.BLUE};
/**
* {@inheritDoc}
*/
public EdgeType graphEdgeType() {
return EdgeType.UNDIRECTED;
}
/**
* {@inheritDoc}
*/
public void reset(Graph<GraphNode, GraphEdge> graph) {
this.graph = graph;
started = false;
coloring = false;
}
/**
* {@inheritDoc}
*/
public boolean isStarted() {
return started;
}
/**
* {@inheritDoc}
*/
public void start() {
this.started = true;
//create an empty stack
stack = new LinkedList<>();
//create an empty priority queue
queue = new WeissPriorityQueue<>();
for(GraphNode v : graph.getVertices()) {
//Set the cost of each node to be its degree
v.setCost(graph.degree(v));
//Set each node to be active
//This enables the display of cost for the node
v.setActive();
//add node into queue
queue.add(v);
}
//highlight the current node with max priority
highlightNextMax();
}
/**
* {@inheritDoc}
*/
public void finish() {
// Coloring completed. Set all edges back to "no color".
for (GraphEdge e: graph.getEdges()){
e.setColor(COLOR_NONE_EDGE);
}
}
/**
* {@inheritDoc}
*/
public void cleanUpLastStep() {
}
/**
* {@inheritDoc}
*/
public boolean setupNextStep() {
if (coloring && stack.size() == 0)
return false;
if (!coloring && graph.getVertexCount() == stack.size()){
coloring = true;
}
return true;
}
/**
* {@inheritDoc}
*/
public void doNextStep() {
if (!coloring){
//Stage 1: pushing nodes into stack one by one & update record
// maxNode is the active node with the highest priority
// Remove the maxNode from priority queue and push it into stack
GraphNode maxNode = findMax();
//Update the cost of all nodes that is a neighbor of the maxNode
updateNeighborCost(maxNode);
//Identify and highlight the next max node in the updated priority queue
highlightNextMax();
}
else{
//Stage 2: pop nodes from stack one by one and choose a color for each
//Pop off stack top
GraphNode node = stack.pop();
//For the node popped off, pick a color that is different from all
//neighbors who has got assigned a color so far
Color newColor = chooseColor(node);
//Inform all neighbors of this node the selected color
updateColor(node, newColor);
}
}
/**
* Highlights the next
* node in the priority Queue.
*/
public void highlightNextMax(){
queue.element().color = COLOR_HIGHLIGHT;
}
/**
* Removes the next node with the highest priority in the queue
* and pushes the node into a separate stack and setting the node
* and its incident edges to INACTIVE.
*
* @return the max priority node that was removed
*/
public GraphNode findMax(){
if(queue.size() == 0) {
return null;
}
GraphNode removed = queue.remove();
stack.push(removed);
removed.unsetActive();
removed.color = COLOR_INACTIVE_NODE;
for (GraphEdge currrentEdge : graph.getIncidentEdges(removed)) {
currrentEdge.color = COLOR_INACTIVE_EDGE;
}
return removed;
}
/**
* Update the cost (node neighbors) of the current
* max node (node with the highest priority) with the newest cost.
*
* @param maxNode the highest priority node
*/
public void updateNeighborCost(GraphNode maxNode){
int cost = 0;
for (GraphNode currentNode : graph.getNeighbors(maxNode)) {
if (currentNode.isActive()) {
cost++;
}
}
maxNode.setCost(cost);
}
/**
* Changes the color of a current node that isn't
* the same as any of its neighbors and is in the lowest possible index
* in the COLORS' arrays.
*
* @param node current node
* @return the color chosen or COLOR_WARNING if no color is available
*/
public Color chooseColor(GraphNode node){
if(node == null) {
return null;
}
List<Color> colors = new LinkedList<>();
colors.addAll(List.of(COLORS));
for (GraphNode current : graph.getNeighbors(node)) {
colors.remove(current.color);
}
if(colors.isEmpty()) {
return COLOR_WARNING;
}
for (int i = 0; i < COLORS.length; i++) {
if (colors.get(0) == COLORS[i]) {
node.setNbrColor(i);
return COLORS[i];
}
}
return null;
}
/**
* Changes the color of the node being passed in the method by the color
* being passed.
*
* @param node to update
* @param newColor the color to set node to
*/
public void updateColor(GraphNode node, Color newColor){
if (newColor == null || node == null) {
return;
}
node.color = newColor;
for (GraphEdge curr : graph.getIncidentEdges(node)) {
if (curr.getColor() == null || curr.color == Color.BLACK) {
curr.color = newColor;
}
}
}
}