Example #1
0
def best_first_graph_search(problem, f):
    """
    Search the nodes with the lowest f scores first.
    You specify the function f(node) that you want to minimize; for example,
    if f is a heuristic estimate to the goal, then we have greedy best
    first search; if f is node.depth then we have breadth-first search.
    There is a subtlety: the line "f = memoize(f, 'f')" means that the f
    values will be cached on the nodes as they are computed. So after doing
    a best first search you can examine the f values of the path returned.
  """

    f = memoize(f, 'f')
    node = Node(problem.getStartState())
    if problem.isGoalState(node.state):
        return node

    frontier = PriorityQueue(min, f)
    frontier.push(node)
    explored = set()
    while frontier:
        node = frontier.pop()
        if problem.isGoalState(node.state):
            return node
        explored.add(node.state)
        for child in node.expand(problem):
            if child.state not in explored and not frontier.contains(child):
                frontier.push(child)
            elif frontier.contains(child):
                incumbent = frontier.__getitem__(child)
                if f(child) < f(incumbent):
                    del frontier[incumbent]
                    frontier.push(child)
    return None