def a_star(board, heuristic):
    """
    A*算法主题

    :param board: 要解决的游戏
    :param heuristic: 选择的启发函数
    :return: 返回的解的路径
    """

    frontier = PriorityQueue()
    node = Node(board)
    frontier.add(node, heuristic(node.data) + len(node.path()) - 1)

    explored = []

    while frontier.has_next():
        node = frontier.pop()

        if node.data.is_solved():
            return node.path()

        for move in node.data.legal_moves():
            child = Node(node.data.forecast(move), node)
            if (not frontier.has(child)) and (child.data not in explored):
                frontier.add(child,
                             heuristic(child.data) + len(child.path()) - 1)
            elif frontier.has(child):
                child_value = heuristic(child.data) + len(child.path()) - 1
                if child_value < frontier.get_value(child):
                    frontier.remove(child)
                    frontier.add(child, child_value)

        explored.append(node.data)

    return None
예제 #2
0
def greedy_best_first(board, heuristic):
    """
    an implementation of the greedy best first search algorithm. it uses a heuristic function to find the quickest
    way to the destination

    :param board: (Board) the board you start at
    :param heuristic: (function) the heuristic function
    :return: (list) path to solution, (int) number of explored boards
    """

    frontier = PriorityQueue()
    node = Node(board)
    frontier.add(node, heuristic(node.data))

    explored = []
    while frontier.has_next():
        node = frontier.pop()

        if node.data.is_solved():
            return node.path(), len(explored) + 1

        for move in node.data.legal_moves():
            child = Node(node.data.forecast(move), node)
            if (not frontier.has(child)) and (child.data not in explored):
                frontier.add(child, heuristic(child.data))

        explored.append(node.data)

    return None, len(explored)
예제 #3
0
def a_star(board, heuristic):
    """
    solves the board using the A* approach accompanied by the heuristic function

    :param board: board to solve
    :param heuristic: heuristic function
    :return: path to solution, and number of explored nodes
    """

    frontier = PriorityQueue()
    node = Node(board)
    frontier.add(node, heuristic(node.data) + len(node.path()) - 1)

    explored = []

    while frontier.has_next():
        node = frontier.pop()

        # check if solved
        if node.data.is_solved():
            return node.path(), len(explored) + 1

        # add children to frontier
        for move in node.data.legal_moves():
            child = Node(node.data.forecast(move), node)
            # child must not have already been explored
            if (not frontier.has(child)) and (child.data not in explored):
                frontier.add(child,
                             heuristic(child.data) + len(child.path()) - 1)
            # if the child is already in the frontier, it can be added only if it's better
            elif frontier.has(child):
                child_value = heuristic(child.data) + len(child.path()) - 1
                if child_value < frontier.get_value(child):
                    frontier.remove(child)
                    frontier.add(child, child_value)

        explored.append(node.data)

    return None, len(explored)
예제 #4
0
def compute_path(grid, start, goal, cost, heuristic):

    # Use the OrderedSet for your closed list
    closed_set = OrderedSet()

    # Use thePriorityQueue for the open list
    open_set = PriorityQueue(order=min, f=lambda v: v.f)

    # Keep track of the parent of each node. Since the car can take 4 distinct orientations,
    # for each orientation we can store a 2D array indicating the grid cells.
    # E.g. parent[0][2][3] will denote the parent when the car is at (2,3) facing up
    parent = [[[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))],
              [[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))],
              [[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))],
              [[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))]]

    # The path of the car
    path = [['-' for row in range(len(grid[0]))] for col in range(len(grid))]

    x = start[0]
    y = start[1]
    theta = start[2]
    h = heuristic[x][y]
    g = 0
    f = g + h

    # your code: implement A*
    open_set.put(start, Value(f=f, g=g))
    while open_set.__len__() != 0:
        node = open_set.pop()
        g = node[1].g
        x = node[0][0]
        y = node[0][1]
        theta = node[0][2]
        #if reach the goal, break
        if (node[0] == goal):
            closed_set.add(node[0])
            break
        closed_set.add(node[0])
        for idx, act in enumerate(action):
            new_theta = (theta + act) % 4
            #use orientation to determine the position
            new_x = x + forward[new_theta][0]
            new_y = y + forward[new_theta][1]
            #to make sure it won't break the node is naviable
            if (new_x < 0 or new_x > 4 or new_y < 0 or new_y > 5
                    or grid[new_x][new_y] == 1):
                continue
            new_g = g + cost[idx]
            new_h = heuristic[new_x][new_y]
            new_f = new_g + new_h
            child = [(new_x, new_y, new_theta), Value(f=new_f, g=new_g)]
            if (child[0] not in closed_set and child[0] not in open_set):
                open_set.put(child[0], child[1])
                parent[new_theta][new_x][new_y] = (action_name[idx], node[0])
            #if the cost decreased, add it to the openlist
            elif (open_set.has(child[0]) and open_set.get(child[0]).g > new_g):
                open_set.put(child[0], child[1])
                parent[new_theta][new_x][new_y] = (action_name[idx], node[0])
            #recording the path in parent

    #reach the goal
    path[x][y] = '*'
    #find out the path by recalling step by step
    while (x, y, theta) != start:
        pre_step = parent[theta][x][y]
        x = pre_step[1][0]
        y = pre_step[1][1]
        theta = pre_step[1][2]
        path[x][y] = pre_step[0]

    # Initially you may want to ignore theta, that is, plan in 2D.
    # To do so, set actions=forward, cost = [1, 1, 1, 1], and action_name = ['U', 'L', 'R', 'D']
    # Similarly, set parent=[[' ' for row in range(len(grid[0]))] for col in range(len(grid))]

    return path, closed_set
예제 #5
0
def compute_path(grid, start, goal, cost, heuristic):

    # Use the OrderedSet for your closed list
    closed_set = OrderedSet()

    # Use thePriorityQueue for the open list
    open_set = PriorityQueue(order=min, f=lambda v: v.f)

    # Keep track of the parent of each node. Since the car can take 4 distinct orientations,
    # for each orientation we can store a 2D array indicating the grid cells.
    # E.g. parent[0][2][3] will denote the parent when the car is at (2,3) facing up
    parent = [[[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))],
              [[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))],
              [[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))],
              [[' ' for row in range(len(grid[0]))]
               for col in range(len(grid))]]

    # The path of the car
    path = [['-' for row in range(len(grid[0]))] for col in range(len(grid))]

    x = start[0]
    y = start[1]
    theta = start[2]
    h = heuristic[x][y]
    g = 0
    f = g + h
    open_set.put(start, Value(f=f, g=g))

    # your code: implement A*

    # Initially you may want to ignore theta, that is, plan in 2D.
    # To do so, set actions=forward, cost = [1, 1, 1, 1], and action_name = ['U', 'L', 'R', 'D']
    # Similarly, set parent=[[' ' for row in range(len(grid[0]))] for col in range(len(grid))]

    path[goal[0]][goal[1]] = '*'
    l = []
    l.append(start)

    while (len(open_set) != 0):
        curr_node = open_set.pop()
        if (curr_node[0][:2] != start[:2]):
            path[l[-1][0]][l[-1][1]] = curr_node[1].g
        l.append(curr_node[0])
        if (curr_node[0] == goal):
            print("get path!")
            closed_set.add(curr_node)
            break
        closed_set.add(curr_node)
        x_current = curr_node[0][0]  #row of current node
        y_current = curr_node[0][1]  #col of current node
        o_current = curr_node[0][2]  #orientation of current node

        for i_act, act in enumerate(action):
            o_next = (o_current + act) % 4  #orientation of next node
            x_next = x_current + forward[o_next][0]  #row of next node
            y_next = y_current + forward[o_next][1]  #col of next node
            n_act = action_name[
                i_act]  #action to get this next node, this cause the one step delay in the display

            if (x_next >= 0 and x_next < len(grid) and y_next >= 0
                    and y_next < len(grid[0])
                ):  #filter the available child (map boundery and barrier)
                if (grid[x_next][y_next] == 0):
                    F_cost = cost[i_act] + heuristic[x_next][
                        y_next]  # abs(x_next - goal[0]) + abs(y_next - goal[1]) #calculate the f(n) = g(n) + h(n)
                    if ((not open_set.has((x_next, y_next, o_next)))
                            or (not closed_set.has((x_next, y_next, o_next)))):
                        open_set.put((x_next, y_next, o_next),
                                     Value(f=F_cost, g=n_act))
                        #parent[x_next][y_next] = (x_next, y_next, o_next)
                    elif (open_set.has((x_next, y_next, o_next))
                          and F_cost < open_set.get(
                              (x_next, y_next, o_next)).f):
                        open_set.get((x_next, y_next, o_next)).f = F_cost
                        open_set.get((x_next, y_next, o_next)).g = n_act

    if (curr_node[0] != goal): print("fail to find the path!")
    return path, closed_set