diff --git a/search.py b/search.py index cd330bf..e2ce3f5 100644 --- a/search.py +++ b/search.py @@ -18,7 +18,8 @@ """ import util - +from util import Stack +from util import Queue class SearchProblem: """ This class outlines the structure of a search problem, but doesn't implement @@ -82,17 +83,176 @@ def depthFirstSearch(problem): To get started, you might want to try some of these simple commands to understand the search problem that is being passed in: + print("Start:", problem.getStartState()) + print("Is the start a goal?", problem.isGoalState(problem.getStartState())) + print("Start's successors:", problem.getSuccessors(problem.getStartState())) + """ + fringe = Stack() + visited = set() + + fringe.push((problem.getStartState(), [])) + + while not fringe.isEmpty(): + node, path = fringe.pop() + if problem.isGoalState(node): + return path + + if node not in visited: + visited.add(node) + for successor in problem.getSuccessors(node): + fringe.push((successor[0], path + [successor[1]])) + + + + +# search.py +# --------- +# Licensing Information: You are free to use or extend these projects for +# educational purposes provided that (1) you do not distribute or publish +# solutions, (2) you retain this notice, and (3) you provide clear +# attribution to UC Berkeley, including a link to http://ai.berkeley.edu. +# +# Attribution Information: The Pacman AI projects were developed at UC Berkeley. +# The core projects and autograders were primarily created by John DeNero +# (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu). +# Student side autograding was added by Brad Miller, Nick Hay, and +# Pieter Abbeel (pabbeel@cs.berkeley.edu). + + +""" +In search.py, you will implement generic search algorithms which are called by +Pacman agents (in searchAgents.py). + +# Abbreviations +bfs = breadthFirstSearch +dfs = depthFirstSearch +astar = aStarSearch +ucs = uniformCostSearch +""" + +import util + + +class SearchProblem: + """ + This class outlines the structure of a search problem, but doesn't implement + any of the methods (in object-oriented terminology: an abstract class). + + You do not need to change anything in this class, ever. + """ + + def getStartState(self): + """ + Returns the start state for the search problem. + """ + util.raiseNotDefined() + + def isGoalState(self, state): + """ + state: Search state + + Returns True if and only if the state is a valid goal state. + """ + util.raiseNotDefined() + + def getSuccessors(self, state): + """ + state: Search state + + For a given state, this should return a list of triples, (successor, + action, stepCost), where 'successor' is a successor to the current + state, 'action' is the action required to get there, and 'stepCost' is + the incremental cost of expanding to that successor. + """ + util.raiseNotDefined() + + def getCostOfActions(self, actions): + """ + actions: A list of actions to take + + This method returns the total cost of a particular sequence of actions. + The sequence must be composed of legal moves. + """ + util.raiseNotDefined() + + +def tinyMazeSearch(problem): + """ + Returns a sequence of moves that solves tinyMaze. For any other maze, the + sequence of moves will be incorrect, so only use this for tinyMaze. + """ + from game import Directions + s = Directions.SOUTH + w = Directions.WEST + return [s, s, w, s, w, w, s, w] + + +def depthFirstSearch(problem: SearchProblem): + """ + Search the deepest nodes in the search tree first. + + Your search algorithm needs to return a list of actions that reaches the + goal. Make sure to implement a graph search algorithm. + + To get started, you might want to try some of these simple commands to + understand the search problem that is being passed in: + print("Start:", problem.getStartState()) print("Is the start a goal?", problem.isGoalState(problem.getStartState())) print("Start's successors:", problem.getSuccessors(problem.getStartState())) """ "*** YOUR CODE HERE ***" - util.raiseNotDefined() + fringe = Stack() + visited = set() + + fringe.push((problem.getStartState(), [])) + + while not fringe.isEmpty(): + node, path = fringe.pop() + if problem.isGoalState(node): + return path + + if node not in visited: + visited.add(node) + for successor in problem.getSuccessors(node): + fringe.push((successor[0], path + [successor[1]])) + + def breadthFirstSearch(problem): """Search the shallowest nodes in the search tree first.""" "*** YOUR CODE HERE ***" - util.raiseNotDefined() + from game import Directions, Actions + + queue = util.Queue() + visited = set() + actions = [] + # print(queue.isEmpty()) + print("Start:", problem.getStartState()) + print("Is the start a goal?", problem.isGoalState(problem.getStartState())) + print("Start's successors:", problem.getSuccessors(problem.getStartState())) + + # push root (starting position) + root = problem.getStartState() + queue.push(root) + + visited.add(root) + while not queue.isEmpty(): + current_node = queue.pop() + print("Visiting:", current_node) + + if (problem.isGoalState(current_node)): + print("Reached the goal") + break + + for paths in problem.getSuccessors(current_node): + path = paths[0] + if path not in visited: + visited.add(path) + queue.push(path) + print(actions) + return path + def uniformCostSearch(problem): """Search the node of least total cost first."""