Finish the Route Finding Part 1 Project.

This commit is contained in:
Charles Descamps 2025-02-28 23:29:02 -07:00
parent 5c3f0fb689
commit c1da0ee15c
9 changed files with 95 additions and 40 deletions

View file

@ -1,5 +1,3 @@
# Define Searcher class here.
# Define Searcher, hSLD, SearchNode.
import DRDViz import DRDViz
import math import math
@ -31,6 +29,9 @@ class Searcher:
def __init__(self, mapfile, searchType, verbose=False): def __init__(self, mapfile, searchType, verbose=False):
self.mapfile = mapfile self.mapfile = mapfile
self.searchType = searchType self.searchType = searchType
self.verbose = verbose
# let the user know what searchtype is used and the filename
if self.verbose: print(f"Loaded search type {self.searchType} with map in file: {self.mapfile}")
# load the mapfile's structure # load the mapfile's structure
with open(self.mapfile) as mapper: with open(self.mapfile) as mapper:
mapContents = mapper.read() mapContents = mapper.read()
@ -111,47 +112,101 @@ class Searcher:
self.open.append(SearchNode(self.startNode, 0)) self.open.append(SearchNode(self.startNode, 0))
# do I need to reset the visualization too? # do I need to reset the visualization too?
def insert_front(self, nodeList): def insert_front(self, nodeList):
# backwards "sort" # merge the existing open list with the new nodes
# loop through each element, and apply it to the beginning of the open list. # had to minorly change the algorithm from the previous version.
for item in nodeList: combinedList = sorted(self.open + [item for item in nodeList if item not in self.open])
if item not in self.open: self.open = combinedList
self.open.insert(0, item)
def insert_end(self, nodeList): def insert_end(self, nodeList):
# forwards "sort" # merge the existing open list with the new nodes
# loop through each element, and apply it to the end of the open list. combinedList = sorted(self.open + [item for item in nodeList if item not in self.open])
for item in nodeList: self.open = combinedList
if item not in self.open:
self.open.append(item)
def insert_ordered(self, nodeList): def insert_ordered(self, nodeList):
# sort by the lowest cost after adding all the elements to the open list. # merge the existing open list with the new nodes based on path cost
# add the nodes to the list combinedList = sorted(self.open + [item for item in nodeList if item not in self.open], key=lambda item: item.pathcost)
self.open.extend(nodeList) self.open = combinedList
# sort via a lambda function key, using the sorted function
sortedList = sorted(self.open, key=lambda item: item.pathcost)
# clear out the open list
self.open.clear()
# replace it with the sorted list by extending the blank list.
self.open.extend(sortedList)
def search(self): def search(self):
print(f"Begin Searching with type {self.searchType}") # reset the open list if another search is done at a different time
if self.searchType.lower() == "depth": self.reset()
self.depth_first_search() # keep track of the visited nodes as a set
elif self.searchType.lower() == "breadth": visited = set()
self.breadth_first_search() # parent dictionary
elif self.searchType.lower() == "best": parentNode = {self.startNode: None}
self.best_first_search() # check to see if the A* algorithm is being used, if it is, use
elif self.searchType.lower() == "a*": # the heuristic functions
self.a_star_search() if self.searchType.lower() == "a*":
goalCosts = {self.startNode: 0}
totalCosts = {self.startNode: hSLD(self.startNode, self)}
# while loop through the open list, inserting successor nodes to the open list
# depending on the algorithm
while self.open:
# grab the current node, if not A*
if self.searchType.lower() != "a*":
currentNode = self.open.pop(0)
else: else:
print("Invalid searchtype.") # if A* search, then grab the node with the lowest totalCost
def depth_first_search(self): currentNode = min(self.open, key=lambda node: totalCosts.get(node.label, float('inf')))
pass # remove it from the open list
def breadth_first_search(self): self.open.remove(currentNode)
pass # print out the node explored if verbosity is set
def best_first_search(self): if self.verbose: print(f"Exploring node: {currentNode.label}")
pass # use the DRDViz tool to plot the explored node.
def a_star_search(self): # self.myViz.exploreNode(currentNode.label, visited)
pass # check if the current node is the goal
if currentNode.label == self.endNode:
tempNode = currentNode
# backtrack to find the path taken
pathTaken = []
# loop through the node list
while currentNode:
# append the node to the path list
pathTaken.append(currentNode.label)
# grab the node from the parentNode dictionary
currentNode = parentNode[currentNode.label]
# reverse the pathTaken list, and display it.
pathTaken.reverse()
print(f"Success! Reached goal node {self.endNode} with path: {pathTaken}")
self.myViz.exploreNode(tempNode.label, pathTaken)
# save the DRDViz plot.
if self.searchType.lower() != "a*":
self.myViz.save(f"{self.mapfile[:-4]}-{self.searchType}.png")
else:
self.myViz.save(f"{self.mapfile[:-4]}-ASTAR.png")
# return 'early' to prevent further traversal
return
# check to see if the current node isn't in the visited set
if currentNode.label not in visited:
# add the node to the visited set
visited.add(currentNode.label)
# find the successors to the current node
successors = self.successors(currentNode)
# print the successor list if verbosity is set
if self.verbose: print(f"Inserting new children: {successors}")
# insert the successors in the open list, depending on the algorithm
for successor in successors:
# if successor.label not in visited:
if successor.label not in visited and successor not in self.open:
parentNode[successor.label] = currentNode
if self.searchType.lower() == "depth":
self.insert_front([successor])
elif self.searchType.lower() == "breadth":
self.insert_end([successor])
elif self.searchType.lower() == "best":
self.insert_ordered([successor])
elif self.searchType.lower() == "a*":
# since this is A*, now we need to compute all the heuristic values for the nodes
currentGoalCost = goalCosts[currentNode.label] + successor.pathcost
# check if the successor is not in the goalCosts or in the currentGoalCost and less than the goalCosts list
if successor.label not in goalCosts or currentGoalCost < goalCosts[successor.label]:
# add the successor to the goal and totalCosts dictionaries
goalCosts[successor.label] = currentGoalCost
totalCosts[successor.label] = currentGoalCost + hSLD(successor.label, self)
# then, append itself to the open list.
if successor not in self.open:
self.open.append(successor)
if self.verbose: print(f"Open List: {self.open}")
# in the event that the while loop completes and never actually reaches a goal
# print that if verbosity is set.
if self.verbose: print("Unable to reach goal.")
# 10test.txt map # 10test.txt map
x=Searcher("10test.txt", searchType="DEPTH", verbose=True) x=Searcher("10test.txt", searchType="DEPTH", verbose=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB