Skip to content

Commit ba35aa4

Browse files
goswami-rahulnorvig
authored andcommitted
refactored FIFOQueue, Stack, and PriorityQueue (aimacode#878)
1 parent 3e790e9 commit ba35aa4

File tree

7 files changed

+215
-274
lines changed

7 files changed

+215
-274
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Here is a table of algorithms, the figure, name of the algorithm in the book and
7272
| 3.2 | Romania | `romania` | [`search.py`][search] | Done | Included |
7373
| 3.7 | Tree-Search | `tree_search` | [`search.py`][search] | Done | |
7474
| 3.7 | Graph-Search | `graph_search` | [`search.py`][search] | Done | |
75-
| 3.11 | Breadth-First-Search | `breadth_first_search` | [`search.py`][search] | Done | Included |
75+
| 3.11 | Breadth-First-Search | `breadth_first_graph_search` | [`search.py`][search] | Done | Included |
7676
| 3.14 | Uniform-Cost-Search | `uniform_cost_search` | [`search.py`][search] | Done | Included |
7777
| 3.17 | Depth-Limited-Search | `depth_limited_search` | [`search.py`][search] | Done | |
7878
| 3.18 | Iterative-Deepening-Search | `iterative_deepening_search` | [`search.py`][search] | Done | |

gui/romania_problem.py

Lines changed: 96 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
66
from search import *
77
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, \
99
astar_search as asts
10-
from utils import Stack, FIFOQueue, PriorityQueue
10+
from utils import PriorityQueue
1111
from copy import deepcopy
1212

1313
root = None
@@ -26,9 +26,7 @@
2626

2727

2828
def create_map(root):
29-
'''
30-
This function draws out the required map.
31-
'''
29+
"""This function draws out the required map."""
3230
global city_map, start, goal
3331
romania_locations = romania_map.locations
3432
width = 750
@@ -260,17 +258,13 @@ def create_map(root):
260258

261259

262260
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."""
266262
map.create_line(x0, y0, x1, y1)
267263
map.create_text((x0 + x1) / 2, (y0 + y1) / 2, text=distance)
268264

269265

270266
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."""
274268
global city_coord
275269
rect = map.create_rectangle(
276270
x0 - margin,
@@ -313,51 +307,51 @@ def make_legend(map):
313307

314308

315309
def tree_search(problem):
316-
'''
310+
"""
317311
Search through the successors of a problem to find a goal.
318312
The argument frontier should be an empty queue.
319313
Don't worry about repeated paths to a state. [Figure 3.7]
320314
This function has been changed to make it suitable for the Tkinter GUI.
321-
'''
315+
"""
322316
global counter, frontier, node
323-
# print(counter)
317+
324318
if counter == -1:
325319
frontier.append(Node(problem.initial))
326-
# print(frontier)
320+
327321
display_frontier(frontier)
328322
if counter % 3 == 0 and counter >= 0:
329323
node = frontier.pop()
330-
# print(node)
324+
331325
display_current(node)
332326
if counter % 3 == 1 and counter >= 0:
333327
if problem.goal_test(node.state):
334-
# print(node)
328+
335329
return node
336330
frontier.extend(node.expand(problem))
337-
# print(frontier)
331+
338332
display_frontier(frontier)
339333
if counter % 3 == 2 and counter >= 0:
340-
# print(node)
334+
341335
display_explored(node)
342336
return None
343337

344338

345339
def graph_search(problem):
346-
'''
340+
"""
347341
Search through the successors of a problem to find a goal.
348342
The argument frontier should be an empty queue.
349343
If two paths reach a state, only use the first one. [Figure 3.7]
350344
This function has been changed to make it suitable for the Tkinter GUI.
351-
'''
345+
"""
352346
global counter, frontier, node, explored
353347
if counter == -1:
354348
frontier.append(Node(problem.initial))
355349
explored = set()
356-
# print("Frontier: "+str(frontier))
350+
357351
display_frontier(frontier)
358352
if counter % 3 == 0 and counter >= 0:
359353
node = frontier.pop()
360-
# print("Current node: "+str(node))
354+
361355
display_current(node)
362356
if counter % 3 == 1 and counter >= 0:
363357
if problem.goal_test(node.state):
@@ -366,18 +360,15 @@ def graph_search(problem):
366360
frontier.extend(child for child in node.expand(problem)
367361
if child.state not in explored and
368362
child not in frontier)
369-
# print("Frontier: " + str(frontier))
363+
370364
display_frontier(frontier)
371365
if counter % 3 == 2 and counter >= 0:
372-
# print("Explored node: "+str(node))
373366
display_explored(node)
374367
return None
375368

376369

377370
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."""
381372
global city_map, city_coord
382373
qu = deepcopy(queue)
383374
while qu:
@@ -388,63 +379,92 @@ def display_frontier(queue):
388379

389380

390381
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."""
394383
global city_map, city_coord
395384
city = node.state
396385
city_map.itemconfig(city_coord[city], fill="red")
397386

398387

399388
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."""
403390
global city_map, city_coord
404391
city = node.state
405392
city_map.itemconfig(city_coord[city], fill="gray")
406393

407394

408395
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."""
412397
global city_map, city_coord
413398
for city in cities:
414399
city_map.itemconfig(city_coord[city], fill="green")
415400

416401

417402
def breadth_first_tree_search(problem):
418403
"""Search the shallowest nodes in the search tree first."""
419-
global frontier, counter
404+
global frontier, counter, node
420405
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
423425

424426

425427
def depth_first_tree_search(problem):
426428
"""Search the deepest nodes in the search tree first."""
427429
# This search algorithm might not work in case of repeated paths.
428-
global frontier, counter
430+
global frontier, counter, node
429431
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
432451

433452

434-
def breadth_first_search(problem):
453+
def breadth_first_graph_search(problem):
435454
"""[Figure 3.11]"""
436455
global frontier, node, explored, counter
437456
if counter == -1:
438457
node = Node(problem.initial)
439458
display_current(node)
440459
if problem.goal_test(node.state):
441460
return node
442-
frontier = FIFOQueue()
443-
frontier.append(node)
461+
462+
frontier = deque([node]) # FIFO queue
463+
444464
display_frontier(frontier)
445465
explored = set()
446466
if counter % 3 == 0 and counter >= 0:
447-
node = frontier.pop()
467+
node = frontier.popleft()
448468
display_current(node)
449469
explored.add(node.state)
450470
if counter % 3 == 1 and counter >= 0:
@@ -461,10 +481,30 @@ def breadth_first_search(problem):
461481

462482
def depth_first_graph_search(problem):
463483
"""Search the deepest nodes in the search tree first."""
464-
global frontier, counter
484+
global counter, frontier, node, explored
465485
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
468508

469509

470510
def best_first_graph_search(problem, f):
@@ -483,7 +523,7 @@ def best_first_graph_search(problem, f):
483523
display_current(node)
484524
if problem.goal_test(node.state):
485525
return node
486-
frontier = PriorityQueue(min, f)
526+
frontier = PriorityQueue('min', f)
487527
frontier.append(node)
488528
display_frontier(frontier)
489529
explored = set()
@@ -525,9 +565,9 @@ def astar_search(problem, h=None):
525565
# Remove redundant code.
526566
# Make the interchangbility work between various algorithms at each step.
527567
def on_click():
528-
'''
568+
"""
529569
This function defines the action of the 'Next' button.
530-
'''
570+
"""
531571
global algo, counter, next_button, romania_problem, start, goal
532572
romania_problem = GraphProblem(start.get(), goal.get(), romania_map)
533573
if "Breadth-First Tree Search" == algo.get():
@@ -546,8 +586,8 @@ def on_click():
546586
display_final(final_path)
547587
next_button.config(state="disabled")
548588
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)
551591
if node is not None:
552592
final_path = bfs(romania_problem).solution()
553593
final_path.append(start.get())
@@ -605,7 +645,7 @@ def main():
605645
algorithm_menu = OptionMenu(
606646
root,
607647
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",
609649
"Uniform Cost Search", "A* - Search")
610650
Label(root, text="\n Search Algorithm").pack()
611651
algorithm_menu.pack()

planning.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33

44
import itertools
55
from search import Node
6-
from utils import Expr, expr, first, FIFOQueue
6+
from utils import Expr, expr, first
77
from logic import FolKB
8+
from collections import deque
89

910

1011
class PDDL:
@@ -727,16 +728,16 @@ def hierarchical_search(problem, hierarchy):
727728
"""
728729
[Figure 11.5] 'Hierarchical Search, a Breadth First Search implementation of Hierarchical
729730
Forward Planning Search'
730-
The problem is a real-world prodlem defined by the problem class, and the hierarchy is
731+
The problem is a real-world problem defined by the problem class, and the hierarchy is
731732
a dictionary of HLA - refinements (see refinements generator for details)
732733
"""
733734
act = Node(problem.actions[0])
734-
frontier = FIFOQueue()
735+
frontier = deque()
735736
frontier.append(act)
736-
while(True):
737+
while True:
737738
if not frontier:
738739
return None
739-
plan = frontier.pop()
740+
plan = frontier.popleft()
740741
print(plan.state.name)
741742
hla = plan.state # first_or_null(plan)
742743
prefix = None

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy