def nodes_at_depth(problem, initial=None, depth=27, verbosity=1): """Breadth-first search to see how many unique states exist at a given distance/depth from `initial`""" if initial is None: initial = problem.goal visited = set() # set of hashable states already visited frontier = set() # set of hashable states at fringe being explored now node = Node(problem.initial) frontier.add(node) d = 0 while frontier and d < depth: if verbosity: print('='*40 + ' {0:03d}'.format(d) + ' ' + '='*40) d += 1 children = set() # set of nodes to explore next for node in frontier: hashable_state = force_hashable(node.state) visited.add(hashable_state) for child in node.expand(problem): hashable_child = force_hashable(child.state) if hashable_child not in visited: children.add(child) frontier = set(children) if verbosity > 1: print(','.join(''.join(str(i) for i in node.state) for node in frontier)) elif verbosity: print(len(children)) return frontier
def goal_test(self, state): """Return True if the state is a goal. The default method compares the state to self.goal, as specified in the constructor. Override this method if checking against a single self.goal is not enough.""" if self.verbosity: print('{0} =? {1}'.format(state, self.goal)) state = getattr(state, 'state', state) return force_hashable(state) == force_hashable(self.goal)
def astar_search(problem, heuristic=h_npuzzle_manhattan): """Modified version of Norvig's A* graph search algorithm Allows unhashable states by converting them to hashable types inside Node Search the nodes with the lowest heuristic scores first. You specify the function heuristic(node) that you want to minimize; for example, if heuristic is a heuristic estimate to the goal, then we have greedy best first search; if heuristic is node.depth then we have breadth-first search. There is a subtlety: the line "heuristic = memoize(heuristic, 'heuristic')" means that the heuristic values will be cached on the nodes as they are computed. So after doing a best first search you can examine the heuristic values of the path returned.""" max_depth = 0 heuristic = memoize(heuristic, 'heuristic') node = Node(problem.initial) if problem.goal_test(node): return node frontier = PriorityQueue(min, heuristic) frontier.append(node) explored = set() while frontier: node = frontier.pop() if node.depth > max_depth: max_depth = node.depth print(max_depth, len(frontier)) if problem.goal_test(node): return node, explored explored.add(force_hashable(node.state)) for child in node.expand(problem): hashable_child = force_hashable(child.state) if hashable_child not in explored and child not in frontier: frontier.append(child) elif hashable_child in frontier: hashable_incumbent = frontier[hashable_child] if heuristic(hashable_child) < heuristic(hashable_incumbent): del frontier[hashable_incumbent] frontier.append(hashable_child) return None, explored