def A_star_graph_search(graph: Maze, start, goal): if goal == start: return [], [] path = [] path.append(start) path_heuristic = graph.manhattan_heuristic_calculator(start) expanded = [] frontier = [] frontier.append(Evaluation(path_heuristic, path)) while True: item = ExploreFrontier(frontier) # find the best next node to explore if item is None: break current_node = item.getFurthestNode() current_path = list(item.getPath()) current_cost = item.getCost() - graph.manhattan_heuristic_calculator( current_node) expanded.append(current_node) # if goal was in frontier if current_node == goal: return expanded, current_path nearby_nodes = (graph.getNode(current_node)).adjacent_list() for node in nearby_nodes: new_path = list(current_path) new_path.append(node) new_cost = current_cost + step_cost + graph.manhattan_heuristic_calculator( node) new_item = Evaluation(new_cost, new_path) location_in_frontier = is_in_frontier(node, frontier) if location_in_frontier is None: if node not in expanded: frontier.append(new_item) else: # replace an existing frontier node which have higher cost if frontier[location_in_frontier].getCost() > new_cost: frontier.pop(location_in_frontier) frontier.append(new_item) # no need to sort frontier 'cause ExploreFrontier can handle it return None, None
def Breadth_first_search(graph: Maze, start, goal): expanded = [] expanded_with_parent = [] frontier = [] # dict format: { "Node": 2, "Parent": 1 }, init = {"Node": start, "Parent": None} frontier.append(init) # return nothing if goal is start if start == goal: return [goal], [goal] while frontier: current_node = frontier.pop(0) node = current_node["Node"] if node not in expanded: neighbours = (graph.getNode(node)).adjacent_list() for neighbour in neighbours: if neighbour == goal: expanded.append(node) expanded.append(goal) expanded_with_parent.append(current_node) expanded_with_parent.append({"Node": goal, "Parent": node}) path_to_node = tracePath(expanded_with_parent, start, neighbour) return expanded, path_to_node else: new_node = {"Node": int(neighbour), "Parent": node} frontier.append(new_node) expanded.append(node) expanded_with_parent.append(current_node) return expanded, None
def A_star_graph_search(graph: Maze, start, goal): if goal == start: return [goal], [goal] start_heuristic = graph.manhattan_heuristic_calculator(start) init = {"Node": start, "Parent": None, "Cost": start_heuristic} expanded = [] expanded_with_parent = [] frontier = [] frontier.append(init) while True: item = ExploreFrontier(frontier)# find the best next node to explore if item is None: #print(expanded) break expanded.append(item["Node"]) expanded_with_parent.append(item) # if goal was in frontier if item["Node"] == goal: current_path = tracePath(expanded_with_parent, start, item["Node"]) return expanded, current_path current_cost = item["Cost"] - graph.manhattan_heuristic_calculator(item["Node"]) nearby_nodes = (graph.getNode(item["Node"])).adjacent_list() for node in nearby_nodes: new_cost = current_cost + step_cost + graph.manhattan_heuristic_calculator(node) new_item = {"Node": node, "Parent": item["Node"], "Cost": new_cost} location_in_frontier = is_in_frontier(node, frontier) if location_in_frontier is None: if node not in expanded: frontier.append(new_item) else: temp = frontier[location_in_frontier] if temp["Cost"] > new_item["Cost"]: frontier.pop(location_in_frontier) frontier.append(new_item) # no need to sort frontier 'cause ExploreFrontier can handle it return expanded, None
def Iterative_deepening_search(graph: Maze, start, goal): # Repeatedly depth-limit search till the maximum depth expanded_by_depth = [] result_path = [] size = graph.getSize() max_depth = size * size for lim in range(0, max_depth): expanded = [] init_node = {"Node":start, "Parent": None} is_right, path = recursive_depth_limited_search(graph, init_node, goal, lim, expanded) expanded_by_depth.append(expanded) if is_right: result_path = list(path) break return expanded_by_depth, result_path
def Uniform_cost_search(graph: Maze, start, goal): if goal == start: return [], [] path_cost = 0 path = [] path.append(start) expanded = [] frontier = [] frontier.append(Evaluation(path_cost, path)) while True: item = ExploreFrontier(frontier) if item is None: break current_node = item.getFurthestNode() current_path = list(item.getPath()) current_cost = item.getCost() # print(current_path) expanded.append(current_node) # if goal was in frontier if current_node == goal: return expanded, current_path nearby_nodes = (graph.getNode(current_node)).adjacent_list() for node in nearby_nodes: new_path = list(current_path) new_path.append(node) new_cost = current_cost + step_cost new_item = Evaluation(new_cost, new_path) in_frontier = is_in_frontier(node, frontier) if in_frontier is None: if node not in expanded: frontier.append(new_item) else: if frontier[in_frontier].getCost() > new_cost: frontier.pop(in_frontier) frontier.append(new_item) # no need to sort frontier 'cause ExploreFrontier can handle it return None, None
def recursive_depth_limited_search(graph: Maze, current_node: dict, goal, limit, expanded): expanded.append(current_node["Node"]) if(current_node["Node"] == goal): return True, [current_node["Node"]] # If reached the depth limit, stop recursing. if limit <= 0 : return False, [] node: Node = graph.getNode(current_node["Node"]) nearby_nodes = node.adjacent_list() path = [current_node["Node"]] # Recur for all the vertices adjacent to this vertex for item in nearby_nodes: if item != current_node["Parent"]: next_node = {"Node" : item, "Parent" : current_node["Node"]} res, child_path = recursive_depth_limited_search(graph, next_node, goal, limit - 1, expanded) if(res): return True, path + child_path return False, []
def Breadth_first_search(graph: Maze, start, goal): # keep track of explored nodes expanded_list = [] # keep track of all the paths to be checked path_list = [[start]] # return nothing if goal is start if start == goal: return [], [] # test run all given paths until path_list is empty while path_list: # pop the oldest path from the path_list -> FIFO path = path_list.pop(0) # get the furthest node in path node = path[-1] if node not in expanded_list: # get node's adjacent_list neighbours = (graph.getNode(node)).adjacent_list() # if input data is wrong (no node exist at given location) if neighbours is None: # mark node as explored expanded_list.append(node) continue # check go through all neighbour nodes, create a new path and add it into the testing_paths for neighbour in neighbours: new_path = list(path) new_path.append(neighbour) path_list.append(new_path) # return path if neighbour is goal if neighbour == goal: expanded_list.append(node) expanded_list.append(goal) # task requirement return expanded_list, new_path # mark node as explored expanded_list.append(node) # if no result can be found return None, None
def recursive_depth_limited_search(graph: Maze, current_node: int, goal, limit): if(goal == None): return True, Node return None # If reached the depth limit, stop recursing. if limit <= 0 : return False, None node = graph.getNode(current_node) nearby_nodes = node.adjacent_list() path = [] path.append(current_node) # Recur for all the vertices adjacent to this vertex for item in nearby_nodes: res, _path = recursive_depth_limited_search(graph, item, goal, limit - 1) if(res): return True, path.append(path) return False, None
file_name = choose_input_files("..\INPUT") if file_name is not None: input_list = ImportData(file_name) if len(input_list) < 3: print("No data was imported") print(input_list) sys.exit() size = int(input_list.pop(0)) goal = int(input_list.pop(-1)) if (goal < 0) or (goal > int(size * size)): print( "\n[Warning]: Goal doesn't exist in Maze!\n->This might result in long runtime and uncompleted result!!\n" ) board = Maze(size, input_list, goal) # start = input("Enter the number of starting point: ") # start = int(start) start = 0 print("Starting point:\t", start) print("Goal:\t\t\t", goal) algorithms = [(Breadth_first_search), (Uniform_cost_search), (Iterative_deepening_search), (Greedy_best_first_search), (A_star_graph_search)] for method in algorithms: result = method(board, start, goal) #print(method.__name__ + " completed\n") OutputData("..\OUTPUT\ ", method.__name__, result)