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
Example #2
0
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)