Example #1
0
def astar_search(grid_size, start, goal, obstacles, costFn, logger):
    """
    A* search algorithm finds the optimal path from the start cell to the
    goal cell in the 2D grid world.

    After expanding a node, to retrieve the cost of a child node at location (x,y), 
    please call costFn((x,y)). In all of the grid maps, the cost is always 1.  

    See depth_first_search() for details.    
    """
    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    ##########################################
    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = PriorityQueue(order="min", f=lambda v: abs(v))
    closed_set = Queue()
    ##########################################

    ##########################################
    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set
    ##########################################

    movement = []

    # ----------------------------------------
    # finish the code below to implement a Manhattan distance heuristic
    # ----------------------------------------

    #############################################################################
    def heuristic(row, col):
        R = goal[0] - row
        C = goal[1] - col
        hyp = R * R + C * C
        return abs(math.sqrt(hyp))

    def Gvalue(row, col):
        return abs(goal[0] - row + goal[1] - col)

    def backtrace(parent, start, goal):

        path = [goal]
        while path[-1] != start:
            path.append(parent[path[-1]])
        path.reverse()

        iter = len(path)
        i = 0
        while i < iter - 1:

            R = path[i + 1][0] - path[i][0]
            C = path[i + 1][1] - path[i][1]

            if (R == -1 and C == 0):
                movement.append(ACTIONS[0])
            if (R == 0 and C == -1):
                movement.append(ACTIONS[1])
            if (R == 1 and C == 0):
                movement.append(ACTIONS[2])
            if (R == 0 and C == 1):
                movement.append(ACTIONS[3])

            i += 1

        return movement, closed_set

    def TransitionModel(node, value):
        current_row = node[0]
        current_col = node[1]
        direction_can_go = []

        #down
        TempRow = current_row
        TempCol = current_col + 1
        TempNode = (TempRow, TempCol)

        # print("TempNode ::",TempNode)

        if TempNode not in obstacles and TempRow >= 0 and TempCol >= 0 and TempRow <= n_rows and TempCol <= n_cols:
            returnnode = [
                TempNode,
                Gvalue(TempRow, TempCol) + heuristic(TempRow, TempCol)
            ]
            direction_can_go.append(returnnode)

        #right
        TempRow = current_row + 1
        TempCol = current_col
        TempNode = (TempRow, TempCol)

        if TempNode not in obstacles and TempRow >= 0 and TempCol >= 0 and TempRow <= n_rows and TempCol <= n_cols:
            returnnode = [
                TempNode,
                Gvalue(TempRow, TempCol) + heuristic(TempRow, TempCol)
            ]
            direction_can_go.append(returnnode)

        #left
        TempRow = current_row - 1
        TempCol = current_col
        TempNode = (TempRow, TempCol)

        if TempNode not in obstacles and TempRow >= 0 and TempCol >= 0 and TempRow <= n_rows and TempCol <= n_cols:
            returnnode = [
                TempNode,
                Gvalue(TempRow, TempCol) + heuristic(TempRow, TempCol)
            ]
            direction_can_go.append(returnnode)
        #up
        TempRow = current_row
        TempCol = current_col - 1
        TempNode = (TempRow, TempCol)

        if TempNode not in obstacles and TempRow >= 0 and TempCol >= 0 and TempRow <= n_rows and TempCol <= n_cols:
            returnnode = [
                TempNode,
                Gvalue(TempRow, TempCol) + heuristic(TempRow, TempCol)
            ]
            direction_can_go.append(returnnode)

    # print("direction_can_go ::",direction_can_go)
    #print("node ::",node)
        return direction_can_go

    open_set.put(start, 0)
    parent = {}
    while len(open_set):
        node, value = open_set.pop()

        if node == goal:
            print("found it")
            movement, closed_set = backtrace(parent, start, goal)
            print("movement ::", movement)
            return movement, closed_set

        #costFn(node)
        closed_set.add(node)

        actions_posible = TransitionModel(node, value)

        for nextnode in actions_posible:
            #print("nextnode ::" ,nextnode[0])
            if nextnode[0] not in closed_set and nextnode[0] not in open_set:
                open_set.put(nextnode[0], nextnode[1])
                parent[nextnode[0]] = node
            elif nextnode[0] in open_set and nextnode[1] < open_set.get(
                    nextnode[0]):
                open_set.put(nextnode[0], nextnode[1])
                parent[nextnode[0]] = node


#############################################################################
    return movement, closed_set
Example #2
0
def depth_first_search(grid_size, start, goal, obstacles, costFn, logger):
    """
    DFS algorithm finds the path from the start cell to the
    goal cell in the 2D grid world.

    After expanding a node, to retrieve the cost of a child node at location (x,y), 
    please call costFn((x,y)). 
    
    Parameters
    ----------
    grid_size: tuple, (n_rows, n_cols)
        (number of rows of the grid, number of cols of the grid)
    start: tuple, (row, col)
        location of the start cell;
        row and col are counted from 0, i.e. the 1st row is 0
    goal: tuple, (row, col)
        location of the goal cell
    obstacles: tuple, ((row, col), (row, col), ...)
        locations of obstacles in the grid
        the cells where obstacles are located are not allowed to access 
    costFn: a function that returns the cost of landing to a cell (x,y)
         after taking an action. 
    logger: a logger to visualize the search process.
         Do not do anything to it.

   

    Returns
    -------
    movement along the path from the start to goal cell: list of actions
        The first returned value is the movement list found by the search
        algorithm from the start cell to the end cell.
        The movement list should be a list object composed of actions
        that should move the agent from the start to goal cell along the path
        as found by the algorithm.
        For example, if nodes in the path from the start to end cell are:
            (0, 0) (start) -> (0, 1) -> (1, 1) -> (1, 0) (goal)
        then, the returned movement list should be
            [(0,1), (1,0), (0, -1)]
        which means: move right, down, left.

        Return an EMPTY list if the search algorithm fails finding any
        available path.
        
    closed set: list of location tuple (row, col)
        The second returned value is the closed set, namely, the cells are expanded during search.
    """
    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    ##########################################
    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = Stack()
    closed_set = Queue()
    ##########################################

    ##########################################
    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set
    ##########################################

    parent = [  # the immediate predecessor cell from which to reach a cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]
    actions = [  # the action that the parent took to reach the cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]

    movement = []
    path_storage = {}
    # ----------------------------------------
    # finish the code below
    # ----------------------------------------
    #############################################################################
    open_set.add(start)
    i = 0
    while open_set:
        child = []
        node_current = open_set.pop()
        closed_set.add(node_current)
        current_row, current_col = node_current
        child = [
            (current_row - 1, current_col), (current_row, current_col + 1),
            (current_row + 1, current_col), (current_row, current_col - 1)
        ]

        for child_node in child:
            child_row, child_col = child_node
            if child_node not in obstacles and child_row >= 0 and child_col >= 0 and child_row < n_rows and child_col < n_cols:
                print('Child node is', child_node)
                if child_node not in closed_set and child_node not in open_set:
                    if child_node == goal:
                        path_storage[child_node] = node_current
                        path_list = [goal]
                        print('The goal is', goal)
                        while path_list[-1] != start:
                            print('The parent node is',
                                  path_storage[path_list[-1]])
                            path_list.append(path_storage[path_list[-1]])
                        path_list.reverse()
                        iter = 0
                        for iter in range(len(path_list) - 1):
                            r, c = path_list[iter]
                            r2, c2 = path_list[iter + 1]
                            row = r2 - r
                            col = c2 - c
                            if (row == -1 and col == 0):
                                movement.append((-1, 0))
                            if (row == 0 and col == -1):
                                movement.append((0, -1))
                            if (row == 1 and col == 0):
                                movement.append((1, 0))
                            if (row == 0 and col == 1):
                                movement.append((0, 1))
                            iter += 1
                        return movement, closed_set
                    else:
                        open_set.add(child_node)
                        path_storage[child_node] = node_current
        i += 1


#############################################################################
    return movement, closed_set
Example #3
0
def astar_search(grid_size, start, goal, obstacles, costFn, logger):
    """
    A* search algorithm finds the optimal path from the start cell to the
    goal cell in the 2D grid world.

    After expanding a node, to retrieve the cost of a child node at location (x,y), 
    please call costFn((x,y)).   

    See depth_first_search() for details.    
    """
    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    ##########################################
    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = PriorityQueue(order="min", f=lambda v: v)
    closed_set = Queue()
    ##########################################

    ##########################################
    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set
    ##########################################

    parent = [  # the immediate predecessor cell from which to reach a cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]
    actions = [  # the action that the parent took to reach the cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]

    movement = []
    path_storage = {}

    # ----------------------------------------
    # finish the code below to implement a Manhattan distance heuristic
    # ----------------------------------------
    def heuristic(row, col):
        #############################################################################
        return abs(goal_row - row) + abs(goal_col - col)


#############################################################################

    open_set.put(start, 0)
    i = 0
    while open_set:
        child = []
        node_current, v = open_set.pop()
        closed_set.add(node_current)
        current_row, current_col = node_current
        h = heuristic(current_row, current_col)
        cost_child = v - h

        child = [((current_row + 1, current_col), cost_child + costFn(
            (current_row + 1, current_col)) +
                  heuristic(current_row + 1, current_col)),
                 ((current_row, current_col - 1), cost_child + costFn(
                     (current_row, current_col - 1)) +
                  heuristic(current_row, current_col - 1)),
                 ((current_row - 1, current_col), cost_child + costFn(
                     (current_row - 1, current_col)) +
                  heuristic(current_row - 1, current_col)),
                 ((current_row, current_col + 1), cost_child + costFn(
                     (current_row, current_col + 1)) +
                  heuristic(current_row, current_col + 1))]

        for node in child:
            child_node, cost = node
            child_row, child_col = child_node
            if child_node not in obstacles and child_row >= 0 and child_col >= 0 and child_row < n_rows and child_col < n_cols:
                if child_node not in closed_set and child_node not in open_set:
                    print('Child node is', node)
                    if child_node == goal:
                        path_storage[child_node] = node_current
                        path_list = [goal]
                        print('The goal is', goal)
                        while path_list[-1] != start:
                            print('The parent node is',
                                  path_storage[path_list[-1]])
                            path_list.append(path_storage[path_list[-1]])
                        path_list.reverse()
                        iter = 0
                        for iter in range(len(path_list) - 1):
                            r, c = path_list[iter]
                            r2, c2 = path_list[iter + 1]
                            row = r2 - r
                            col = c2 - c
                            if (row == -1 and col == 0):
                                movement.append((-1, 0))
                            if (row == 0 and col == -1):
                                movement.append((0, -1))
                            if (row == 1 and col == 0):
                                movement.append((1, 0))
                            if (row == 0 and col == 1):
                                movement.append((0, 1))
                            iter += 1
                        return movement, closed_set
                    else:
                        open_set.put(child_node, cost)
                        path_storage[child_node] = node_current

    return movement, closed_set
def astar_search(grid_size, start, goal, obstacles, costFn, logger):
    """
    A* search algorithm finds the optimal path from the start cell to the
    goal cell in the 2D grid world.

    After expanding a node, to retrieve the cost of a child node at location (x,y), 
    please call costFn((x,y)).   

    See depth_first_search() for details.    
    """
    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    ##########################################
    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = PriorityQueue(order="min", f=lambda v: v)
    closed_set = Queue()
    ##########################################

    ##########################################
    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set
    ##########################################

    parent = [  # the immediate predecessor cell from which to reach a cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]
    actions = [  # the action that the parent took to reach the cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]

    movement = []

    # ----------------------------------------
    # finish the code below to implement a Manhattan distance heuristic
    # ----------------------------------------

    def heuristic(row, col):
        #############################################################################
        h = abs(goal_row - row) + abs(goal_col - col)
        return h


#############################################################################

    '''
    Based on the pseudo code from the slides
    '''
    open_set.put(start, 0 + heuristic(start_row, start_col))
    while open_set:
        children = []
        currentNode, v = open_set.pop()
        if currentNode == goal:  # reach the goal start backtrace
            closed_set.add(
                currentNode
            )  # for the same outcome with the demo video provided
            p_row, p_col = goal
            while (p_row, p_col) != start:
                movement.append(actions[p_row][p_col])
                p_row, p_col = parent[p_row][p_col]
            movement.reverse()

            return movement, closed_set
        currentNode_row, currentNode_col = currentNode
        closed_set.add(currentNode)
        currentNodeHeuristic = heuristic(currentNode_row, currentNode_col)
        # get the g cost for compute the children's total costs
        g_cost = v - currentNodeHeuristic

        # get the children
        children = [((currentNode_row - 1, currentNode_col), g_cost + costFn(
            (currentNode_row - 1, currentNode_col)) +
                     heuristic(currentNode_row - 1, currentNode_col)),
                    ((currentNode_row, currentNode_col - 1), g_cost + costFn(
                        (currentNode_row, currentNode_col - 1)) +
                     heuristic(currentNode_row, currentNode_col - 1)),
                    ((currentNode_row + 1, currentNode_col), g_cost + costFn(
                        (currentNode_row + 1, currentNode_col)) +
                     heuristic(currentNode_row + 1, currentNode_col)),
                    ((currentNode_row, currentNode_col + 1), g_cost + costFn(
                        (currentNode_row, currentNode_col + 1)) +
                     heuristic(currentNode_row, currentNode_col + 1))]

        # expand the children
        for child in children:
            node, cost = child
            child_row, child_col = node
            if (
                    child_row, child_col
            ) not in obstacles and child_row >= 0 and child_col >= 0 and child_row < n_rows and child_col < n_cols:
                if node not in closed_set and node not in open_set:
                    open_set.put(node, cost)
                    parent[child_row][child_col] = currentNode
                    action = (child_row - currentNode_row,
                              child_col - currentNode_col)
                    if action == (-1, 0):
                        actions[child_row][child_col] = ACTIONS[0]
                    if action == (0, -1):
                        actions[child_row][child_col] = ACTIONS[1]
                    if action == (1, 0):
                        actions[child_row][child_col] = ACTIONS[2]
                    if action == (0, 1):
                        actions[child_row][child_col] = ACTIONS[3]
                # if need to update with a lower cost
                elif child in open_set and open_set.get(
                    (child_row, child_col)) > cost:
                    open_set.put(node, cost)
                    parent[child_row][child_col] = currentNode
                    action = (child_row - currentNode_row,
                              child_col - currentNode_col)
                    if action == (-1, 0):
                        actions[child_row][child_col] = ACTIONS[0]
                    if action == (0, -1):
                        actions[child_row][child_col] = ACTIONS[1]
                    if action == (1, 0):
                        actions[child_row][child_col] = ACTIONS[2]
                    if action == (0, 1):
                        actions[child_row][child_col] = ACTIONS[3]
Example #5
0
def uniform_cost_search(grid_size, start, goal, obstacles, costFn, logger):

    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = PriorityQueue(order="min", f=lambda v: v)
    closed_set = Queue()

    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set

    parents = [  # the immediate predecessor cell from which to reach a cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]
    actions = [  # the action that the parent took to reach the cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]

    movement = []

    # Variables initialization
    open_set.put(start, 0)
    child_rows = 0
    child_cols = 0
    g = 0  # Path cost

    # Define UCS
    while (open_set != []):

        # Take out (x,y)(parent) and path v(cost) from openset
        temp_parent = open_set.pop()
        parent, v = temp_parent

        # Determine whether the agent reach to goal
        if parent == goal:

            # Search path
            for j in range(n_cols * n_rows):
                parent_rows, parent_cols = parent

                # Stop and return
                if parent == start:
                    print(movement)
                    return movement, closed_set

                # record action and put it in to movement()
                act = actions[parent_rows][parent_cols]
                movement.insert(0, act)

                # Update parent
                parent = parents[parent_rows][parent_cols]

        # Add parent to closedset
        closed_set.add(parent)

        # Search each direction of the parent
        for i in range(4):

            # Moving direction
            action_rows = action[i][0]
            action_cols = action[i][1]

            # Calculate child position
            parent_rows, parent_cols = parent
            child_rows, child_cols = parent_rows + action_rows, parent_cols + action_cols
            child = child_rows, child_cols

            # Update g(path cost)
            g = v + costFn((parent_rows, parent_cols))

            # Restrict the node in the map
            if (child not in obstacles) and (child_rows < n_rows) and (
                    child_cols < n_cols) and (child_rows >= 0) and (child_cols
                                                                    >= 0):
                if (child not in open_set) and (child not in closed_set):

                    # Add into openset
                    open_set.put(child, g)

                    # Record parent and action for each step
                    parents[child_rows][child_cols] = parent
                    actions[child_rows][child_cols] = tuple(action[i])

                # Update path cost if agent already in open list
                elif (child in open_set) and (g < open_set.get(child)):

                    # Add into openset
                    open_set.put(child, g)

                    # Record parent and action for each step
                    parents[child_rows][child_cols] = parent
                    actions[child_rows][child_cols] = tuple(action[i])
Example #6
0
def depth_first_search(grid_size, start, goal, obstacles, costFn, logger):

    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = Stack()  # Use Stack for openset
    closed_set = Queue()

    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set

    parents = [  # the immediate predecessor cell from which to reach a cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]
    actions = [  # the action that the parent took to reach the cell
        [None for __ in range(n_cols)] for _ in range(n_rows)
    ]

    movement = []

    # Define DFS
    open_set.add(start)
    while (open_set != []):
        parent = open_set.pop()
        closed_set.add(parent)

        # Search each direction of the parent
        for i in range(4):

            # Moving direction
            action_rows = action[i][0]
            action_cols = action[i][1]

            # Calculate child position
            parent_rows, parent_cols = parent
            child_rows, child_cols = parent_rows + action_rows, parent_cols + action_cols
            child = child_rows, child_cols

            # Restrict the node in the map
            if (child not in obstacles) and (child_rows < n_rows) and (
                    child_cols < n_cols) and (child_rows >= 0) and (child_cols
                                                                    >= 0):
                if (child not in open_set) and (child not in closed_set):

                    # Record parent and action for each step
                    parents[child_rows][child_cols] = parent
                    actions[child_rows][child_cols] = tuple(action[i])

                    if child == goal:

                        # Find Path
                        for j in range(n_cols * n_rows):

                            # find action for each step
                            act = actions[child_rows][child_cols]

                            # Save action in movement[]
                            movement.insert(0, act)

                            # find parent for each step
                            parent = parents[child_rows][child_cols]
                            child_rows, child_cols = parent

                            # Stop and return results
                            if parent == start:
                                return movement, closed_set
                    else:
                        open_set.add(child)
Example #7
0
def astar_search(grid_size, start, goal, obstacles, costFn, logger):
    """
    A* search algorithm finds the optimal path from the start cell to the
    goal cell in the 2D grid world.

    After expanding a node, to retrieve the cost of a child node at location (x,y), 
    please call costFn((x,y)). In all of the grid maps, the cost is always 1.  

    See depth_first_search() for details.    
    """
    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    ##########################################
    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    open_set = PriorityQueue(order="min", f=lambda v: v)
    #closed_set = PriorityQueue(order="min", f=lambda v: abs(v))
    closed_set = Queue()
    ##########################################

    ##########################################
    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set
    ##########################################

    movement = []
    #the path below is the dictionary that maintains key value pairs of parent and child
    pathTrace = {}
    path = {}

    # ----------------------------------------
    # finish the code below to implement a Manhattan distance heuristic
    # ----------------------------------------
    def heuristic(row, col):
        #############################################################################
        #pass
        return abs(goal_row - row) + abs(goal_col - col)

#############################################################################

    def Backtrace():
        #############################################################################
        path = [goal]
        print('goal is', goal)
        while path[-1] != start:
            #if pathTrace[path[-1]] in closed_set and pathTrace[path[-1]] not in path:
            print('parent is', pathTrace[path[-1]])
            path.append(pathTrace[path[-1]])
        path.reverse()
        print(path)
        num = 0
        while num < len(path) - 1:
            row, col = path[num]
            parentRow, parentCol = path[num + 1]
            dRow = parentRow - row
            dCol = parentCol - col
            if (dRow == -1 and dCol == 0):
                movement.append((-1, 0))
            if (dRow == 0 and dCol == -1):
                movement.append((0, -1))
            if (dRow == 1 and dCol == 0):
                movement.append((1, 0))
            if (dRow == 0 and dCol == 1):
                movement.append((0, 1))
            num += 1
        return movement


#############################################################################

    open_set.put(start, 0)
    i = 0
    while open_set:
        children = []
        currentNode, v = open_set.pop()
        if currentNode == goal:
            movement = Backtrace()
            return movement, closed_set
        currentNode_row, currentNode_col = currentNode
        closed_set.add(currentNode)
        currentNodeHeuristic = heuristic(currentNode_row, currentNode_col)
        costG = v - currentNodeHeuristic

        children = [((currentNode_row - 1, currentNode_col), costG + costFn(
            (currentNode_row - 1, currentNode_col)) +
                     heuristic(currentNode_row - 1, currentNode_col)),
                    ((currentNode_row + 1, currentNode_col), costG + costFn(
                        (currentNode_row + 1, currentNode_col)) +
                     heuristic(currentNode_row + 1, currentNode_col)),
                    ((currentNode_row, currentNode_col - 1), costG + costFn(
                        (currentNode_row, currentNode_col - 1)) +
                     heuristic(currentNode_row, currentNode_col - 1)),
                    ((currentNode_row, currentNode_col + 1), costG + costFn(
                        (currentNode_row, currentNode_col + 1)) +
                     heuristic(currentNode_row, currentNode_col + 1))]

        for childNode in children:
            node, cost = childNode
            node_row, node_col = node
            if (
                    node_row, node_col
            ) not in obstacles and node_row >= 0 and node_col >= 0 and node_row < n_rows and node_col < n_cols:
                if node not in closed_set and node not in open_set:
                    open_set.put(node, cost)
                    pathTrace[node] = currentNode
                    print('Path Trace loop 1', pathTrace[node])
                elif childNode in open_set and open_set.get(
                    (node_row, node_col)) > cost:
                    open_set.put(node, cost)
                    pathTrace[node] = currentNode
                    print('Path Trace loop 2', pathTrace[node_row, node_col])
Example #8
0
def depth_first_search(grid_size, start, goal, obstacles, costFn, logger):
    """
    DFS algorithm finds the path from the start cell to the
    goal cell in the 2D grid world.
    
    Parameters
    ----------
    grid_size: tuple, (n_rows, n_cols)
        (number of rows of the grid, number of cols of the grid)
    start: tuple, (row, col)
        location of the start cell;
        row and col are counted from 0, i.e. the 1st row is 0
    goal: tuple, (row, col)
        location of the goal cell
    obstacles: tuple, ((row, col), (row, col), ...)
        locations of obstacles in the grid
        the cells where obstacles are located are not allowed to access 
    costFn: a function that returns the cost of landing to a cell (x,y)
         after taking an action. The default cost is 1, regardless of the
         action and the landing cell, i.e. every time the agent moves NSEW
         it costs one unit. 
    logger: a logger to visualize the search process.
         Do not do anything to it.

   

    Returns
    -------
    movement along the path from the start to goal cell: list of actions
        The first returned value is the movement list found by the search
        algorithm from the start cell to the end cell.
        The movement list should be a list object who is composed of actions
        that should made moving from the start to goal cell along the path
        found the algorithm.
        For example, if nodes in the path from the start to end cell are:
            (0, 0) (start) -> (0, 1) -> (1, 1) -> (1, 0) (goal)
        then, the returned movement list should be
            [(0,1), (1,0), (0, -1)]
        which means: move right, down, left.

        Return an EMPTY list if the search algorithm fails finding any
        available path.
        
    closed set: list of location tuple (row, col)
        The second returned value is the closed set, namely, the cells are expanded during search.
    """
    n_rows, n_cols = grid_size
    start_row, start_col = start
    goal_row, goal_col = goal

    ##########################################
    # Choose a proper container yourself from
    # OrderedSet, Stack, Queue, PriorityQueue
    # for the open set and closed set.
    # open_set = OrderedSet()
    # closed_set = OrderedSet()
    open_set = Stack()
    closed_set = Queue()
    ##########################################

    ##########################################
    # Set up visualization logger hook
    # Please do not modify these four lines
    closed_set.logger = logger
    logger.closed_set = closed_set
    open_set.logger = logger
    logger.open_set = open_set
    ##########################################

    movement = []
    pathTrace = {}

    def Backtrace():
        #############################################################################
        path = [goal]
        print('goal is', goal)
        while path[-1] != start:
            #if pathTrace[path[-1]] not in path:
            print('parent is', pathTrace[path[-1]])
            path.append(pathTrace[path[-1]])
        path.reverse()
        num = 0
        while num < len(path) - 1:
            row, col = path[num]
            parentRow, parentCol = path[num + 1]
            dRow = parentRow - row
            dCol = parentCol - col
            if (dRow == -1 and dCol == 0):
                movement.append((-1, 0))
            if (dRow == 0 and dCol == -1):
                movement.append((0, -1))
            if (dRow == 1 and dCol == 0):
                movement.append((1, 0))
            if (dRow == 0 and dCol == 1):
                movement.append((0, 1))
            num += 1
        return movement

    # ----------------------------------------
    # finish the code below
    # ----------------------------------------
#############################################################################
    open_set.add(start)
    i = 0
    while open_set:
        i = i + 1
        children = []
        currentNode = open_set.pop()
        closed_set.add(currentNode)
        currentNode_row, currentNode_col = currentNode

        children = [(currentNode_row - 1, currentNode_col),
                    (currentNode_row + 1, currentNode_col),
                    (currentNode_row, currentNode_col - 1),
                    (currentNode_row, currentNode_col + 1)]

        for childNode in children:
            node_row, node_col = childNode
            if childNode not in obstacles and node_row >= 0 and node_col >= 0 and node_row < n_rows and node_col < n_cols:
                if childNode not in closed_set and childNode not in open_set:
                    if childNode == goal:
                        pathTrace[childNode] = currentNode
                        movement = Backtrace()
                        return movement, closed_set
                    else:
                        open_set.add(childNode)
                        pathTrace[childNode] = currentNode


#############################################################################
    return movement, closed_set