def graph_search(problem, verbose=False, debug=False): """graph_search(problem, verbose, debug) - Given a problem representation (instance of basicsearch_lib02.representation.Problem or derived class), attempt to solve the problem. If debug is True, debugging information will be displayed. if verbose is True, the following information will be displayed: Number of moves to solution List of moves and resulting puzzle states Example: Solution in 25 moves Initial state 0 1 2 0 4 8 7 1 5 . 2 2 3 6 1 Move 1 - [0, -1] 0 1 2 0 4 8 7 1 . 5 2 2 3 6 1 Move 2 - [1, 0] 0 1 2 0 4 8 7 1 3 5 2 2 . 6 1 ... more moves ... 0 1 2 0 1 3 5 1 4 2 . 2 6 7 8 Move 22 - [-1, 0] 0 1 2 0 1 3 . 1 4 2 5 2 6 7 8 Move 23 - [0, -1] 0 1 2 0 1 . 3 1 4 2 5 2 6 7 8 Move 24 - [1, 0] 0 1 2 0 1 2 3 1 4 . 5 2 6 7 8 If no solution were found (not possible with the puzzles we are using), we would display: No solution found Returns a tuple (path, nodes_explored) where: path - list of actions to solve the problem or None if no solution was found nodes_explored - Number of nodes explored (dequeued from frontier) """ frontierNodes = PriorityQueue(min, Node.get_f) node = Node(problem, problem.getInitialBoardState()) nodesExplored = 0 exploredStates = Explored() #hash table to store states exploredStates.add(node) for node in node.expand(problem): if not exploredStates.exists(node): #its not a duplicate in explored frontierNodes.append(node) #get initial frontier nodes done = found = False while not done: node = frontierNodes.pop() #loop thru frontier states nodesExplored += 1 exploredStates.add(node) if problem.goal_test(node.state): #if found, set true found = done = True else: #if not, then add the new frontier states to the queue for node in node.expand(problem): if not exploredStates.exists( node): #its not a duplicate in explored #if not frontierNodes.__contains__(node): #not a duplicate in frontier, slow! frontierNodes.append(node) if (frontierNodes.__len__ == 0 ): #if we run thru all frontier, search complete done = True if found: if (verbose): print("Moves to solution: ", node.path().__len__()) print("Nodes Expanded: ", nodesExplored) move = 0 solutionList = node.solution() boardList = [] for node in node.path(): boardList.append(problem.generateDebugBoard(node.state)) print("Initial State") for board in boardList: counter = move + 1 print(board) print() if (move < boardList.__len__() - 1): print("Move ", counter, " ", solutionList[move]) move += 1 if (debug): print() print("Debug Info:") print(print_nodes(node.path())) print() return (node.solution(), nodesExplored ) #returns solution node's path/solution else: if (verbose | debug): print("No solution found") return ("No solution found", nodesExplored)
def graph_search(problem, verbose=False, debug=False): """graph_search(problem, verbose, debug) - Given a problem representation (instance of basicsearch_lib02.representation.Problem or derived class), attempt to solve the problem. If debug is True, debugging information will be displayed. if verbose is True, the following information will be displayed: Number of moves to solution List of moves and resulting puzzle states Example: Solution in 25 moves Initial state 0 1 2 0 4 8 7 1 5 . 2 2 3 6 1 Move 1 - [0, -1] 0 1 2 0 4 8 7 1 . 5 2 2 3 6 1 Move 2 - [1, 0] 0 1 2 0 4 8 7 1 3 5 2 2 . 6 1 ... more moves ... 0 1 2 0 1 3 5 1 4 2 . 2 6 7 8 Move 22 - [-1, 0] 0 1 2 0 1 3 . 1 4 2 5 2 6 7 8 Move 23 - [0, -1] 0 1 2 0 1 . 3 1 4 2 5 2 6 7 8 Move 24 - [1, 0] 0 1 2 0 1 2 3 1 4 . 5 2 6 7 8 If no solution were found (not possible with the puzzles we are using), we would display: No solution found Returns a tuple (path, nodes_explored) where: path - list of actions to solve the problem or None if no solution was found nodes_explored - Number of nodes explored (dequeued from frontier) """ #Initial tileboard for testing tb = problem.initial #Create first node and test if node passes goal node0 = Node(problem, tb) if problem.goal_test(node0.state) == True: return node0.solution() #define frontier set as priority queue and the explored set pq = PriorityQueue() pq.append(node0) new_nodes = [] exploredSet = Explored() frontier = Explored() frontier.add(node0) nodesExpanded = 0 #Expand the search tree until the goal state is found found = False #time.sleep(2) while (not found): #Check if the frontier is empty signifying failure if pq.__len__() == 0: print("No solution found") break #Take the next node from the priority queue and add it to explored set node = pq.pop() exploredSet.add(node) #Check if the goal state has been found if problem.goal_test(node.state) == True: path = node.path() solution = node.solution() steps = len(path) - 1 found = True if verbose == True: verboseFunc(solution, steps, tb, path) else: #Expand the search tree and check if the nodes have been explored new_nodes = node.expand(problem) for j in range(len(new_nodes)): if exploredSet.exists(new_nodes[j].state) or frontier.exists( new_nodes[j].state): continue else: #Add one to the number of nodes explored nodesExpanded += 1 pq.append(new_nodes[j]) #Add the nodes to the priority queue frontier.add( new_nodes[j]) #use hashed set to decrease lookup time if debug == True: debugFunc(debug, pq) return (steps, nodesExpanded)
def graph_search(problem, verbose=False, debug=False): """graph_search(problem, verbose, debug) - Given a problem representation (instance of basicsearch_lib02.representation.Problem or derived class), attempt to solve the problem. If debug is True, debugging information will be displayed. if verbose is True, the following information will be displayed: Number of moves to solution List of moves and resulting puzzle states Example: Solution in 25 moves Initial state 0 1 2 0 4 8 7 1 5 . 2 2 3 6 1 Move 1 - [0, -1] 0 1 2 0 4 8 7 1 . 5 2 2 3 6 1 Move 2 - [1, 0] 0 1 2 0 4 8 7 1 3 5 2 2 . 6 1 ... more moves ... 0 1 2 0 1 3 5 1 4 2 . 2 6 7 8 Move 22 - [-1, 0] 0 1 2 0 1 3 . 1 4 2 5 2 6 7 8 Move 23 - [0, -1] 0 1 2 0 1 . 3 1 4 2 5 2 6 7 8 Move 24 - [1, 0] 0 1 2 0 1 2 3 1 4 . 5 2 6 7 8 If no solution were found (not possible with the puzzles we are using), we would display: No solution found Returns a tuple (path, nodes_explored) where: path - list of actions to solve the problem or None if no solution was found nodes_explored - Number of nodes explored (dequeued from frontier) """ path = [] nodes_explored = 0 return_tuple = () node = Node(problem, problem.initial) # root node frontier = PriorityQueue(order=min, f=lambda x: x.get_f()) # todo Sort this out explored = Explored() frontier.append(node) if problem.goal_test(node.state): path = node.solution() return_tuple = (path, nodes_explored) return return_tuple counter = 0 while True: if frontier.__len__() == 0: path = node.solution() nodes_explored = counter return_tuple = (path, nodes_explored) return return_tuple node = frontier.pop() if problem.goal_test(node.state): break child_nodes = node.expand(problem) if explored.add(node.state): counter = counter + 1 for child_node in child_nodes: if child_node not in frontier and not explored.exists( child_node.state): frontier.append(child_node) path = node.solution() node_path = node.path() if verbose: print("Solution in " + str(len(node_path) - 1) + " moves.") i = 0 for sol in node_path: if i is 0: print("Initial state") print(sol.state) i = i + 1 continue print("Move " + str(i) + " - " + str(path[i - 1])) print(sol.state) i = i + 1 nodes_explored = counter return_tuple = (path, nodes_explored) return return_tuple