def cancellations(): cancels = [ EquationCancellation(OperationType.PLUS(), OperationType.MINUS()), EquationCancellation(OperationType.MINUS(), OperationType.PLUS()), EquationCancellation(OperationType.TIMES(), OperationType.DIVIDE()), EquationCancellation(OperationType.DIVIDE(), OperationType.TIMES()) ] transformations = [x.as_transformation() for x in cancels] return SolverStep(transformations)
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)
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)
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)
def test_equation_cancellation(self): lhs = Parser(Tokenizer.tokenize('x * 4')).parse() rhs = Parser(Tokenizer.tokenize('y')).parse() equation = Equation(lhs, rhs) multiplication_cancellation = EquationCancellation( OperationType.TIMES(), OperationType.DIVIDE()) self.assertTrue(multiplication_cancellation.is_applicable_to(equation)) result = multiplication_cancellation.apply(equation) verify(str(result), self.reporter)
def test_complex_single_solution_solve(self): lhs = Parser(Tokenizer.tokenize('x * 4 - 18')).parse() rhs = Parser(Tokenizer.tokenize('2')).parse() equation = Equation(lhs, rhs) cancellations = [ EquationCancellation(OperationType.PLUS(), OperationType.MINUS()), EquationCancellation(OperationType.MINUS(), OperationType.PLUS()), EquationCancellation(OperationType.TIMES(), OperationType.DIVIDE()), EquationCancellation(OperationType.DIVIDE(), OperationType.TIMES()) ] transformations = list( map(lambda x: x.as_transformation(), cancellations)) step = SolverStep(transformations) step.next_step = step condition = lambda x: str(x.lhs) == 'x' result = step.execute_until(equation, condition) verify(str(result), self.reporter)
class InfixParselet: token_map = { TokenType.PLUS: OperationType.PLUS(), TokenType.MINUS: OperationType.MINUS(), TokenType.TIMES: OperationType.TIMES(), TokenType.DIVIDES: OperationType.DIVIDE(), TokenType.EXPONENTIATES: OperationType.EXPONENTIATE() } # Enforce order of operations # If precedence <= max_priority, parser will parse only the next substatement # If priority > max_priority, parser will parse everything to the right precedence_map = { TokenType.EXPONENTIATES: 3, TokenType.TIMES: 2, TokenType.DIVIDES: 2, TokenType.PLUS: 1, TokenType.MINUS: 1 } def __init__(self, token): assert isinstance(token, Token) assert token.token_type in self.token_map.keys() self._operation_type = self.token_map[token.token_type] self.precedence = self.precedence_map[token.token_type] 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]) @staticmethod def get_next_precedence(parser): assert isinstance(parser, Parser) token = parser.peek() if token.token_type in InfixParselet.precedence_map.keys(): return InfixParselet.precedence_map[token.token_type] else: return 0