Beispiel #1
0
def greedy(matrix, start, goal):
    """
    Find the path from start to the goal using Greedy Best-first Search Algorithm
    The algorithm is implemented based on the description on Wikipedia:
    https://en.wikipedia.org/wiki/Best-first_search#Greedy_BFS
    Notice: GBFS is suboptimal algorithm, so the solution MAY NOT BE OPTIMAL!
    :param matrix: Search space, as a 2D list
    :param start: Start point, as a tuple
    :param goal: Goal point, as a tuple
    :return: The path (if found) from start to goal, or None
    """
    print('Analytics: start node ' + str(start) + ', goal node ' + str(goal))

    # The set of nodes already evaluated
    visited = set()
    partially_expanded = set()

    # The set of currently discovered nodes that are not evaluated yet.
    # Initially, only the start node is known.
    # frontier is implemented as a priority queue
    frontier = Frontier()
    frontier.add(start, manhattan_dist(start, goal))

    # For each node, which node it can most efficiently be reached from.
    # If a node can be reached from many nodes, came_from will eventually contain the
    # most efficient previous step.
    came_from = {}

    while frontier:
        current, current_distance = frontier.nearest
        if current == goal:
            print('Analytics: ' + str(len(partially_expanded)) +
                  ' expanded nodes out of ' + str(count_nodes(matrix)) +
                  ' nodes , among which ' + str(len(visited)) +
                  ' are fully expanded (all successors evaluated)')
            return reconstruct_path(came_from, current)

        partially_expanded.add(current)
        is_interrupted = False
        for neighbor in expand(current, matrix):
            if neighbor not in visited:
                neighbor_distance = manhattan_dist(neighbor, goal)
                if neighbor not in frontier:  # Discover a new node
                    came_from[neighbor] = current
                    frontier.add(neighbor, neighbor_distance)
                    if current_distance > neighbor_distance:
                        is_interrupted = True
                        break

        if not is_interrupted:
            frontier.pop_nearest()
            visited.add(current)

    return None
Beispiel #2
0
def a_star(matrix, start, goal, estimate=manhattan_dist):
    """
    Find the path from start to the goal using Greedy Best-first Search Algorithm
    The algorithm is implemented based on the description on Wikipedia:
    https://en.wikipedia.org/wiki/Best-first_search#Greedy_BFS
    Notice: GBFS is suboptimal algorithm, so the solution MAY NOT BE OPTIMAL!
    :param estimate: Heuristics used in a_star search
    :param matrix: Search space, as a 2D list
    :param start: Start point, as a tuple
    :param goal: Goal point, as a tuple
    :return: The path (if found) from start to goal, or None
    """
    print('Analytics: start node ' + str(start) + ', goal node ' + str(goal))

    # The set of nodes already evaluated
    visited = set()

    # For each node, the cost of getting from the start node to that node.
    # The cost of going from start to start is zero.
    g_score = {start: 0}

    # For each node, the total cost of getting from the start node to the goal
    # by passing by that node. That value is partly known, partly heuristic.
    # For the first node, that value is completely heuristic.
    f_score = {start: estimate(start, goal)}

    # The set of currently discovered nodes that are not evaluated yet.
    # Initially, only the start node is known.
    # frontier is implemented as a priority queue
    frontier = Frontier()
    frontier.add(start, f_score[start])

    # For each node, which node it can most efficiently be reached from.
    # If a node can be reached from many nodes, came_from will eventually contain the
    # most efficient previous step.
    came_from = {}

    while frontier:
        current, current_f_score = frontier.pop_nearest()
        if current == goal:
            print('Analytics: ' + str(len(visited)) +
                  ' expanded nodes, out of ' + str(count_nodes(matrix)) +
                  ' nodes')
            # draw_expanded_nodes(matrix, visited)
            return reconstruct_path(came_from, current)

        visited.add(current)
        for neighbor in expand(current, matrix):
            if neighbor not in visited:
                g_through_current = g_score[
                    current] + 1  # every neighbor has distance 1

                if (neighbor not in frontier
                        or g_through_current < g_score[neighbor]):
                    # Discover a new node or a better path
                    came_from[neighbor] = current
                    g_score[neighbor] = g_through_current
                    f_score[neighbor] = (g_score[neighbor] +
                                         estimate(neighbor, goal))
                    frontier.add(neighbor, f_score[neighbor])

    return None
Beispiel #3
0
def a_star_multidots(edges,
                     start: tuple,
                     goals: tuple,
                     estimate=mst_estimator):
    """
    Find the path from start to the goal using Greedy Best-first Search Algorithm
    The algorithm is implemented based on the description on Wikipedia:
    https://en.wikipedia.org/wiki/Best-first_search#Greedy_BFS
    Notice: GBFS is suboptimal algorithm, so the solution MAY NOT BE OPTIMAL!
    :param estimate: Heuristics used in a_star search
    :param edges: Search space, as a 2D list
    :param start: Start point, as a tuple
    :param goals: Goal points, as a set of all dots
    :return: The path (if found) from start to goal, or None
    """
    print('Analytics: start node ' + str(start) + ', dots node ' + str(goals))

    goals_to_indices = {g: i for i, g in enumerate(goals, 2)}

    start = init_state(start, goals)
    if start[0:2] in goals:
        start = mark_visited(start[0:2], goals_to_indices, start)

    # The set of nodes already evaluated
    visited = set()

    # For each node, the cost of getting from the start node to that node.
    # The cost of going from start to start is zero.
    g_score = {start: 0}

    # For each node, the total cost of getting from the start node to the dots
    # by passing by that node. That value is partly known, partly heuristic.
    # For the first node, that value is completely heuristic.
    # f_score = {start: naive_estimator(start, dots_visited[start], goals)}
    f_score = {start: estimate(start, goals, edges)}

    # The set of currently discovered nodes that are not evaluated yet.
    # Initially, only the start node is known.
    # frontier is implemented as a priority queue
    frontier = Frontier()
    frontier.add(start, f_score[start])

    # For each node, which node it can most efficiently be reached from.
    # If a node can be reached from many nodes, came_from will eventually contain the
    # most efficient previous step.
    came_from = {}

    while frontier:
        current, current_f_score = frontier.pop_nearest()
        if current[2:].count(1) == len(current) - 2:
            print('Analytics: ' + str(len(visited)) +
                  ' expanded nodes, out of ' +
                  str(len(edges) * (2**(len(current) - 2))) + ' nodes')
            return reconstruct_path(came_from, current)

        visited.add(current)
        for neighbor in expand_multidots(current, edges):
            if neighbor[0:2] in goals:
                neighbor = mark_visited(neighbor[0:2], goals_to_indices,
                                        neighbor)

            if neighbor not in visited:
                # Subtract 1 here because the edge_maps contains both start and end for
                # the shortest path between dots
                g_through_current = g_score[current] + len(
                    edges[current[0:2]][neighbor[0:2]]) - 1

                if (neighbor not in frontier
                        or g_through_current < g_score[neighbor]):
                    # Discover a new node or a better path

                    came_from[neighbor] = current
                    g_score[neighbor] = g_through_current

                    f_score[neighbor] = (g_score[neighbor] +
                                         estimate(neighbor, goals, edges))
                    frontier.add(neighbor, f_score[neighbor])

    return None