Finish the Route Finding Part 1 Project.
This commit is contained in:
parent
5c3f0fb689
commit
c1da0ee15c
9 changed files with 95 additions and 40 deletions
|
|
@ -1,5 +1,3 @@
|
|||
# Define Searcher class here.
|
||||
# Define Searcher, hSLD, SearchNode.
|
||||
import DRDViz
|
||||
import math
|
||||
|
||||
|
|
@ -31,6 +29,9 @@ class Searcher:
|
|||
def __init__(self, mapfile, searchType, verbose=False):
|
||||
self.mapfile = mapfile
|
||||
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
|
||||
with open(self.mapfile) as mapper:
|
||||
mapContents = mapper.read()
|
||||
|
|
@ -111,47 +112,101 @@ class Searcher:
|
|||
self.open.append(SearchNode(self.startNode, 0))
|
||||
# do I need to reset the visualization too?
|
||||
def insert_front(self, nodeList):
|
||||
# backwards "sort"
|
||||
# loop through each element, and apply it to the beginning of the open list.
|
||||
for item in nodeList:
|
||||
if item not in self.open:
|
||||
self.open.insert(0, item)
|
||||
# merge the existing open list with the new nodes
|
||||
# had to minorly change the algorithm from the previous version.
|
||||
combinedList = sorted(self.open + [item for item in nodeList if item not in self.open])
|
||||
self.open = combinedList
|
||||
def insert_end(self, nodeList):
|
||||
# forwards "sort"
|
||||
# loop through each element, and apply it to the end of the open list.
|
||||
for item in nodeList:
|
||||
if item not in self.open:
|
||||
self.open.append(item)
|
||||
# merge the existing open list with the new nodes
|
||||
combinedList = sorted(self.open + [item for item in nodeList if item not in self.open])
|
||||
self.open = combinedList
|
||||
def insert_ordered(self, nodeList):
|
||||
# sort by the lowest cost after adding all the elements to the open list.
|
||||
# add the nodes to the list
|
||||
self.open.extend(nodeList)
|
||||
# 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)
|
||||
# merge the existing open list with the new nodes based on path cost
|
||||
combinedList = sorted(self.open + [item for item in nodeList if item not in self.open], key=lambda item: item.pathcost)
|
||||
self.open = combinedList
|
||||
def search(self):
|
||||
print(f"Begin Searching with type {self.searchType}")
|
||||
if self.searchType.lower() == "depth":
|
||||
self.depth_first_search()
|
||||
elif self.searchType.lower() == "breadth":
|
||||
self.breadth_first_search()
|
||||
elif self.searchType.lower() == "best":
|
||||
self.best_first_search()
|
||||
elif self.searchType.lower() == "a*":
|
||||
self.a_star_search()
|
||||
else:
|
||||
print("Invalid searchtype.")
|
||||
def depth_first_search(self):
|
||||
pass
|
||||
def breadth_first_search(self):
|
||||
pass
|
||||
def best_first_search(self):
|
||||
pass
|
||||
def a_star_search(self):
|
||||
pass
|
||||
# reset the open list if another search is done at a different time
|
||||
self.reset()
|
||||
# keep track of the visited nodes as a set
|
||||
visited = set()
|
||||
# parent dictionary
|
||||
parentNode = {self.startNode: None}
|
||||
# check to see if the A* algorithm is being used, if it is, use
|
||||
# the heuristic functions
|
||||
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:
|
||||
# if A* search, then grab the node with the lowest totalCost
|
||||
currentNode = min(self.open, key=lambda node: totalCosts.get(node.label, float('inf')))
|
||||
# remove it from the open list
|
||||
self.open.remove(currentNode)
|
||||
# print out the node explored if verbosity is set
|
||||
if self.verbose: print(f"Exploring node: {currentNode.label}")
|
||||
# use the DRDViz tool to plot the explored node.
|
||||
# self.myViz.exploreNode(currentNode.label, visited)
|
||||
# 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
|
||||
x=Searcher("10test.txt", searchType="DEPTH", verbose=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue