def main(): # Task 1 map = Map_Obj(1) start_state = (map, map.get_start_pos()[0], map.get_start_pos()[1]) a_star = AStar(start_state, walking_distance, generate_adjacent_states, goal_evaluate) node_path = a_star.run() pos_path = [] for node in node_path: pos_path.append([node.state[1], node.state[2]]) print('Positions in the path of task 1:') print(pos_path) visualise_path_map(map, pos_path) # Task 2 map = Map_Obj(2) start_state = (map, map.get_start_pos()[0], map.get_start_pos()[1]) a_star = AStar(start_state, walking_distance, generate_adjacent_states, goal_evaluate) node_path = a_star.run() pos_path = [] for node in node_path: pos_path.append([node.state[1], node.state[2]]) print('Positions in the path of task 2:') print(pos_path) visualise_path_map(map, pos_path)
def best_friend_search(): open_nodes = [] closed = [] map_obj = Map_Obj(task=4) endpos = map_obj.get_goal_pos() start = Node(None, map_obj.get_start_pos(), endpos, 0) start.g = 0 open_nodes.insert(0, start) i = 0 while True: current = open_nodes.pop(0) if current.pos == endpos: print("Finished after {} iterations".format(i)) endnode = current while current.parent is not None: map_obj.save_frame(i) print(current.pos) current = current.parent map_obj.set_cell_value(current.pos, 'p') i += 1 map_obj.save_frame(i) return endnode, map_obj for pos in current.get_adjacent(): if pos in [node.pos for node in closed]: continue if map_obj.get_cell_value(pos) == -1: continue cost = map_obj.get_cell_value(pos) if pos in [node.pos for node in open_nodes]: for node in open_nodes: if node.pos == pos: node.propogate(current) break continue neighbour = Node(current, pos, endpos, current.g + cost) current.children.append(neighbour) priority_insert(open_nodes, neighbour) map_obj.set_cell_value(pos, 'o') closed.append(current) map_obj.set_cell_value(current.pos, 0) if len(open_nodes) == 0: print("No path found") return None, map_obj #if not i%10: map_obj.save_frame(i) i += 1
def main(): map_obj = Map_Obj(task=5) start_state = (map_obj, *map_obj.get_start_pos()) heuristic_func = samf_chase_heuristic output = a_star(start_state, heuristic_func, successors_gen, goal_predicate, cost_func=cost_func) for coords in output: map_obj.set_cell_value(coords, "☺", str_map=True) map_obj.show_map()
def main(): for task in range( 1, 5): # runs through tasks 1 - 4, continues after key input map_obj = Map_Obj(task=task) start_state = (map_obj, *map_obj.get_start_pos()) heuristic_func = manhattan output = a_star(start_state, heuristic_func, successors_gen, goal_predicate, cost_func=cost_func) for coords in output: map_obj.set_cell_value(coords, "☺", str_map=True) map_obj.show_map() input()
class BestSearchFirst: def __init__(self, task=1): self.state_dictionary = {} self.open = [ ] # Sorted by ascending f values, nodes with lot of promise popped early, contains unexpanded nodes self.closed = [] # no order, contains expanded nodes self.map = Map_Obj(task) # the map # creates a new state with coordinates of the goal position from map self.goal = State(tuple(self.map.get_goal_pos())) # creates a new state as current state with the coordinates of the start position from map self.current_state = State(tuple(self.map.get_start_pos())) self.root_node = Node(self.current_state) # root of the search tree self.root_node.g = 0 self.heuretic_evaluation(self.root_node) # all of the f, g, h variables are taken from the appendix added to the task. self.root_node.f = self.root_node.g + self.root_node.h # adding the root node to the open list self.open.append(self.root_node) self.solution_node = None # Hopefully the goal def arc_cost(self, p, c): """ This calculates the arc cost between two nodes (parent and child) using the cost of the child node (the one you are moving to)""" return self.map.get_cell_value(c.state.coordinates) def propagate_path_improvements(self, p): """ Goes through the children of a parent node and updates the cost of going to the child from the parent if it less than the current cost of going to the child. This is done recursively """ for c in p.childs: if p.g + self.arc_cost(p, c) < c.g: c.parent = p c.g = p.g + self.arc_cost(p, c) c.f = c.g + c.h self.propagate_path_improvements(c) def agenda_loop(self): """ Agenda loop """ it = 0 solution = False while not solution: it += 1 if not self.open: # in these tasks with obvious solutions something must be wrong with the implementation print("Something definitely went wrong!") return False x = self.open.pop() self.closed.append(x) solution_state = None if self.check_solution(x): solution = True self.solution_node = x else: # generating the successor nodes, expanding x successors = self.generate_successor_nodes(x) for s in successors: # go through each of these children in_open = False in_closed = False if s in self.open: in_open = True s_star = self.open[self.open.index(s)] if s.state == s_star.state: s = s_star elif s in self.closed: in_closed = True s_star = self.closed[self.closed.index(s)] if s.state == s_star.state: s = s_star # s is a child of x even though x might not be the best parent x.childs.append(s) if not in_open and not in_closed: # attach the new succesor (it just got explored) with parent x self.attach_and_eval(s, x) self.open.append(s) # we will expand this node later self.open = sorted(self.open, key=lambda val: val.f, reverse=True) # sorting open list in descending based on f value, pop function takes from the back of the list elif x.g + self.arc_cost( x, s) < s.g: # found cheaper path to s # attaches s to a new parent x self.attach_and_eval(s, x) if in_closed: # propagate the improved path to s through all of s children (and their children) self.propagate_path_improvements(s) return solution, solution_state def attach_and_eval(self, c, p): """ Simply attaches a child node to a node that is now considered its best parent (so far) """ c.parent = p c.g = p.g + self.arc_cost(p, c) self.heuretic_evaluation(c) c.f = c.g + c.h # This should be changed, need to have a dictionary from coordinates to State def generate_successor_nodes(self, node): """ Given a node in the search tree this generates all possible succesor states to the node's state """ directions = [ (1, 0), (-1, 0), (0, 1), (0, -1) ] # directions you are allowed to move in (up, right, left, down) successor_nodes = [] # all the successors for i in directions: x = node.state.coordinates[0] + i[0] y = node.state.coordinates[1] + i[1] if tuple((x, y)) in self.state_dictionary: successor_nodes.append(self.state_dictionary.get(tuple( (x, y)))) else: value = self.map.get_cell_value((x, y)) if value != -1: # if it isn't a wall we will add the new node and state to the successors state = State((x, y)) child = Node(state) self.state_dictionary[tuple((x, y))] = child self.heuretic_evaluation(child) child.g = node.g + self.arc_cost(node, child) child.f = child.g + child.h successor_nodes.append(child) return successor_nodes def heuretic_evaluation(self, node): """ Gives a heuretic evaluation of the distance to the goal using manhattan distance """ heuretic = abs(self.goal.coordinates[0] - node.state.coordinates[0] ) + abs(self.goal.coordinates[1] - node.state.coordinates[1]) node.h = heuretic return heuretic def check_solution(self, node): """ Compares the state of the nodes to the goal state (by comparing coordinates) """ return node.state == self.goal def print_solution(self): """ Finds the given solution path by going through the parent of the solution node and going backwards to the root node, then shows the solution using the map """ child = self.solution_node parent = self.solution_node.parent solution_list = [self.solution_node.state.coordinates] while parent != None: solution_list.append(parent.state.coordinates) child = parent parent = child.parent self.map.show_solution(solution_list)