def test_depth_first_graph_search(): """ depth-first graph and tree search are the same on this problem. """ for goal in range(1, 10): p = AnnotatedProblem(EasyProblem(0, goal)) sol = next(depth_first_search(p, graph=True)) assert sol.state_node.state == goal assert p.nodes_expanded == goal * 2 assert p.goal_tests == goal + 1 p = AnnotatedProblem(EasyProblem(0, goal)) sol = next( depth_first_search(p, graph=True, forward=False, backward=True)) assert sol.state_node == sol.goal_node assert p.nodes_expanded == goal * 2 assert p.goal_tests == goal + 1 p2 = AnnotatedProblem(EasyProblem2(0, goal)) try: next(depth_first_search(p2, graph=True)) assert False except StopIteration: assert p2.nodes_expanded == 2 assert p2.goal_tests == 1
def pattern_match(pattern, index, substitution=None, partial=False): """ Find substitutions that yield a match of the pattern against the provided index. If no match is found then it returns None. """ if substitution is None: substitution = {} sub = frozenset(substitution.items()) determined_vars = set(v for t in pattern for v in identify_determined_vars(t)) terms = {} for t in pattern: necessary = frozenset(identify_necessary_vars(t, determined_vars)) if necessary not in terms: terms[necessary] = [] terms[necessary].append(t) f_terms = set(t for t in pattern if is_functional_term(t)) terms = update_terms(terms, f_terms, substitution, index, partial) if terms is None: return if partial: problem = PartialMatchingProblem(sub, extra=(terms, f_terms, index)) else: problem = PatternMatchingProblem(sub, extra=(terms, f_terms, index)) for solution in depth_first_search(problem): yield dict(solution.state_node.state)
def test_depth_first_tree_search(): """ Test depth first tree search (i.e., with duplicates). """ for goal in range(1, 10): p = AnnotatedProblem(EasyProblem(0, goal)) sol = next(depth_first_search(p, graph=False)) assert sol.state_node.state == goal assert p.nodes_expanded == goal * 2 assert p.goal_tests == goal + 1 p = AnnotatedProblem(EasyProblem(0, goal)) sol = next( depth_first_search(p, graph=False, forward=False, backward=True)) assert sol.state_node == sol.goal_node assert p.nodes_expanded == goal * 2 assert p.goal_tests == goal + 1
def new_match(pos_terms, neg_terms, free_vars, index, substitution): substitution = frozenset(substitution.items()) pos_terms = update_pos_pattern(pos_terms, substitution, index) if pos_terms is None: return neg_terms = update_neg_pattern(neg_terms, substitution, index, free_vars) if neg_terms is None: return problem = PatternMatchingProblem(substitution, extra=(pos_terms, neg_terms, free_vars, index)) for solution in depth_first_search(problem): yield dict(solution.state_node.state)
def test_solution_node(): ep = EasyProblem(0, 8) sol1 = next(depth_first_search(ep)) assert sol1.depth() == 8 assert sol1.path() == tuple(['expand'] * 8) assert str(sol1) == ("StateNode={State: 8, Extra: None}, " "GoalNode={State: 8, Extra: None}") assert repr(sol1) == "SolutionNode(Node(8), GoalNode(8))" assert hash(sol1) == hash((8, 8)) sol2 = next(breadth_first_search(ep, forward=True, backward=True)) assert sol2.depth() == 8 print(sol2.path()) assert sol2.path() == tuple(['expand'] * 8) assert sol2.goal_node.path() == tuple(['expand'] * 4) assert str(sol2) == ("StateNode={State: 4, Extra: None}, " "GoalNode={State: 4, Extra: None}") assert repr(sol2) == "SolutionNode(Node(4), GoalNode(4))" assert hash(sol2) == hash((4, 4)) assert sol1 == sol1 assert sol1 != sol2
def depth(self, x): return depth_first_search(x, forward=True, backward=False)
@staticmethod def successors(node): logger.debug(f"getting successors for {node}") world = node.state nentities = len(world.entities) if nentities <= 3: logger.debug("Circles") # Circles for circle in world.all_circles(world.get_points()): if circle not in world.entities: yield Node(world.add_entity(circle)) elif nentities <= 5: logger.debug("Lines") # Lines for line in world.all_lines(world.get_points()): if line not in world.entities: try: yield Node(world.add_entity(line)) except RuntimeError: logger.warn(f"Couldn't add {line}") else: logger.debug("Nothing!") return if __name__ == '__main__': from py_search.uninformed import depth_first_search logging.basicConfig(level="DEBUG") print(next(depth_first_search(E10())))