Skip to content

Commit 46d4564

Browse files
committed
Polishing BFS
1 parent 5f26faf commit 46d4564

File tree

2 files changed

+93
-105
lines changed

2 files changed

+93
-105
lines changed

src/algorithms/controllers/BFS.js

Lines changed: 73 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,7 @@
22
// XXX see README_graph_search
33
import GraphTracer from '../../components/DataStructures/Graph/GraphTracer';
44
import Array2DTracer from '../../components/DataStructures/Array/Array2DTracer';
5-
6-
// Colors for array, graph nodes, graph edges
7-
// OMG, colors for array and graph require different types and are
8-
// inconsistent!
9-
// XXX not sure how this interracts with color perception options -
10-
// doesnt seem to work like this
11-
// XXX should do similar for edge colors?
12-
const FRONTIER_COLOR_A = '0'; // Blue
13-
const FRONTIER_COLOR_N = 4; // Blue
14-
const FRONTIER_COLOR_E = 4; // Blue
15-
const N_M_COLOR_E = 2; // Orange - edge between n and m
16-
const FINALISED_COLOR_A = '1'; // Green
17-
const FINALISED_COLOR_N = 1; // Green
18-
const FINALISED_COLOR_E = 3; // Red
19-
// if we find a path to end node:
20-
const SUCCESS_COLOR_A = '1'; // Green
21-
const SUCCESS_COLOR_E = 1; // Green
5+
import {colors} from './graphSearchColours';
226

237
export default {
248
initVisualisers() {
@@ -31,8 +15,6 @@ export default {
3115
instance: new Array2DTracer('array', null, 'Parent array, Seen array & Queue'),
3216
order: 1,
3317
},
34-
35-
3618
};
3719
},
3820

@@ -145,7 +127,7 @@ export default {
145127

146128
// select start node in blue
147129
vis.array.select(0,b + 1);
148-
vis.graph.colorNode(b, FRONTIER_COLOR_N);
130+
vis.graph.colorNode(b, colors.FRONTIER_N);
149131
},
150132
[[displayedNodes, displayedParent, displayedVisited], displayedQueue, explored, visited, s, Nodes]
151133
);
@@ -166,23 +148,28 @@ export default {
166148
);
167149

168150
// while Nodes not empty B2
169-
while (Nodes.length > 0) {
151+
// XXX ?nice to have while true and break out of the
152+
// loop after the chunk (conditionally) so when the loop exits
153+
// we have an extra chunk at the start of the loop
154+
// while (Nodes.length > 0) {
155+
/* eslint-disable no-constant-condition */
156+
while (true) {
170157
chunker.add(
171158
2,
172159
(vis, c_n, c_lastNei, c_parent, c_visited, c_Nodes) => {
173160
// removes m if it exists; need to redo node selection etc
174-
// for green nodes:(
161+
// for green nodes:
175162
vis.array.assignVariable('m', 2, undefined); // removes m if there
176163
// highlight all nodes explored in green in the array
177164
// and all other seen nodes in blue in the array
178165
for(let i = 0; i < c_visited.length; i++)
179166
{
180167
if(c_visited[i] == true)
181168
if(!c_Nodes.includes(i)) {
182-
vis.array.select(0, i + 1, 0, i + 1, FINALISED_COLOR_A);
169+
vis.array.select(0, i + 1, 0, i + 1, colors.FINALISED_A);
183170
} else {
184171
// vis.array.deselect(0, i + 1);
185-
vis.array.select(0, i + 1, 0, i + 1, FRONTIER_COLOR_A);
172+
vis.array.select(0, i + 1, 0, i + 1, colors.FRONTIER_A);
186173
}
187174
}
188175

@@ -193,24 +180,17 @@ export default {
193180
vis.graph.removeEdgeColor(c_n, c_lastNei);
194181
let prevColor;
195182
if (c_Nodes.includes(c_lastNei))
196-
prevColor = FRONTIER_COLOR_E;
183+
prevColor = colors.FRONTIER_E;
197184
else
198-
prevColor = FINALISED_COLOR_E;
185+
prevColor = colors.FINALISED_E;
199186
vis.graph.removeEdgeColor(c_n, c_lastNei);
200187
vis.graph.colorEdge(c_n, c_lastNei, prevColor);
201188
}
202-
203-
// // recolor in red if it has a child
204-
// for(let i = 0; i < c_parent.length; i ++){
205-
// if (c_parent[i] == c_lastNei){
206-
// vis.graph.removeEdgeColor(i, c_lastNei);
207-
// vis.graph.colorEdge(i, c_lastNei, FRONTIER_COLOR_E);
208-
// }
209-
// }
210189
},
211190
[n, lastNeighbor, parent, visited, Nodes]
212-
213191
);
192+
if (!(Nodes.length > 0))
193+
break;
214194

215195
// n <- dequeue(Nodes) B10
216196
n = Nodes.shift();
@@ -226,7 +206,7 @@ export default {
226206
// highlight all frontier nodes
227207
for (let i = 0; i < a.length; i ++){
228208
if(a[i] == true && Nodes.includes(i)){
229-
vis.array.select(0,i + 1, 0, i + 1, FRONTIER_COLOR_A);
209+
vis.array.select(0,i + 1, 0, i + 1, colors.FRONTIER_A);
230210
// vis.array.select(0,i + 1, 0, i + 1, '1');
231211

232212
}
@@ -237,23 +217,23 @@ export default {
237217
{
238218
if(b[i] == true && !Nodes.includes(i))
239219
{
240-
vis.array.select(0, i + 1, 0, i + 1, FINALISED_COLOR_A);
220+
vis.array.select(0, i + 1, 0, i + 1, colors.FINALISED_A);
241221
vis.graph.removeNodeColor(i);
242-
vis.graph.colorNode(i, FINALISED_COLOR_N);
222+
vis.graph.colorNode(i, colors.FINALISED_N);
243223
}
244224
}
245225

246226
// finalise edge color to n from parent
247227
if (c_parent[c_n] !== null) {
248228
vis.graph.removeEdgeColor(c_n, c_parent[c_n]);
249-
vis.graph.colorEdge(c_n, c_parent[c_n], FINALISED_COLOR_E);
229+
vis.graph.colorEdge(c_n, c_parent[c_n], colors.FINALISED_E);
250230
}
251231

252232
//redisplay queue
253233
vis.array.setList(z);
254234
},
255235
[[displayedNodes, displayedParent, displayedVisited], n,
256-
displayedQueue, explored, visited, parent, Nodes]
236+
displayedQueue, explored, visited, parent, Nodes]
257237
);
258238

259239
// If is_end_node(n) B11
@@ -276,14 +256,14 @@ displayedQueue, explored, visited, parent, Nodes]
276256
if(c_parent[y] != null)
277257
{
278258
vis.graph.removeEdgeColor(c_parent[y], y);
279-
vis.graph.colorEdge(c_parent[y], y , FRONTIER_COLOR_E);
259+
vis.graph.colorEdge(c_parent[y], y , colors.FRONTIER_E);
280260
}
281261

282262
// recolor in red if it has a child
283263
for(let i = 0; i < c_parent.length; i ++){
284264
if (c_parent[i] == y){
285265
vis.graph.removeEdgeColor(i, y);
286-
vis.graph.colorEdge(i, y, FRONTIER_COLOR_E);
266+
vis.graph.colorEdge(i, y, colors.FRONTIER_E);
287267
}
288268
}
289269
}
@@ -301,9 +281,9 @@ displayedQueue, explored, visited, parent, Nodes]
301281
// + color parent array
302282
while((current != a) && (c_parent[current] != null))
303283
{
304-
vis.array.select(1, current + 1, 1, current + 1, SUCCESS_COLOR_A);
284+
vis.array.select(1, current + 1, 1, current + 1, colors.SUCCESS_A);
305285
vis.graph.removeEdgeColor(current, c_parent[current]);
306-
vis.graph.colorEdge(current, c_parent[current], SUCCESS_COLOR_E);
286+
vis.graph.colorEdge(current, c_parent[current], colors.SUCCESS_E);
307287
current = c_parent[current];
308288
}
309289
},
@@ -334,27 +314,17 @@ displayedQueue, explored, visited, parent, Nodes]
334314
// recolor if node has a parent or is start
335315
if(c_parent[c_lastNei] != null || c_lastNei == start) {
336316
vis.graph.removeEdgeColor(c_n, c_lastNei);
337-
// XXX if not just added or previously FINALISED_COLOR_E
338317
if (c_parent[c_n] === c_lastNei)
339-
vis.graph.colorEdge(c_n, c_lastNei, FINALISED_COLOR_E);
318+
vis.graph.colorEdge(c_n, c_lastNei, colors.FINALISED_E);
340319
else if (c_parent[c_lastNei] === c_n)
341-
vis.graph.colorEdge(c_n, c_lastNei, FRONTIER_COLOR_E);
320+
vis.graph.colorEdge(c_n, c_lastNei, colors.FRONTIER_E);
342321
}
343-
344-
// recolor in red if it has a child
345-
// for(let i = 0; i < c_parent.length; i ++){
346-
// if (c_parent[i] == c_lastNei){
347-
// vis.graph.removeEdgeColor(i, c_lastNei);
348-
// vis.graph.colorEdge(i, c_lastNei, FRONTIER_COLOR_E);
349-
// }
350-
// }
351-
352322
}
353323

354324
//highlight the edge connecting the neighbor
355325
vis.graph.removeEdgeColor(c_n,c_m);
356326
// color 2 = orange doesn't show up well - 4 = green better?
357-
vis.graph.colorEdge(c_n, c_m, N_M_COLOR_E);
327+
vis.graph.colorEdge(c_n, c_m, colors.N_M_E);
358328

359329
// add var m; need to color elements again
360330
vis.array.assignVariable('m', 2, c_m + 1);
@@ -364,10 +334,10 @@ displayedQueue, explored, visited, parent, Nodes]
364334
{
365335
if(c_visited[i] == true)
366336
if(!c_Nodes.includes(i)) {
367-
vis.array.select(0, i + 1, 0, i + 1, FINALISED_COLOR_A);
337+
vis.array.select(0, i + 1, 0, i + 1, colors.FINALISED_A);
368338
} else {
369339
// vis.array.deselect(0, i + 1);
370-
vis.array.select(0, i + 1, 0, i + 1, FRONTIER_COLOR_A);
340+
vis.array.select(0, i + 1, 0, i + 1, colors.FRONTIER_A);
371341
}
372342
}
373343
},
@@ -404,17 +374,17 @@ displayedQueue, explored, visited, parent, Nodes]
404374
{
405375
if(c_visited[i] == true)
406376
if(!(c_Nodes.includes(i) || i === c_m)) {
407-
vis.array.select(0, i + 1, 0, i + 1, FINALISED_COLOR_A);
377+
vis.array.select(0, i + 1, 0, i + 1, colors.FINALISED_A);
408378
} else {
409379
// vis.array.deselect(0, i + 1);
410-
vis.array.select(0, i + 1, 0, i + 1, FRONTIER_COLOR_A);
380+
vis.array.select(0, i + 1, 0, i + 1, colors.FRONTIER_A);
411381
}
412382
}
413383
vis.array.setList(y);
414384

415385
// color the graph node in blue as seen
416386
vis.graph.removeNodeColor(c_m);
417-
vis.graph.colorNode(c_m, FRONTIER_COLOR_N);
387+
vis.graph.colorNode(c_m, colors.FRONTIER_N);
418388
},
419389

420390
[[displayedNodes, displayedParent, displayedVisited], displayedQueue, explored, visited, n, m, Nodes]
@@ -440,10 +410,10 @@ displayedQueue, explored, visited, parent, Nodes]
440410
{
441411
if(z[i] == true || i === c)
442412
if(i !==c && !Nodes.includes(i)) {
443-
vis.array.select(0, i + 1, 0, i + 1, FINALISED_COLOR_A);
413+
vis.array.select(0, i + 1, 0, i + 1, colors.FINALISED_A);
444414
} else {
445415
// vis.array.deselect(0, i + 1);
446-
vis.array.select(0, i + 1, 0, i + 1, FRONTIER_COLOR_A);
416+
vis.array.select(0, i + 1, 0, i + 1, colors.FRONTIER_A);
447417
}
448418
}
449419
vis.array.setList(y);
@@ -453,7 +423,7 @@ displayedQueue, explored, visited, parent, Nodes]
453423

454424
//highlight the edge from n to this neighbor in red
455425
vis.graph.removeEdgeColor(b, c);
456-
vis.graph.colorEdge(b, c, FRONTIER_COLOR_E);
426+
vis.graph.colorEdge(b, c, colors.FRONTIER_E);
457427

458428

459429
// vis.array.set(x, 'BFS');
@@ -476,7 +446,7 @@ displayedQueue, explored, visited, parent, Nodes]
476446
// if it has not been seen
477447
if(y[z] == false && Nodes.includes(z)){
478448
vis.array.deselect(0, z + 1);
479-
vis.array.select(0, z + 1, 0, z + 1, FINALISED_COLOR_A);
449+
vis.array.select(0, z + 1, 0, z + 1, colors.FINALISED_A);
480450
//vis.graph.removeNodeColor(z);
481451
//vis.graph.colorNode(z, 4);
482452
}
@@ -490,50 +460,48 @@ displayedQueue, explored, visited, parent, Nodes]
490460
}
491461
// no path found
492462
//return B5
493-
chunker.add(
494-
5,
495-
(vis, x, y, z, a, b) => {
496-
//remove the orange highlight from the last neighbour
497-
// XXX not needed?
498-
if (y != null)
499-
{
500-
vis.graph.removeEdgeColor(y, x);
501-
502-
// recolor in red if it has a parent
503-
if(z[y] != null)
463+
chunker.add(
464+
5,
465+
(vis, c_n, c_lastNei, c_parent, c_visited, c_Nodes) => {
466+
// We don't actually need to do anything here if we have a
467+
// chunk before breaking out of the outer while loop, but
468+
// it does no harm and we need to fix one edge color at
469+
// least if we don't use the break coding.
470+
//
471+
// removes m if it exists; need to redo node selection etc
472+
// for green nodes:
473+
vis.array.assignVariable('m', 2, undefined); // removes m if there
474+
// highlight all nodes explored in green in the array
475+
// and all other seen nodes in blue in the array
476+
for(let i = 0; i < c_visited.length; i++)
504477
{
505-
vis.graph.removeEdgeColor(z[y], y);
506-
vis.graph.colorEdge(z[y], y , FRONTIER_COLOR_E);
507-
}
508-
509-
// recolor in red if it has a child
510-
for(let i = 0; i < z.length; i ++){
511-
if (z[i] == y){
512-
vis.graph.removeEdgeColor(i, y);
513-
vis.graph.colorEdge(i, y, FRONTIER_COLOR_E);
514-
}
478+
if(c_visited[i] == true)
479+
if(!c_Nodes.includes(i)) {
480+
vis.array.select(0, i + 1, 0, i + 1, colors.FINALISED_A);
481+
} else {
482+
// vis.array.deselect(0, i + 1);
483+
vis.array.select(0, i + 1, 0, i + 1, colors.FRONTIER_A);
484+
}
515485
}
516-
}
517-
},
518-
[n, lastNeighbor, parent, start, end]
519486

520-
) ;
521-
}; // End of bfs
487+
// remove the highlight between n
488+
// and the last visited neighbor
489+
if((c_n != null) && (c_lastNei != null)){
522490

491+
vis.graph.removeEdgeColor(c_n, c_lastNei);
492+
let prevColor;
493+
if (c_Nodes.includes(c_lastNei))
494+
prevColor = colors.FRONTIER_E;
495+
else
496+
prevColor = colors.FINALISED_E;
497+
vis.graph.removeEdgeColor(c_n, c_lastNei);
498+
vis.graph.colorEdge(c_n, c_lastNei, prevColor);
499+
}
500+
},
501+
[n, lastNeighbor, parent, visited, Nodes]
502+
);
503+
}; // End of bfs
523504

524505
bfs(start);
525-
526506
}
527-
528507
};
529-
530-
// green vis.array.select(0, i + 1, 0, i + 1, '1');
531-
// blue vis.array.select(0,i + 1);
532-
// red vis.array.select(0, i + 1, 0, i + 1, '4');
533-
// for (let i = 0; i < numVertices; i++) { // For each vertex v
534-
// if (!visited[i]) { // If v is not Seen
535-
// bfs(i); // Call BFS starting from v
536-
// }
537-
// }
538-
// }
539-
// };
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Colors for array (..._A), graph nodes (..._N), graph edges (..._E)
2+
// for graph search/traversal algorithms (+ Prim's eventually)
3+
//
4+
// OMG, colors for array and graph require different types and are
5+
// inconsistent!
6+
// XXX not sure how this interracts with color perception options -
7+
// doesn't seem to work like this - should figure out how it's done if
8+
// it's still supported
9+
export const colors = {
10+
FRONTIER_A: '0', // Blue
11+
FRONTIER_N: 4, // Blue
12+
FRONTIER_E: 4, // Blue
13+
N_M_E: 2, // Orange - edge between n and m
14+
FINALISED_A: '1', // Green
15+
FINALISED_N: 1, // Green
16+
FINALISED_E: 3, // Red
17+
// if we find a path to end node:
18+
SUCCESS_A: '1', // Green
19+
SUCCESS_E: 1, // Green
20+
}

0 commit comments

Comments
 (0)