def generate_random_expression_tree() -> Tuple[ExprTree, Dict[str, int]]: """ Generate a random expression tree and its lookup dictionary. """ # randomly pick how many variables to have var = {'a': randint(0, 2), 'b': randint(0, 2), 'c': randint(0, 2)} # ensure at least one variable if all([var[v] == 0 for v in var]): var['a'] = 1 # start with a set of leaves subtrees = [] for k in var: for _ in range(var[k]): subtrees.append(ExprTree(k, [])) for _ in range(randint(1, 5)): subtrees.append(ExprTree(randint(1, 9), [])) shuffle(subtrees) # iteratively form subtrees - starting form our initial set of leaves while len(subtrees) > 1: op = choice(OPERATORS) num_children = randint(2, min(3, len(subtrees))) nu_node = ExprTree(op, subtrees[-num_children:]) for _ in range(num_children): subtrees.pop() subtrees.insert(randint(0, len(subtrees)), nu_node) # there is one tree left in subtrees - this is the root we will return, # but first, we will setup its lookup lookup = {} subtrees[0].populate_lookup(lookup) # set_lookup recursively sets lookup return subtrees[0], lookup
def test_expression_tree_puzzle_fail_fast_false() -> None: """Test ExpressionTreePuzzle.fail_fast on a solvable puzzle.""" exp_t = ExprTree('+', [ExprTree('a', []), ExprTree('b', [])]) puz = ExpressionTreePuzzle(exp_t, 7) puz.variables['a'] = 2 assert puz.fail_fast() is False
def test_expression_tree_populate_lookup_doctest() -> None: """Test ExprTree.populate_lookup on the provided doctest""" expr_t = ExprTree('a', []) look_up = {} expr_t.populate_lookup(look_up) assert look_up['a'] == 0 assert len(look_up) == 1
def test_expression_tree_puzzle_is_solved_doctest() -> None: """Test ExpressionTreePuzzle.is_solved on the provided doctest""" exp_t = ExprTree('+', [ExprTree('a', []), ExprTree('b', [])]) puz = ExpressionTreePuzzle(exp_t, 7) assert puz.is_solved() is False puz.variables['a'] = 7 assert puz.is_solved() is False puz.variables['a'] = 5 puz.variables['b'] = 2 assert puz.is_solved() is True
def test_expression_tree_puzzle_extensions_doctest() -> None: """Test ExpressionTreePuzzle.extensions on the provided doctest""" exp_t = ExprTree('a', []) puz = ExpressionTreePuzzle(exp_t, 7) exts_of_puz = puz.extensions() assert len(exts_of_puz) == 9 exts_of_an_ext = exts_of_puz[0].extensions() assert len(exts_of_an_ext) == 0 exp_t = ExprTree('+', [ExprTree('a', []), ExprTree('b', [])]) puz = ExpressionTreePuzzle(exp_t, 8) exts_of_puz = puz.extensions() assert len(exts_of_puz) == 18
def main(): pop_size = 1000 max_runs = 50 mutate_ratio = 0.2 # Which data set to use. mode = 1 random.seed() pop = [] # Create a random population of trees. for i in range(pop_size): pop.append(ExprTree(mode)) print "Population created." for tree in pop: print tree for i in range(max_runs): print "Beginning crossover " + str(i) + ":" # Crossover and mutate population. genetic.mutate(pop, mutate_ratio, mode) pop = genetic.crossover(pop, mode) print "Crossover " + str(i) + " complete."
def __init__(self, tree: ExprTree, target: int) -> None: """ Create a new expression tree puzzle given the provided expression tree and the target value. The variables are initialized using the tree's populate_lookup method. >>> puz = ExpressionTreePuzzle(ExprTree('a', []), 4) >>> puz.variables == {'a': 0} True >>> puz.target 4 """ self.variables = {} tree.populate_lookup(self.variables) self._tree = tree self.target = target
def test_expression_tree_puzzle_str_doctest() -> None: """Test ExpressionTreePuzzle.__str__ on the provided doctest""" exp_t = ExprTree('+', [ExprTree('*', [ExprTree('a', []), ExprTree('+', [ExprTree('b', []), ExprTree(6, []), ExprTree(6, []), ])]), ExprTree(5, [])]) puz = ExpressionTreePuzzle(exp_t, 61) assert str(puz) == "{'a': 0, 'b': 0}\n((a * (b + 6 + 6)) + 5) = 61"
def combine(first, second): """ Combine 2 trees to create a child tree. Static method. Parameters: first - ExprTree - tree to combine second - ExprTree - tree to combine Returns: tuple - (ExprTree, ExprTree) - children of given trees """ first = ExprTree(0, first) second = ExprTree(0, second) parent1, left1 = first.random_parent() parent2, left2 = second.random_parent() if left1: temp = parent1.left if left2: parent1.left = parent2.left parent2.left = temp else: parent1.left = parent2.right parent2.right = temp else: temp = parent1.right if left2: parent1.right = parent2.left parent2.left = temp else: parent1.right = parent2.right parent2.right = temp return first, second
def test_expression_tree_eq_doctest() -> None: """Test ExprTree.__eq__ on the provided doctest""" t1 = ExprTree(5, []) assert t1.__eq__(ExprTree(5, [])) t2 = ExprTree('*', [ExprTree(5, []), ExprTree(2, [])]) assert t2.__eq__(ExprTree('*', [ExprTree(5, []), ExprTree(2, [])])) assert t2.__eq__(ExprTree('*', [])) is False
def test_expression_tree_str_doctest() -> None: """Test ExprTree.__str__ on the provided doctest""" exp_t = ExprTree('+', [ExprTree('a', []), ExprTree('b', []), ExprTree(3, [])]) assert str(exp_t) == '(a + b + 3)' exp_t = ExprTree(None, []) assert str(exp_t) == '()' exp_t = ExprTree(5, []) assert str(exp_t) == '5' exp_t = ExprTree('+', [ ExprTree('*', [ ExprTree(7, []), ExprTree('+', [ExprTree(6, []), ExprTree(6, [])]) ]), ExprTree(5, []) ]) assert str(exp_t) == '((7 * (6 + 6)) + 5)' exp_t = ExprTree('+', [ ExprTree(3, []), ExprTree('*', [ExprTree('x', []), ExprTree('y', [])]), ExprTree('x', []) ]) assert str(exp_t) == '(3 + (x * y) + x)'
def test_expression_tree_substitute_doctest() -> None: """Test ExprTree.substitute on the provided doctest""" # This test relies on ExprTree.__str__ working correctly. exp_t = ExprTree('a', []) exp_t.substitute({'a': 1}) assert str(exp_t) == '1' exp_t = ExprTree('*', [ ExprTree('a', []), ExprTree('*', [ExprTree('a', []), ExprTree(1, [])]) ]) exp_t.substitute({'a': 2, '*': '+'}) assert str(exp_t) == '(2 + (2 + 1))'
def test_expression_tree_eval_doctest() -> None: """Test ExprTree.eval on the provided doctest""" exp_t = ExprTree('+', [ ExprTree(3, []), ExprTree('*', [ExprTree('x', []), ExprTree('y', [])]), ExprTree('x', []) ]) look_up = {} exp_t.populate_lookup(look_up) assert exp_t.eval(look_up) == 3 look_up['x'] = 7 look_up['y'] = 3 assert exp_t.eval(look_up) == 31