class NPuzzle(Problem): """ NPuzzle - Problem representation for an N-tile puzzle Provides implementations for Problem actions specific to N tile puzzles. """ def __init__(self, n, force_state=None, **kwargs): """"__init__(n, force_state, **kwargs) NPuzzle constructor. Creates an initial TileBoard of size n. If force_state is not None, the puzzle is initialized to the specified state instead of being generated randomly. The parent's class constructor is then called with the TileBoard instance any any remaining arguments captured in **kwargs. """ # Note on **kwargs: # **kwargs is Python construct that captures any remaining arguments # into a dictionary. The dictionary can be accessed like any other # dictionary, e.g. kwargs["keyname"], or passed to another function # as if each entry was a keyword argument: # e.g. foobar(arg1, arg2, …, argn, **kwargs). self.size = n self.tileBoard = TileBoard(self.size, False, force_state) super().__init__(self.tileBoard, **kwargs) #call parent class with tileboard? return def getInitialBoardState(self): return self.tileBoard.state_tuple() def generateDebugBoard(self, state): return TileBoard(self.size, False, state) def actions(self, state): "actions(state) - find a set of actions applicable to specified state" actionBoard = TileBoard(self.size, False, state) actions = actionBoard.get_actions() return actions def result(self, state, action): "result(state, action)- apply action to state and return new state" actionBoard = TileBoard(self.size, False, state) newboard = actionBoard.move(action) return newboard.state_tuple() def goal_test(self, state): "goal_test(state) - Is state a goal?" testBoard = TileBoard(self.size, False, state) if (testBoard.solved()): return True else: return False
def driver(): start_overall_time = tic() sec_per_min = 60.0 number_of_tileboard_instances = 2 puzzle_size = 8 methods = [BreadthFirst, DepthFirst, Manhattan] list_of_paths = list() list_of_number_of_nodes_explored = list() list_of_times = list() for n in range(number_of_tileboard_instances): board = TileBoard(puzzle_size) state_tuple = board.state_tuple( ) # do this becuase we din't want to modify the original board for method in methods: puzzle = NPuzzle(puzzle_size, forced_state=state_tuple, g=method.g, h=method.h) (list_of_paths[n], list_of_number_of_nodes_explored[n], list_of_times[n]) = solve(puzzle)
def driver(): manTime = [] manLength = [] manNodes = [] depTime = [] depLength = [] depNodes = [] breadTime = [] breadLength = [] breadNodes = [] for i in range(0,31): tb = TileBoard(8) #starting with manhattan manprobs = NPuzzle(8,tb.state_tuple(),g=Manhattan.g,h=Manhattan.h) curTime = tic() #current time manList = graph_search(manprobs) #CONSIDER OTHER PARAMETERS LATER manTime.append(tock(curTime)) manLength.append(len(manList[0])) manNodes.append(manList[1]) #depth_first search depprobs = NPuzzle(8,tb.state_tuple(),g=DepthFirst.g,h=DepthFirst.h) curTime = tic() #current time depList = graph_search(depprobs) #CONSIDER OTHER PARAMETERS LATER depTime.append(tock(curTime)) depLength.append(len(depList[0])) depNodes.append(depList[1]) #breadth_first search breadprobs = NPuzzle(8,tb.state_tuple(),g=BreadthFirst.g,h=BreadthFirst.h) curTime = tic() #current time breadList = graph_search(breadprobs) #CONSIDER OTHER PARAMETERS LATER breadTime.append(tock(curTime)) breadLength.append(len(breadList[0])) breadNodes.append(breadList[1]) #calculate mean and stdevs for each list generated at beginning #manhattan statistics meanmantime = mean(manTime) stdmantime = stdev(manTime,meanmantime) meanmanlength = mean(manLength) stdmanlength = stdev(manLength,meanmanlength) meanmannodes = mean(manNodes) stdmannodes = stdev(manNodes,meanmannodes) #depth-first statistics meandeptime = mean(depTime) stddeptime = stdev(depTime) meandeplength = mean(depLength) stddeplength = stdev(depLength) meandepnodes = mean(depNodes) stddepnodes = stdev(depNodes) #breadth-first statistics meanbreadtime = mean(breadTime) stdbreadtime = stdev(breadTime) meanbreadlength = mean(breadLength) stdbreadlength = stdev(breadLength) meanbreadnodes = mean(breadNodes) stdbreadnodes = stdev(breadNodes) print("Manhattan Statistics - Mean Time: ", meanmantime, "StDev Time: ", stdmantime) print("Manhattan Statistics - Mean Length: ", meanmanlength, "StDev Length: ", stdmanlength) print("Manhattan Statistics - Mean Nodes: ", meanmannodes, "StDev Nodes: ", stdmannodes) print("Depth-First Statistics - Mean Time: ", meandeptime, "StDev Time: ", stddeptime) print("Depth-First Statistics - Mean Length: ", meandeplength, "StDev Length: ", stddeplength) print("Depth-First Statistics - Mean Nodes: ", meandepnodes, "StDev Nodes: ", stddepnodes) print("Breadth-First Statistics - Mean Time: ", meanbreadtime, "StDev Time: ", stdbreadtime) print("Breadth-First Statistics - Mean Length: ", meanbreadlength, "StDev Length: ", stdbreadlength) print("Breadth-First Statistics - Mean Nodes: ", meanbreadnodes, "StDev Nodes: ", stdbreadnodes)
def driver() : bfsLengthList = [] bfsNodesExpandedList = [] bfsTimeList = [] dfsLengthList = [] dfsNodesExpandedList = [] dfsTimeList = [] manLengthList = [] manNodesExpandedList = [] manTimeList = [] for i in range(2): #change back to 31 tempBoard = TileBoard(8) #force_state=(1,2,3,4,5,6,7,8,None) #Breadth First Search bfs = NPuzzle(8,g=BreadthFirst.g,force_state=tempBoard.state_tuple()) tempTimer = Timer() path,numNodes = graph_search(bfs, verbose=True) bfsTimeList.append(tempTimer.elapsed_s()) bfsNodesExpandedList.append(numNodes) bfsLengthList.append(len(path)) #Depth First Search dfs = NPuzzle(8,g=DepthFirst.g,force_state=tempBoard.state_tuple()) tempTimer = Timer() path,numNodes = graph_search(dfs, verbose=True) dfsTimeList.append(tempTimer.elapsed_s()) dfsNodesExpandedList.append(numNodes) dfsLengthList.append(len(path)) #Manhattan Search manhattan = NPuzzle(8, h=Manhattan.h, force_state=tempBoard.state_tuple()) tempTimer = Timer() path, numNodes = graph_search(manhattan, verbose=True) manTimeList.append(tempTimer.elapsed_s()) manNodesExpandedList.append(numNodes) manLengthList.append(len(path)) print("BFS Average Path Length:",mean(bfsLengthList)) print("BFS Average Nodes Expanded:",mean(bfsNodesExpandedList)) print("BFS Average Time Elapsed:",mean(bfsTimeList)) print("DFS Average Path Length:", mean(dfsLengthList)) print("DFS Average Nodes Expanded:",mean(dfsNodesExpandedList)) print("DFS Average Time Elapsed:",mean(dfsTimeList)) print("Manhattan Average Path Length:", mean(manLengthList)) print("Manhattan Average Nodes Expanded:", mean(manNodesExpandedList)) print("Manhattan Average Time Elapsed:", mean(manTimeList)) print("BFS Standard Deviation Path Length:", stdev(bfsLengthList)) print("BFS Standard Deviation Nodes Expanded:", stdev(bfsNodesExpandedList)) print("BFS Standard Deviation Time Elapsed:", stdev(bfsTimeList)) print("DFS Standard Deviation Path Length:", stdev(dfsLengthList)) print("DFS Standard Deviation Nodes Expanded:", stdev(dfsNodesExpandedList)) print("DFS Standard Deviation Time Elapsed:", stdev(dfsTimeList)) print("Manhattan Standard Deviation Path Length:", stdev(manLengthList)) print("Manhattan Standard Deviation Nodes Expanded:", stdev(manNodesExpandedList)) print("Manhattan Standard Deviation Time Elapsed:", stdev(manTimeList))
class NPuzzle(Problem): """ NPuzzle - Problem representation for an N-tile puzzle Provides implementations for Problem actions specific to N tile puzzles. """ def __init__(self, n, force_state=None, **kwargs): """"__init__(n, force_state, **kwargs) NPuzzle constructor. Creates an initial TileBoard of size n. If force_state is not None, the puzzle is initialized to the specified state instead of being generated randomly. The parent's class constructor is then called with the TileBoard instance and any remaining arguments captured in **kwargs. """ # Instantiate Tileboard self.puzzle = TileBoard(n, force_state=force_state) # Initialize parent class super().__init__(self.puzzle.state_tuple(), self.puzzle.goals, kwargs["g"], kwargs["h"]) # Note on **kwargs: # **kwargs is Python construct that captures any remaining arguments # into a dictionary. The dictionary can be accessed like any other # dictionary, e.g. kwargs["keyname"], or passed to another function # as if each entry was a keyword argument: # e.g. foobar(arg1, arg2, …, argn, **kwargs). def actions(self, state): """actions(state) - find a set of actions applicable to specified state""" # Convert state tuple to 2D list boarddims = [self.puzzle.get_rows(), self.puzzle.get_cols()] state_list = [ state[i:i + boarddims[0]] for i in range(0, len(state), boarddims[0]) ] # Find empty tile coordinates found = False for y in range(len(state_list)): for x in range(len(state_list[y])): if state_list[y][x] is None: empty = [y, x] found = True break if found: break actions = [] # Initialize empty list for actions for dim in [0, 1]: # rows, then columns # Append offsets to the actions list, # e.g. move left --> (0, -1) # move down --> (1, 0) # Note that when we append to the list of actions, # we use list( ) to make a copy of the list, otherwise # we just get a pointer to it and modification of offset # will change copies in the list. offset = [0, 0] # Add if we don't go off the top or left if empty[dim] - 1 >= 0: offset[dim] = -1 actions.append(list(offset)) # Append if we don't go off the bottom or right if empty[dim] + 1 < boarddims[dim]: offset[dim] = 1 actions.append(list(offset)) return actions def result(self, state, action): """result(state, action)- apply action to state and return new state""" # Convert tuple into 2D list n = self.puzzle.get_rows() state_list = [list(state[i:i + n]) for i in range(0, len(state), n)] # Find empty tile coordinates r = c = 0 found = False for y in range(len(state_list)): for x in range(len(state_list[y])): if state_list[y][x] is None: r, c = y, x found = True break if found: break [delta_r, delta_c] = action # Validate actions rprime = r + delta_r cprime = c + delta_c if rprime < 0 or cprime < 0 or \ rprime >= n or cprime >= n: raise ValueError("Illegal move (%d,%d) from (%d,%d)" % (delta_r, delta_c, r, c)) # Apply move offset accordingly if delta_r != 0: # Move up or down state_list[r][c] = state_list[rprime][c] state_list[rprime][c] = None elif delta_c != 0: # Move left or right state_list[r][c] = state_list[r][cprime] state_list[r][cprime] = None # Create new state after moving empty new_state = [item for sublist in state_list for item in sublist] # Convert to tuple (hashable) and return return tuple(new_state) def goal_test(self, state): """goal_test(state) - Is state a goal?""" # If state is in puzzle goals, return True goal = state in self.puzzle.goals return goal def value(self, state): pass