Example #1
0
    def test_evaluate_where_possible_simple(self):
        two_plus_two = Operation(OperationType.PLUS(),
                                 [Variable(2.0), Variable(2.0)])
        expression = Operation(OperationType.DIVIDE(),
                               [Variable('x'), two_plus_two])

        verify(str(expression.evaluate_where_possible()), self.reporter)
Example #2
0
    def test_complex_operation(self):

        two = Operation(OperationType.POSITIVE(), [Variable(2)])
        negative_x = Operation(OperationType.NEGATIVE(), [Variable('x')])
        op = Operation(OperationType.TIMES(), [two, negative_x])

        verify(str(op), self.reporter)
Example #3
0
    def parse(self, parser):
        assert isinstance(parser, Parser)

        if self._operation_type in self.token_map.values():
            right = parser.parse(precedence=10) # All prefixes should be evaluated before infixes
            return Operation(self._operation_type, [right])
        else:
            return Operation(self._operation_type)
Example #4
0
    def test_evaluation_simple(self):

        two_plus_two = Operation(OperationType.PLUS(),
                                 [Variable(2.0), Variable(2.0)])
        two_plus_two_divided_by_four = Operation(
            OperationType.DIVIDE(), [two_plus_two, Variable(4)])

        self.assertTrue(two_plus_two_divided_by_four.is_evaluatable())
        self.assertAlmostEqual(two_plus_two_divided_by_four.evaluate(), 1)
Example #5
0
    def test_collected_terms_subtract(self):

        x = Term(Operation(Variable('x')))
        y = Term(Operation(Variable('y')), 2)
        z = Term(Operation(Variable('z')))

        expression1 = CollectedTerms([x, y], [1, 3])
        expression2 = CollectedTerms([y, z], [-3, -2])
        result = CollectedTerms.subtract(expression1, expression2)
        verify(str(result), self.reporter)
Example #6
0
    def test_equation(self):

        two = Operation(OperationType.POSITIVE(), [Variable(2)])
        negative_x = Operation(OperationType.NEGATIVE(), [Variable('x')])
        lhs = Operation(OperationType.TIMES(), [two, negative_x])

        rhs = Variable(3.1415)

        eq = Equation(lhs, rhs)

        verify(str(eq), self.reporter)
Example #7
0
 def apply_function(equation):
     if equation.lhs.operation_type.arity == 0:
         equation = equation.flip()
     if (equation.rhs.operation_type.arity
             == 0) and (equation.rhs.operation_type.symbol == '0'):
         homogenized = equation.lhs
     else:
         homogenized = Operation(OperationType.MINUS(),
                                 [equation.lhs, equation.rhs])
     collected = CollectedTerms.try_parse_expression(homogenized)
     if collected is None:
         return equation
     collected = collected.as_expression
     return Equation(collected, Operation(Variable(0)))
Example #8
0
    def parse(self, parser, left):
        assert isinstance(parser, Parser)
        assert isinstance(left, Operation)

        right = parser.parse(self.precedence)

        return Operation(self._operation_type, [left, right])
Example #9
0
    def apply(self, equation):
        assert isinstance(equation, Equation)
        assert self.is_applicable_to(equation)

        assert len(equation.lhs.arguments) == 2
        operand = equation.lhs.arguments[1]
        lhs = equation.lhs.arguments[0]
        rhs = Operation(self._inverse_type, [equation.rhs, operand])
        return Equation(lhs, rhs)
Example #10
0
 def test_collected_terms_instantiate(self):
     x = Term(Operation(Variable('x')))
     expression1 = CollectedTerms([x], [1])
     self.assertEqual(str(expression1), 'x')
     expression2 = CollectedTerms([x], [5])
     self.assertEqual(str(expression2), '5.0x')
     expression3 = CollectedTerms([x], [-1])
     self.assertEqual(str(expression3), '-x')
     expression4 = CollectedTerms([x], [-12])
     self.assertEqual(str(expression4), '-12.0x')
Example #11
0
    def test_evaluation_trivial(self):

        two = Operation(OperationType.POSITIVE(), [Variable('2')])

        self.assertTrue(two.is_evaluatable())
        self.assertAlmostEqual(two.evaluate(), 2)

        x = Operation(OperationType.POSITIVE(), [Variable('x')])
        self.assertFalse(x.is_evaluatable())
Example #12
0
    def _substitute(self, operation, pattern):

        if operation.operation_type.arity == 0:
            if operation.operation_type.symbol in pattern.keys():
                return pattern[operation.operation_type.symbol]
            else:
                return operation

        to_return_op_type = operation.operation_type
        to_return_arguments = list()
        for sub_op in operation.arguments:
            to_return_arguments.append(self._substitute(sub_op, pattern))

        return Operation(to_return_op_type, to_return_arguments)
Example #13
0
    def transform(self, expression, pattern=None):
        assert isinstance(expression, Operation)
        if pattern is None:
            assert isinstance(pattern, SubstitutionPattern)

        for k in pattern.keys():
            if type(pattern[k]) == str:
                pattern[k] = Operation(OperationType.VARIABLE(pattern[k]))

        substituted_start = self.try_transform(expression, pattern)

        substituted_end = self._substitute(self._end, pattern)

        return substituted_end
Example #14
0
    def test_evaluate_where_possible_complex(self):
        two_plus_two = Operation(OperationType.PLUS(),
                                 [Variable(2.0), Variable(2.0)])
        two_plus_two_divided_by_four = Operation(
            OperationType.DIVIDE(), [two_plus_two, Variable(4)])
        three_minus_x = Operation(OperationType.MINUS(),
                                  [Variable(3.0), Variable('x')])
        seven_plus_five = Operation(OperationType.PLUS(),
                                    [Variable(7), Variable(5)])
        three_minus_x_over_seven_plus_five = Operation(
            OperationType.DIVIDE(), [three_minus_x, seven_plus_five])
        expression = Operation(
            OperationType.TIMES(),
            [two_plus_two_divided_by_four, three_minus_x_over_seven_plus_five])

        verify(str(expression.evaluate_where_possible()), self.reporter)
Example #15
0
    def try_transform(self, expression, pattern=None):
        assert isinstance(expression, Operation)
        if pattern is None:
            pattern = SubstitutionPattern(dict())
        assert isinstance(pattern, SubstitutionPattern)

        substituted_start = self._substitute(self._start, pattern)
        if not Operation.areEqual(substituted_start, expression):
            raise TransformException(
                '{} substituted with {} == {} != {}'.format(
                    str(self._start), str(pattern), str(substituted_start),
                    str(expression)))
        else:
            return substituted_start
Example #16
0
    def flip_transformation(variable_to_force_left):
        if type(variable_to_force_left) == str:
            variable_to_force_left = Variable(variable_to_force_left)
        assert isinstance(variable_to_force_left, Variable)

        is_applicable_function = lambda x: True
        subexpression = Operation(variable_to_force_left)

        def apply_function(equation):
            if not (equation.rhs.contains(subexpression)
                    ):  # If it appears on both sides, default to flipping
                return equation
            else:
                return equation.flip()

        return Transformation(is_applicable_function, apply_function)
Example #17
0
    def substitutes(self, expression, pattern):
        assert isinstance(expression, Operation)
        assert isinstance(pattern, SubstitutionPattern)

        substituted_start = self._substitute(self._start, pattern)
        return Operation.areEqual(substituted_start, expression)
Example #18
0
    def single_variable(equation,
                        variable,
                        print_out=False,
                        max_iterations=1000):
        assert isinstance(equation, Equation)
        if type(variable) == str:
            variable = Variable(variable)
        assert isinstance(variable, Variable)
        assert type(print_out) == bool
        assert type(max_iterations) == int
        assert variable.symbol in equation.get_variables()

        expected_result = Operation(variable)
        condition = lambda x: (
            (Operation.areEqual(x.lhs, expected_result) and variable.symbol not in x.rhs.get_variables())\
            or x is None
        )

        distributions = [
            ExpressionSubstitution(Parser.parse_expression('a * (b + c)'),
                                   Parser.parse_expression('a * b + a * c')),
            ExpressionSubstitution(Parser.parse_expression('(a + b) * c'),
                                   Parser.parse_expression('a * c + b * c')),
            ExpressionSubstitution(Parser.parse_expression('(a + b) / c'),
                                   Parser.parse_expression('a / c + b / c')),
            ExpressionSubstitution(Parser.parse_expression('a * (b - c)'),
                                   Parser.parse_expression('a * b - a * c')),
            ExpressionSubstitution(Parser.parse_expression('(a - b) * c'),
                                   Parser.parse_expression('a * c - b * c')),
            ExpressionSubstitution(Parser.parse_expression('(a - b) / c'),
                                   Parser.parse_expression('a / c - b / c')),
        ]

        distributions = [
            Transformation.apply_all_substitution_transformations(x)
            for x in distributions
        ]
        distribute = SolverStep(
            Transformation.each_transformation(distributions, False))

        pre_solve = SolverStep(
            Transformation.collect_like_terms_transformation())

        equation = distribute.execute_step(equation)
        equation = pre_solve.execute_step(equation)

        branches = [equation]
        executed_branches = set()
        iterations = 0

        no_regrets_transformations = [
            Transformation.apply_all_substitution_transformations(x)\
            for x in Solver.no_regrets_substitutions
        ]

        solve_step = SolverStep(Transformation.evaluation_transformation(),
                                terminate_on_repeat=True)
        solve_step_2 = SolverStep(
            Transformation.each_transformation(no_regrets_transformations,
                                               False))
        solve_step_3 = SolverStep(Transformation.flip_transformation(variable))
        solve_step_4 = SolverStep.cancellations()

        solve_step.next_step = solve_step_2
        solve_step_2.next_step = solve_step_3
        solve_step_3.next_step = solve_step_4
        solve_step_4.next_step = solve_step

        while iterations < max_iterations:

            if len(branches) == 0:
                raise SolverException('Exhausted possible transformations.')

            branch = branches[0]
            branches = branches[1:]

            if print_out:
                print('Executing branch: {}'.format(str(branch)))
            result = solve_step.execute_until(branch,
                                              condition,
                                              print_out=print_out)
            if condition(result):
                final_execute_step = SolverStep(
                    Transformation.evaluation_transformation())
                return final_execute_step.execute_step(result)
            else:

                executed_branches.add(str(branch))
                executed_branches.add(
                    str(result))  # Executed already since steps terminated

                new_branches = dict()
                # We don't care about the outputs of flips or cancellations
                new_branch_strings = solve_step_3.previous_inputs - executed_branches
                for string in new_branch_strings:
                    new_branches[string] = Parser.parse_equation(string)
                solve_step.clear_history()
                solve_step_2.clear_history()
                solve_step_3.clear_history()
                solve_step_4.clear_history()

                for substitution in Solver.substitutions:
                    left_substitution_result = [
                        x[1]
                        for x in substitution.get_all_substitutions(branch.lhs)
                    ]
                    right_substitution_result = [
                        x[1]
                        for x in substitution.get_all_substitutions(branch.rhs)
                    ]

                    equations = [
                        Equation(x, branch.rhs)
                        for x in left_substitution_result
                    ]
                    equations += [
                        Equation(branch.lhs, x)
                        for x in right_substitution_result
                    ]

                    pairs = [(str(x), x) for x in equations
                             if str(x) not in executed_branches]

                    for k, v in pairs:
                        new_branches[k] = v

                if print_out:
                    print("New branches from {}:\n{}\n".format(
                        str(branch), '\n'.join(new_branches.keys())))
                branches += new_branches.values()
                branches.sort(key=lambda x: len(str(x)))
            iterations += 1

        raise SolverException(
            'Could not solve equation for a single variable.  Final result: {}'
            .format(str(equation)))
Example #19
0
    def test_single_variable_solver_trivial(self):

        equation = Equation(Operation(Variable('x')), Operation(Variable(2)))
        result = Solver.single_variable(equation, 'x')

        verify(str(result), self.reporter)
Example #20
0
    def test_simple_operation(self):

        simple_op = Operation(OperationType.PLUS(), [Variable(2), Variable(2)])
        verify(str(simple_op), self.reporter)