import sys from collections import deque from os import path import queue import numpy from utils import * from settings import * class Problem: def __init__(self, initial, goal): self.initial = initial self.goal = goal def actions(self, state): moves = [] if self.turn_left(state): moves.append('Left') if self.turn_right(state): moves.append('Right') if self.move_forward(state): moves.append('Forward') #print(moves) return moves def turn_left(self, state): return True def turn_right(self, state): return True def move_forward(self, state): a_row = 0 a_column = 0 for row in range(MAP_SIZE): for column, pos in enumerate(state[row]): if pos == ">": a_row = row a_column = column if a_column == MAP_SIZE-1: return False elif state[a_row][a_column+1] == '.': return True return False if pos == "<": a_row = row a_column = column if a_column == 0: return False elif state[a_row][a_column-1] == '.': return True return False if pos == "v": a_row = row a_column = column if a_row == MAP_SIZE-1: return False elif state[a_row+1][a_column] == '.': return True return False if pos == "^": a_row = row a_column = column if row == 0: return False elif state[a_row-1][a_column] == '.': return True return False def turn_me_or_move(self, state, do_it): temp_map = [list(item) for item in state] #print(temp_map) #a_row = 0 #a_column = 0 for row in range(MAP_SIZE): for column, pos in enumerate(temp_map[row]): if pos == ">": a_row = row a_column = column #print("a_row:" + str(a_row)) #print("a_column" + str(a_column)) if(do_it == 'Left'): temp_map[a_row][a_column] = "^" if(do_it == 'Right'): temp_map[a_row][a_column] = 'v' if(do_it == 'Forward'): temp_map[a_row][a_column] = '.' temp_map[a_row][a_column+1] = '>' return temp_map if pos == "<": a_row = row a_column = column if(do_it == 'Left'): temp_map[a_row][a_column] = 'v' if(do_it == 'Right'): temp_map[a_row][a_column] = '^' if(do_it == 'Forward'): temp_map[a_row][a_column] = '.' temp_map[a_row][a_column-1] = '<' return temp_map if pos == "v": a_row = row a_column = column if(do_it == 'Left'): temp_map[a_row][a_column] = '>' if(do_it == 'Right'): temp_map[a_row][a_column] = '<' if(do_it == 'Forward'): temp_map[a_row][a_column] = '.' temp_map[a_row+1][a_column] = 'v' return temp_map if pos == "^": a_row = row a_column = column if(do_it == 'Left'): temp_map[a_row][a_column] = '<' if(do_it == 'Right'): temp_map[a_row][a_column] = '>' if(do_it == 'Forward'): temp_map[a_row][a_column] = '.' temp_map[a_row-1][a_column] = '^' return temp_map return temp_map def result(self, state, action): new_state = [] if action == 'Left': new_state = self.turn_me_or_move(state, 'Left') elif action == 'Right': new_state = self.turn_me_or_move(state, 'Right') elif action == 'Forward': new_state = self.turn_me_or_move(state, 'Forward') super_new_state = tuple(map(tuple,new_state)) return super_new_state def goal_test(self, state): if self.goal == state: return True return False class Node: def __init__(self, state, parent=None, action=None): """Create a search tree Node, derived from a parent by an action.""" self.state = state self.parent = parent self.action = action def __repr__(self): return "".format(self.state) def expand(self, problem): """List the nodes reachable in one step from this node.""" return [self.child_node(problem, action) for action in problem.actions(self.state)] def child_node(self, problem, action): next_state = problem.result(self.state, action) next_node = Node(next_state, self, action) return next_node def __eq__(self, other): return isinstance(other, Node) and self.state == other.state def __hash__(self): # We use the hash value of the state # stored in the node instead of the node # object itself to quickly search a node # with the same state in a Hash Table return hash(self.state) class BFS: @staticmethod def breadth_first_graph_search(problem): node = Node(problem.initial) if problem.goal_test(node.state): return node frontier = deque([node]) final_child = node history = [] explored = set() while frontier: node = frontier.popleft() explored.add(node.state) for child in node.expand(problem): if child.state not in explored and child not in frontier: if problem.goal_test(child.state): while(child.parent != None): history.append(child.action) child = child.parent #return child history.reverse() #print(history) return history frontier.append(child) #BFS.print_node_state(child.state) return None @staticmethod def loadMap(map_name=''): maze = [] map_folder = path.dirname(__file__) with open(path.join(map_folder, map_name), 'rt') as f: for line in f: maze.append(line.rstrip('\n')) #print(maze) return maze @staticmethod def run(): initial_map = tuple(map(tuple,BFS.loadMap('bfs_maps/map.txt'))) goal_map = tuple(map(tuple,BFS.loadMap('bfs_maps/goal_map.txt'))) problem = Problem(initial_map, goal_map) #BFS.print_node_state(initial_map) #BFS.print_node_state(goal_map) result = BFS.breadth_first_graph_search(problem) print(result) return result #print(BFS.print_node_state(result)) @staticmethod def print_node_state(node_state): print(numpy.matrix(node_state))