5
5
sys .path .append (os .path .join (os .path .dirname (__file__ ), '..' ))
6
6
from search import *
7
7
from search import breadth_first_tree_search as bfts , depth_first_tree_search as dfts , \
8
- depth_first_graph_search as dfgs , breadth_first_search as bfs , uniform_cost_search as ucs , \
8
+ depth_first_graph_search as dfgs , breadth_first_graph_search as bfs , uniform_cost_search as ucs , \
9
9
astar_search as asts
10
- from utils import Stack , FIFOQueue , PriorityQueue
10
+ from utils import PriorityQueue
11
11
from copy import deepcopy
12
12
13
13
root = None
26
26
27
27
28
28
def create_map (root ):
29
- '''
30
- This function draws out the required map.
31
- '''
29
+ """This function draws out the required map."""
32
30
global city_map , start , goal
33
31
romania_locations = romania_map .locations
34
32
width = 750
@@ -260,17 +258,13 @@ def create_map(root):
260
258
261
259
262
260
def make_line (map , x0 , y0 , x1 , y1 , distance ):
263
- '''
264
- This function draws out the lines joining various points.
265
- '''
261
+ """This function draws out the lines joining various points."""
266
262
map .create_line (x0 , y0 , x1 , y1 )
267
263
map .create_text ((x0 + x1 ) / 2 , (y0 + y1 ) / 2 , text = distance )
268
264
269
265
270
266
def make_rectangle (map , x0 , y0 , margin , city_name ):
271
- '''
272
- This function draws out rectangles for various points.
273
- '''
267
+ """This function draws out rectangles for various points."""
274
268
global city_coord
275
269
rect = map .create_rectangle (
276
270
x0 - margin ,
@@ -313,51 +307,51 @@ def make_legend(map):
313
307
314
308
315
309
def tree_search (problem ):
316
- '''
310
+ """
317
311
Search through the successors of a problem to find a goal.
318
312
The argument frontier should be an empty queue.
319
313
Don't worry about repeated paths to a state. [Figure 3.7]
320
314
This function has been changed to make it suitable for the Tkinter GUI.
321
- '''
315
+ """
322
316
global counter , frontier , node
323
- # print(counter)
317
+
324
318
if counter == - 1 :
325
319
frontier .append (Node (problem .initial ))
326
- # print(frontier)
320
+
327
321
display_frontier (frontier )
328
322
if counter % 3 == 0 and counter >= 0 :
329
323
node = frontier .pop ()
330
- # print(node)
324
+
331
325
display_current (node )
332
326
if counter % 3 == 1 and counter >= 0 :
333
327
if problem .goal_test (node .state ):
334
- # print(node)
328
+
335
329
return node
336
330
frontier .extend (node .expand (problem ))
337
- # print(frontier)
331
+
338
332
display_frontier (frontier )
339
333
if counter % 3 == 2 and counter >= 0 :
340
- # print(node)
334
+
341
335
display_explored (node )
342
336
return None
343
337
344
338
345
339
def graph_search (problem ):
346
- '''
340
+ """
347
341
Search through the successors of a problem to find a goal.
348
342
The argument frontier should be an empty queue.
349
343
If two paths reach a state, only use the first one. [Figure 3.7]
350
344
This function has been changed to make it suitable for the Tkinter GUI.
351
- '''
345
+ """
352
346
global counter , frontier , node , explored
353
347
if counter == - 1 :
354
348
frontier .append (Node (problem .initial ))
355
349
explored = set ()
356
- # print("Frontier: "+str(frontier))
350
+
357
351
display_frontier (frontier )
358
352
if counter % 3 == 0 and counter >= 0 :
359
353
node = frontier .pop ()
360
- # print("Current node: "+str(node))
354
+
361
355
display_current (node )
362
356
if counter % 3 == 1 and counter >= 0 :
363
357
if problem .goal_test (node .state ):
@@ -366,18 +360,15 @@ def graph_search(problem):
366
360
frontier .extend (child for child in node .expand (problem )
367
361
if child .state not in explored and
368
362
child not in frontier )
369
- # print("Frontier: " + str(frontier))
363
+
370
364
display_frontier (frontier )
371
365
if counter % 3 == 2 and counter >= 0 :
372
- # print("Explored node: "+str(node))
373
366
display_explored (node )
374
367
return None
375
368
376
369
377
370
def display_frontier (queue ):
378
- '''
379
- This function marks the frontier nodes (orange) on the map.
380
- '''
371
+ """This function marks the frontier nodes (orange) on the map."""
381
372
global city_map , city_coord
382
373
qu = deepcopy (queue )
383
374
while qu :
@@ -388,63 +379,92 @@ def display_frontier(queue):
388
379
389
380
390
381
def display_current (node ):
391
- '''
392
- This function marks the currently exploring node (red) on the map.
393
- '''
382
+ """This function marks the currently exploring node (red) on the map."""
394
383
global city_map , city_coord
395
384
city = node .state
396
385
city_map .itemconfig (city_coord [city ], fill = "red" )
397
386
398
387
399
388
def display_explored (node ):
400
- '''
401
- This function marks the already explored node (gray) on the map.
402
- '''
389
+ """This function marks the already explored node (gray) on the map."""
403
390
global city_map , city_coord
404
391
city = node .state
405
392
city_map .itemconfig (city_coord [city ], fill = "gray" )
406
393
407
394
408
395
def display_final (cities ):
409
- '''
410
- This function marks the final solution nodes (green) on the map.
411
- '''
396
+ """This function marks the final solution nodes (green) on the map."""
412
397
global city_map , city_coord
413
398
for city in cities :
414
399
city_map .itemconfig (city_coord [city ], fill = "green" )
415
400
416
401
417
402
def breadth_first_tree_search (problem ):
418
403
"""Search the shallowest nodes in the search tree first."""
419
- global frontier , counter
404
+ global frontier , counter , node
420
405
if counter == - 1 :
421
- frontier = FIFOQueue ()
422
- return tree_search (problem )
406
+ frontier = deque ()
407
+
408
+ if counter == - 1 :
409
+ frontier .append (Node (problem .initial ))
410
+
411
+ display_frontier (frontier )
412
+ if counter % 3 == 0 and counter >= 0 :
413
+ node = frontier .popleft ()
414
+
415
+ display_current (node )
416
+ if counter % 3 == 1 and counter >= 0 :
417
+ if problem .goal_test (node .state ):
418
+ return node
419
+ frontier .extend (node .expand (problem ))
420
+
421
+ display_frontier (frontier )
422
+ if counter % 3 == 2 and counter >= 0 :
423
+ display_explored (node )
424
+ return None
423
425
424
426
425
427
def depth_first_tree_search (problem ):
426
428
"""Search the deepest nodes in the search tree first."""
427
429
# This search algorithm might not work in case of repeated paths.
428
- global frontier , counter
430
+ global frontier , counter , node
429
431
if counter == - 1 :
430
- frontier = Stack ()
431
- return tree_search (problem )
432
+ frontier = [] # stack
433
+
434
+ if counter == - 1 :
435
+ frontier .append (Node (problem .initial ))
436
+
437
+ display_frontier (frontier )
438
+ if counter % 3 == 0 and counter >= 0 :
439
+ node = frontier .pop ()
440
+
441
+ display_current (node )
442
+ if counter % 3 == 1 and counter >= 0 :
443
+ if problem .goal_test (node .state ):
444
+ return node
445
+ frontier .extend (node .expand (problem ))
446
+
447
+ display_frontier (frontier )
448
+ if counter % 3 == 2 and counter >= 0 :
449
+ display_explored (node )
450
+ return None
432
451
433
452
434
- def breadth_first_search (problem ):
453
+ def breadth_first_graph_search (problem ):
435
454
"""[Figure 3.11]"""
436
455
global frontier , node , explored , counter
437
456
if counter == - 1 :
438
457
node = Node (problem .initial )
439
458
display_current (node )
440
459
if problem .goal_test (node .state ):
441
460
return node
442
- frontier = FIFOQueue ()
443
- frontier .append (node )
461
+
462
+ frontier = deque ([node ]) # FIFO queue
463
+
444
464
display_frontier (frontier )
445
465
explored = set ()
446
466
if counter % 3 == 0 and counter >= 0 :
447
- node = frontier .pop ()
467
+ node = frontier .popleft ()
448
468
display_current (node )
449
469
explored .add (node .state )
450
470
if counter % 3 == 1 and counter >= 0 :
@@ -461,10 +481,30 @@ def breadth_first_search(problem):
461
481
462
482
def depth_first_graph_search (problem ):
463
483
"""Search the deepest nodes in the search tree first."""
464
- global frontier , counter
484
+ global counter , frontier , node , explored
465
485
if counter == - 1 :
466
- frontier = Stack ()
467
- return graph_search (problem )
486
+ frontier = [] # stack
487
+ if counter == - 1 :
488
+ frontier .append (Node (problem .initial ))
489
+ explored = set ()
490
+
491
+ display_frontier (frontier )
492
+ if counter % 3 == 0 and counter >= 0 :
493
+ node = frontier .pop ()
494
+
495
+ display_current (node )
496
+ if counter % 3 == 1 and counter >= 0 :
497
+ if problem .goal_test (node .state ):
498
+ return node
499
+ explored .add (node .state )
500
+ frontier .extend (child for child in node .expand (problem )
501
+ if child .state not in explored and
502
+ child not in frontier )
503
+
504
+ display_frontier (frontier )
505
+ if counter % 3 == 2 and counter >= 0 :
506
+ display_explored (node )
507
+ return None
468
508
469
509
470
510
def best_first_graph_search (problem , f ):
@@ -483,7 +523,7 @@ def best_first_graph_search(problem, f):
483
523
display_current (node )
484
524
if problem .goal_test (node .state ):
485
525
return node
486
- frontier = PriorityQueue (min , f )
526
+ frontier = PriorityQueue (' min' , f )
487
527
frontier .append (node )
488
528
display_frontier (frontier )
489
529
explored = set ()
@@ -525,9 +565,9 @@ def astar_search(problem, h=None):
525
565
# Remove redundant code.
526
566
# Make the interchangbility work between various algorithms at each step.
527
567
def on_click ():
528
- '''
568
+ """
529
569
This function defines the action of the 'Next' button.
530
- '''
570
+ """
531
571
global algo , counter , next_button , romania_problem , start , goal
532
572
romania_problem = GraphProblem (start .get (), goal .get (), romania_map )
533
573
if "Breadth-First Tree Search" == algo .get ():
@@ -546,8 +586,8 @@ def on_click():
546
586
display_final (final_path )
547
587
next_button .config (state = "disabled" )
548
588
counter += 1
549
- elif "Breadth-First Search" == algo .get ():
550
- node = breadth_first_search (romania_problem )
589
+ elif "Breadth-First Graph Search" == algo .get ():
590
+ node = breadth_first_graph_search (romania_problem )
551
591
if node is not None :
552
592
final_path = bfs (romania_problem ).solution ()
553
593
final_path .append (start .get ())
@@ -605,7 +645,7 @@ def main():
605
645
algorithm_menu = OptionMenu (
606
646
root ,
607
647
algo , "Breadth-First Tree Search" , "Depth-First Tree Search" ,
608
- "Breadth-First Search" , "Depth-First Graph Search" ,
648
+ "Breadth-First Graph Search" , "Depth-First Graph Search" ,
609
649
"Uniform Cost Search" , "A* - Search" )
610
650
Label (root , text = "\n Search Algorithm" ).pack ()
611
651
algorithm_menu .pack ()
0 commit comments