1
- // XXX termination when there is no end node needs fixing
2
- // XXX add extra highlighting of code etc for UpdateNodes, like BFS
3
1
// XXX add support for multiple end nodes
4
2
import GraphTracer from '../../components/DataStructures/Graph/GraphTracer' ;
5
3
import Array2DTracer from '../../components/DataStructures/Array/Array2DTracer' ;
@@ -40,6 +38,14 @@ export default {
40
38
const finalCosts = [ ] ;
41
39
const start = startNode - 1 ;
42
40
const end = endNodes [ 0 ] - 1 ;
41
+
42
+ // Display has table [nodes, parents, minCosts, finalCosts]
43
+ // and display code indexes into this table; we define the indices here
44
+ const NODE = 0 ;
45
+ const PAR = 1 ;
46
+ const MCOST = 2 ;
47
+ const FCOST = 3 ;
48
+
43
49
// Create a set to keep track of visited vertices
44
50
const visited = new Set ( ) ;
45
51
let miniIndex = start ;
@@ -89,20 +95,20 @@ export default {
89
95
90
96
// highlight nodes as finalised/frontier in array
91
97
for ( let i = 0 ; i < numVertices ; i ++ ) {
92
- if ( c_nodes_etc [ 2 ] [ i + 1 ] === null ) {
93
- vis . array . select ( 0 , i + 1 , 0 , i + 1 , colors . FINALISED_A ) ;
98
+ if ( c_nodes_etc [ MCOST ] [ i + 1 ] === null ) {
99
+ vis . array . select ( NODE , i + 1 , NODE , i + 1 , colors . FINALISED_A ) ;
94
100
vis . graph . removeNodeColor ( i ) ;
95
101
vis . graph . colorNode ( i , colors . FINALISED_N ) ;
96
- } else if ( isNumber ( c_nodes_etc [ 2 ] [ i + 1 ] ) ) {
97
- vis . array . select ( 0 , i + 1 , 0 , i + 1 , colors . FRONTIER_A ) ;
102
+ } else if ( isNumber ( c_nodes_etc [ MCOST ] [ i + 1 ] ) ) {
103
+ vis . array . select ( NODE , i + 1 , NODE , i + 1 , colors . FRONTIER_A ) ;
98
104
vis . graph . removeNodeColor ( i ) ;
99
105
vis . graph . colorNode ( i , colors . FRONTIER_N ) ;
100
106
}
101
107
}
102
108
103
109
// color Min in PQ
104
110
if ( c_Min != null )
105
- vis . array . select ( 2 , c_Min + 1 , 2 , c_Min + 1 , colors . PQ_MIN_A ) ;
111
+ vis . array . select ( MCOST , c_Min + 1 , MCOST , c_Min + 1 , colors . PQ_MIN_A ) ;
106
112
}
107
113
108
114
chunker . add (
@@ -159,20 +165,27 @@ export default {
159
165
chunker . add (
160
166
7 ,
161
167
( vis , v , w ) => {
168
+ // re-render table with new cost
162
169
vis . array . set ( v , algNameStr ) ;
163
- vis . array . assignVariable ( minStr , 2 , w + 1 ) ;
164
- vis . array . select ( 2 , w + 1 , 2 , w + 1 , colors . PQ_MIN_A ) ;
165
-
166
170
// color start node in array + graph
167
- vis . array . select ( 0 , w + 1 , 0 , w + 1 , colors . FRONTIER_A ) ;
171
+ vis . array . select ( NODE , w + 1 , NODE , w + 1 , colors . FRONTIER_A ) ;
168
172
vis . graph . colorNode ( w , colors . FRONTIER_N ) ;
169
-
170
173
} ,
171
174
[ [ nodes , parents , minCosts , finalCosts ] , start ]
172
175
) ;
173
176
174
177
// Nodes <- PQ containing all nodes
175
- chunker . add ( 8 ) ;
178
+ chunker . add (
179
+ 8 ,
180
+ ( vis , v , w ) => {
181
+ // add min to display
182
+ vis . array . set ( v , algNameStr ) ;
183
+ vis . array . assignVariable ( minStr , 2 , w + 1 ) ;
184
+ vis . array . select ( MCOST , w + 1 , MCOST , w + 1 , colors . PQ_MIN_A ) ;
185
+ vis . array . select ( NODE , w + 1 , NODE , w + 1 , colors . FRONTIER_A ) ;
186
+ } ,
187
+ [ [ nodes , parents , minCosts , finalCosts ] , start ]
188
+ ) ;
176
189
177
190
let currentVertex = null ;
178
191
// while Nodes not Empty
@@ -187,35 +200,30 @@ export default {
187
200
2 ,
188
201
( vis , c_nodes_etc , c_miniIndex , c_last , c_prev , c_cV ) => {
189
202
refresh ( vis , c_nodes_etc , c_miniIndex , c_cV , null ) ;
190
- // visit1(x,y,2) highlights the edge xy,and nodes x and y
191
- // in the 2nd color
192
- // leave1(x,y,2) removes the highlight on nodes x, y and
193
- // edge xy(placed by the visit1 function in the 2nd color)
203
+
194
204
if ( c_last [ 0 ] != null ) {
195
205
vis . graph . removeEdgeColor ( c_last [ 0 ] , c_last [ 1 ] ) ;
196
-
197
-
198
206
199
207
// restore the original color of the edge
200
- if ( c_prev [ c_last [ 0 ] ] != null && c_nodes_etc [ 3 ] [ c_last [ 0 ] + 1 ] == dashStr )
208
+ if ( c_prev [ c_last [ 0 ] ] != null && c_nodes_etc [ FCOST ] [ c_last [ 0 ] + 1 ] == dashStr )
201
209
{
202
210
vis . graph . removeEdgeColor ( c_prev [ c_last [ 0 ] ] , c_last [ 0 ] ) ;
203
211
vis . graph . colorEdge ( c_prev [ c_last [ 0 ] ] , c_last [ 0 ] , colors . FRONTIER_E ) ;
204
212
}
205
213
206
- if ( c_prev [ c_last [ 1 ] ] != null && c_nodes_etc [ 3 ] [ c_last [ 1 ] + 1 ] == dashStr )
214
+ if ( c_prev [ c_last [ 1 ] ] != null && c_nodes_etc [ FCOST ] [ c_last [ 1 ] + 1 ] == dashStr )
207
215
{
208
216
vis . graph . removeEdgeColor ( c_prev [ c_last [ 1 ] ] , c_last [ 1 ] ) ;
209
217
vis . graph . colorEdge ( c_prev [ c_last [ 1 ] ] , c_last [ 1 ] , colors . FRONTIER_E ) ;
210
218
}
211
219
212
- if ( c_nodes_etc [ 3 ] [ c_last [ 0 ] + 1 ] != dashStr )
220
+ if ( c_nodes_etc [ FCOST ] [ c_last [ 0 ] + 1 ] != dashStr )
213
221
{
214
222
vis . graph . removeEdgeColor ( c_prev [ c_last [ 0 ] ] , c_last [ 0 ] ) ;
215
223
vis . graph . colorEdge ( c_prev [ c_last [ 0 ] ] , c_last [ 0 ] , colors . FINALISED_E ) ;
216
224
}
217
225
218
- if ( c_nodes_etc [ 3 ] [ c_last [ 1 ] + 1 ] != dashStr )
226
+ if ( c_nodes_etc [ FCOST ] [ c_last [ 1 ] + 1 ] != dashStr )
219
227
{
220
228
vis . graph . removeEdgeColor ( c_prev [ c_last [ 1 ] ] , c_last [ 1 ] ) ;
221
229
vis . graph . colorEdge ( c_prev [ c_last [ 1 ] ] , c_last [ 1 ] , colors . FINALISED_E ) ;
@@ -226,8 +234,10 @@ export default {
226
234
} ,
227
235
[ [ nodes , parents , minCosts , finalCosts ] , miniIndex , last , prev , currentVertex ]
228
236
) ;
229
- if ( ! ( visited . size < numVertices ) )
237
+ if ( ! ( visited . size < numVertices ) ) {
238
+ chunker . add ( 99 ) ; // return at end of function
230
239
break ;
240
+ }
231
241
232
242
// Find the unvisited vertex with the smallest cost
233
243
@@ -245,24 +255,11 @@ export default {
245
255
chunker . add (
246
256
9 ,
247
257
( vis , c_nodes_etc , c_miniIndex , c_cV , c_prev_cV ) => {
248
- // color graph node
249
- //vis.graph.colorNode(c_cV, colors.FINALISED_N);
250
-
251
- // reset
258
+ // reset previous highlight if any
252
259
if ( c_prev_cV != null ) {
253
260
vis . graph . removeEdgeColor ( c_prev_cV , c_cV ) ;
254
- // vis.graph.colorNode(c_prev_cV, 1);
255
- // vis.graph.colorEdge(c_prev_cV, c_cV, 1);
256
261
vis . graph . colorEdge ( c_prev_cV , c_cV , colors . FINALISED_E ) ;
257
- //vis.graph.deselect(y, x);
258
- //vis.graph.select(y, y);
259
- //vis.graph.visit1(y, x, 1);
260
- //vis.graph.leave1(x, x, 1);
261
- //vis.graph.leave1(y, y, 1);
262
262
}
263
- // vis.graph.colorNode(c_cV, 1);
264
- //vis.graph.select(x, x);
265
-
266
263
refresh ( vis , c_nodes_etc , c_miniIndex , c_cV , null ) ;
267
264
} ,
268
265
[ [ nodes , parents , minCosts , finalCosts ] , miniIndex ,
@@ -272,14 +269,45 @@ export default {
272
269
// If we can't find a reachable vertex, exit
273
270
// if is_end_node(n) or Cost[n] = infinity
274
271
chunker . add ( 10 ) ;
275
- if ( currentVertex === null || currentVertex === end ||
276
- cost [ currentVertex ] === Infinity ) {
272
+ if ( currentVertex === null // || currentVertex === end
273
+ || cost [ currentVertex ] === Infinity ) {
274
+ // terminate without finding end node
277
275
chunker . add ( 3 ) ;
278
276
// return
279
277
break ;
280
278
}
279
+ if ( currentVertex === end ) {
280
+ // found end node - highlight path
281
+ chunker . add ( 3 ,
282
+ ( vis , c_nodes_etc ) => {
283
+ // remove n, add start and end
284
+ vis . array . set ( c_nodes_etc , 'BFS' ) ;
285
+ vis . array . assignVariable ( 'n' , 2 , null ) ;
286
+ vis . array . assignVariable ( 'end' , 2 , end + 1 ) ;
287
+ vis . array . assignVariable ( 'start' , 2 , start + 1 ) ;
288
+ // remove color from node numbers
289
+ for ( let i = 0 ; i < c_nodes_etc [ NODE ] . length ; i ++ ) {
290
+ vis . array . deselect ( 0 , i ) ;
291
+ }
292
+ // color the path from the start node to the end node
293
+ // + color nodes and parent array
294
+ let current = end ;
295
+ while ( ( current != start ) && ( c_nodes_etc [ PAR ] [ current + 1 ] != null ) )
296
+ {
297
+ vis . array . select ( NODE , current + 1 , NODE , current + 1 , colors . SUCCESS_A ) ;
298
+ vis . array . select ( PAR , current + 1 , PAR , current + 1 , colors . SUCCESS_A ) ;
299
+ vis . graph . removeEdgeColor ( current , c_nodes_etc [ PAR ] [ current + 1 ] - 1 ) ;
300
+ vis . graph . colorEdge ( current , c_nodes_etc [ PAR ] [ current + 1 ] - 1 , colors . SUCCESS_E ) ;
301
+ current = c_nodes_etc [ PAR ] [ current + 1 ] - 1 ;
302
+ }
303
+
304
+ } ,
305
+ [ [ nodes , parents , minCosts , finalCosts ] ]
306
+ )
307
+ break ;
308
+ }
309
+
281
310
// Mark the vertex as visited
282
-
283
311
284
312
// Update the cost and prev arrays
285
313
@@ -320,14 +348,10 @@ colors.FRONTIER_E);
320
348
}
321
349
}
322
350
323
-
324
- // console.log(['vis.graph.colorEdge', c_cV, c_m, colors.N_M_E]);
325
351
vis . graph . removeEdgeColor ( c_cV , c_m ) ;
326
352
vis . graph . colorEdge ( c_cV , c_m , colors . N_M_E ) ;
327
353
328
354
refresh ( vis , v , c_miniIndex , c_cV , c_m ) ;
329
-
330
-
331
355
} ,
332
356
[ [ nodes , parents , minCosts , finalCosts ] , miniIndex , last , prev , currentVertex ,
333
357
m ]
@@ -401,19 +425,10 @@ colors.FRONTIER_E);
401
425
vis . graph . removeNodeColor ( c_prev_m ) ;
402
426
vis . graph . colorEdge ( c_prev_m , c_m , colors . FRONTIER_E ) ;
403
427
vis . graph . colorNode ( c_prev_m , 1 ) ;
404
- //vis.graph.deselect(c_prev_m, c_prev_m);
405
- //vis.graph.select(c_prev_m, c_m);
406
428
407
429
// disconnect from the previous parent
408
430
if ( c_lastP != null ) {
409
-
410
- // vis.graph.visit(c_m,[c_lastP]);
411
-
412
431
vis . graph . removeEdgeColor ( c_lastP , c_m ) ;
413
- //vis.graph.deselect(c_lastP, c_m);
414
-
415
- // vis.graph.colorNode(c_lastP, 1);
416
- //vis.graph.select(c_lastP, c_lastP);
417
432
}
418
433
419
434
refresh ( vis , c_nodes_etc , c_miniIndex , c_cV , c_m ) ;
@@ -425,11 +440,6 @@ colors.FRONTIER_E);
425
440
}
426
441
}
427
442
}
428
- // XXX add stuff to deal with while loop termination due to
429
- // PQ being empty
430
443
} ,
431
444
432
-
433
-
434
-
435
445
} ;
0 commit comments