4
4
import math
5
5
sys .path .append (os .path .join (os .path .dirname (__file__ ), '..' ))
6
6
from search import *
7
- from search import breadth_first_tree_search as bfts , depth_first_tree_search as dfts ,depth_first_graph_search as dfgs
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
8
9
from utils import Stack , FIFOQueue , PriorityQueue
9
10
from copy import deepcopy
11
+
10
12
root = None
11
13
city_coord = {}
12
14
romania_problem = None
19
21
front = None
20
22
node = None
21
23
next_button = None
22
- explored = None
24
+ explored = None
25
+
23
26
24
27
def create_map (root ):
25
28
'''
@@ -97,7 +100,7 @@ def create_map(root):
97
100
romania_locations ['Mehadia' ][0 ],
98
101
height -
99
102
romania_locations ['Mehadia' ][1 ],
100
- romania_map .get ('Lugoj' , 'Mehandia ' ))
103
+ romania_map .get ('Lugoj' , 'Mehadia ' ))
101
104
make_line (
102
105
city_map ,
103
106
romania_locations ['Drobeta' ][0 ],
@@ -106,7 +109,7 @@ def create_map(root):
106
109
romania_locations ['Mehadia' ][0 ],
107
110
height -
108
111
romania_locations ['Mehadia' ][1 ],
109
- romania_map .get ('Drobeta' , 'Mehandia ' ))
112
+ romania_map .get ('Drobeta' , 'Mehadia ' ))
110
113
make_line (
111
114
city_map ,
112
115
romania_locations ['Drobeta' ][0 ],
@@ -274,11 +277,19 @@ def make_rectangle(map, x0, y0, margin, city_name):
274
277
x0 + margin ,
275
278
y0 + margin ,
276
279
fill = "white" )
277
- map .create_text (
278
- x0 - 2 * margin ,
279
- y0 - 2 * margin ,
280
- text = city_name ,
281
- anchor = SE )
280
+ if "Bucharest" in city_name or "Pitesti" in city_name or "Lugoj" in city_name \
281
+ or "Mehadia" in city_name or "Drobeta" in city_name :
282
+ map .create_text (
283
+ x0 - 2 * margin ,
284
+ y0 - 2 * margin ,
285
+ text = city_name ,
286
+ anchor = E )
287
+ else :
288
+ map .create_text (
289
+ x0 - 2 * margin ,
290
+ y0 - 2 * margin ,
291
+ text = city_name ,
292
+ anchor = SE )
282
293
city_coord .update ({city_name : rect })
283
294
284
295
@@ -302,7 +313,7 @@ def make_legend(map):
302
313
303
314
def tree_search (problem ):
304
315
'''
305
- earch through the successors of a problem to find a goal.
316
+ Search through the successors of a problem to find a goal.
306
317
The argument frontier should be an empty queue.
307
318
Don't worry about repeated paths to a state. [Figure 3.7]
308
319
This function has been changed to make it suitable for the Tkinter GUI.
@@ -329,20 +340,23 @@ def tree_search(problem):
329
340
display_explored (node )
330
341
return None
331
342
343
+
332
344
def graph_search (problem ):
333
345
'''
334
346
Search through the successors of a problem to find a goal.
335
347
The argument frontier should be an empty queue.
336
348
If two paths reach a state, only use the first one. [Figure 3.7]
337
349
This function has been changed to make it suitable for the Tkinter GUI.
338
350
'''
339
- global counter ,frontier ,node ,explored
351
+ global counter , frontier , node , explored
340
352
if counter == - 1 :
341
353
frontier .append (Node (problem .initial ))
342
- explored = set ()
354
+ explored = set ()
355
+ # print("Frontier: "+str(frontier))
343
356
display_frontier (frontier )
344
- if counter % 3 == 0 and counter >= 0 :
357
+ if counter % 3 == 0 and counter >= 0 :
345
358
node = frontier .pop ()
359
+ # print("Current node: "+str(node))
346
360
display_current (node )
347
361
if counter % 3 == 1 and counter >= 0 :
348
362
if problem .goal_test (node .state ):
@@ -351,13 +365,14 @@ def graph_search(problem):
351
365
frontier .extend (child for child in node .expand (problem )
352
366
if child .state not in explored and
353
367
child not in frontier )
368
+ # print("Frontier: " + str(frontier))
354
369
display_frontier (frontier )
355
370
if counter % 3 == 2 and counter >= 0 :
371
+ # print("Explored node: "+str(node))
356
372
display_explored (node )
357
373
return None
358
374
359
375
360
-
361
376
def display_frontier (queue ):
362
377
'''
363
378
This function marks the frontier nodes (orange) on the map.
@@ -370,6 +385,7 @@ def display_frontier(queue):
370
385
if node .state == city :
371
386
city_map .itemconfig (city_coord [city ], fill = "orange" )
372
387
388
+
373
389
def display_current (node ):
374
390
'''
375
391
This function marks the currently exploring node (red) on the map.
@@ -378,6 +394,7 @@ def display_current(node):
378
394
city = node .state
379
395
city_map .itemconfig (city_coord [city ], fill = "red" )
380
396
397
+
381
398
def display_explored (node ):
382
399
'''
383
400
This function marks the already explored node (gray) on the map.
@@ -386,6 +403,7 @@ def display_explored(node):
386
403
city = node .state
387
404
city_map .itemconfig (city_coord [city ], fill = "gray" )
388
405
406
+
389
407
def display_final (cities ):
390
408
'''
391
409
This function marks the final solution nodes (green) on the map.
@@ -394,6 +412,7 @@ def display_final(cities):
394
412
for city in cities :
395
413
city_map .itemconfig (city_coord [city ], fill = "green" )
396
414
415
+
397
416
def breadth_first_tree_search (problem ):
398
417
"""Search the shallowest nodes in the search tree first."""
399
418
global frontier , counter
@@ -405,19 +424,48 @@ def breadth_first_tree_search(problem):
405
424
def depth_first_tree_search (problem ):
406
425
"""Search the deepest nodes in the search tree first."""
407
426
# This search algorithm might not work in case of repeated paths.
408
- global frontier ,counter
427
+ global frontier , counter
409
428
if counter == - 1 :
410
- frontier = Stack ()
429
+ frontier = Stack ()
411
430
return tree_search (problem )
412
431
413
- # TODO: Check if the solution given by this function is consistent with the original function.
432
+
433
+ def breadth_first_search (problem ):
434
+ """[Figure 3.11]"""
435
+ global frontier , node , explored , counter
436
+ if counter == - 1 :
437
+ node = Node (problem .initial )
438
+ display_current (node )
439
+ if problem .goal_test (node .state ):
440
+ return node
441
+ frontier = FIFOQueue ()
442
+ frontier .append (node )
443
+ display_frontier (frontier )
444
+ explored = set ()
445
+ if counter % 3 == 0 and counter >= 0 :
446
+ node = frontier .pop ()
447
+ display_current (node )
448
+ explored .add (node .state )
449
+ if counter % 3 == 1 and counter >= 0 :
450
+ for child in node .expand (problem ):
451
+ if child .state not in explored and child not in frontier :
452
+ if problem .goal_test (child .state ):
453
+ return child
454
+ frontier .append (child )
455
+ display_frontier (frontier )
456
+ if counter % 3 == 2 and counter >= 0 :
457
+ display_explored (node )
458
+ return None
459
+
460
+
414
461
def depth_first_graph_search (problem ):
415
462
"""Search the deepest nodes in the search tree first."""
416
463
global frontier , counter
417
464
if counter == - 1 :
418
465
frontier = Stack ()
419
466
return graph_search (problem )
420
467
468
+
421
469
# TODO:
422
470
# Remove redundant code.
423
471
# Make the interchangbility work between various algorithms at each step.
@@ -443,19 +491,24 @@ def on_click():
443
491
display_final (final_path )
444
492
next_button .config (state = "disabled" )
445
493
counter += 1
494
+ elif "Breadth-First Search" == algo .get ():
495
+ node = breadth_first_search (romania_problem )
496
+ if node is not None :
497
+ final_path = bfs (romania_problem ).solution ()
498
+ final_path .append (start .get ())
499
+ display_final (final_path )
500
+ next_button .config (state = "disabled" )
501
+ counter += 1
446
502
elif "Depth-First Graph Search" == algo .get ():
447
503
node = depth_first_graph_search (romania_problem )
448
504
if node is not None :
449
- print (node )
450
505
final_path = dfgs (romania_problem ).solution ()
451
- print (final_path )
452
506
final_path .append (start .get ())
453
507
display_final (final_path )
454
508
next_button .config (state = "disabled" )
455
509
counter += 1
456
510
457
511
458
-
459
512
def reset_map ():
460
513
global counter , city_coord , city_map , next_button
461
514
counter = - 1
@@ -479,7 +532,9 @@ def main():
479
532
goal .set ('Bucharest' )
480
533
cities = sorted (romania_map .locations .keys ())
481
534
algorithm_menu = OptionMenu (
482
- root , algo , "Breadth-First Tree Search" , "Depth-First Tree Search" ,"Depth-First Graph Search" )
535
+ root ,
536
+ algo , "Breadth-First Tree Search" , "Depth-First Tree Search" ,
537
+ "Breadth-First Search" , "Depth-First Graph Search" )
483
538
Label (root , text = "\n Search Algorithm" ).pack ()
484
539
algorithm_menu .pack ()
485
540
Label (root , text = "\n Start City" ).pack ()
0 commit comments