예제 #1
0
def test_different_constraints_on_commutative_operation():
    c1 = CustomConstraint(lambda x: len(str(x)) > 1)
    c2 = CustomConstraint(lambda x: len(str(x)) == 1)
    pattern1 = Pattern(f_c(x_), c1)
    pattern2 = Pattern(f_c(x_), c2)
    pattern3 = Pattern(f_c(x_, b), c1)
    pattern4 = Pattern(f_c(x_, b), c2)
    matcher = ManyToOneMatcher(pattern1, pattern2, pattern3, pattern4)

    subject = f_c(a)
    results = list(matcher.match(subject))
    assert len(results) == 1
    assert results[0][0] == pattern2
    assert results[0][1] == {'x': a}

    subject = f_c(Symbol('longer'), b)
    results = sorted(matcher.match(subject))
    assert len(results) == 1
    assert results[0][0] == pattern3
    assert results[0][1] == {'x': Symbol('longer')}

    subject = f_c(a, b)
    results = list(matcher.match(subject))
    assert len(results) == 1
    assert results[0][0] == pattern4
    assert results[0][1] == {'x': a}
예제 #2
0
def test_dataclass_operation_subclass():
    x1_ = Wildcard.dot("x1")
    x2_ = Wildcard.dot("x2")

    matches = match(MySum(Symbol("foo"), Symbol("bar")), Pattern(MySum(x1_, x2_)))
    subst, = list(matches)

    assert subst["x1"].name == "foo"
    assert subst["x2"].name == "bar"
예제 #3
0
def add_default_expressions(doctest_namespace):
    doctest_namespace['f'] = Operation.new('f', Arity.variadic)
    doctest_namespace['a'] = Symbol('a')
    doctest_namespace['b'] = Symbol('b')
    doctest_namespace['c'] = Symbol('c')
    doctest_namespace['x_'] = make_dot_variable('x')
    doctest_namespace['y_'] = make_dot_variable('y')
    doctest_namespace['_'] = Wildcard.dot()
    doctest_namespace['__'] = Wildcard.plus()
    doctest_namespace['___'] = Wildcard.star()
    doctest_namespace['__name__'] = '__main__'

    for name in matchpy.__all__:
        doctest_namespace[name] = getattr(matchpy, name)
예제 #4
0
def test_logic_simplify(replacer):
    LAnd = Operation.new('and', Arity.variadic, 'LAnd', associative=True, one_identity=True, commutative=True)
    LOr = Operation.new('or', Arity.variadic, 'LOr', associative=True, one_identity=True, commutative=True)
    LXor = Operation.new('xor', Arity.variadic, 'LXor', associative=True, one_identity=True, commutative=True)
    LNot = Operation.new('not', Arity.unary, 'LNot')
    LImplies = Operation.new('implies', Arity.binary, 'LImplies')
    Iff = Operation.new('iff', Arity.binary, 'Iff')

    ___ = Wildcard.star()

    a1 = Symbol('a1')
    a2 = Symbol('a2')
    a3 = Symbol('a3')
    a4 = Symbol('a4')
    a5 = Symbol('a5')
    a6 = Symbol('a6')
    a7 = Symbol('a7')
    a8 = Symbol('a8')
    a9 = Symbol('a9')
    a10 = Symbol('a10')
    a11 = Symbol('a11')

    LBot = Symbol(u'⊥')
    LTop = Symbol(u'⊤')

    expression = LImplies(
        LAnd(
            Iff(
                Iff(LOr(a1, a2), LOr(LNot(a3), Iff(LXor(a4, a5), LNot(LNot(LNot(a6)))))),
                LNot(
                    LAnd(
                        LAnd(a7, a8),
                        LNot(
                            LXor(
                                LXor(LOr(a9, LAnd(a10, a11)), a2),
                                LAnd(LAnd(a11, LXor(a2, Iff(a5, a5))), LXor(LXor(a7, a7), Iff(a9, a4)))
                            )
                        )
                    )
                )
            ),
            LImplies(
                Iff(
                    Iff(LOr(a1, a2), LOr(LNot(a3), Iff(LXor(a4, a5), LNot(LNot(LNot(a6)))))),
                    LNot(
                        LAnd(
                            LAnd(a7, a8),
                            LNot(
                                LXor(
                                    LXor(LOr(a9, LAnd(a10, a11)), a2),
                                    LAnd(LAnd(a11, LXor(a2, Iff(a5, a5))), LXor(LXor(a7, a7), Iff(a9, a4)))
                                )
                            )
                        )
                    )
                ),
                LNot(
                    LAnd(
                        LImplies(
                            LAnd(a1, a2),
                            LNot(
                                LXor(
                                    LOr(
                                        LOr(
                                            LXor(LImplies(LAnd(a3, a4), LImplies(a5, a6)), LOr(a7, a8)),
                                            LXor(Iff(a9, a10), a11)
                                        ), LXor(LXor(a2, a2), a7)
                                    ), Iff(LOr(a4, a9), LXor(LNot(a6), a6))
                                )
                            )
                        ), LNot(Iff(LNot(a11), LNot(a9)))
                    )
                )
            )
        ),
        LNot(
            LAnd(
                LImplies(
                    LAnd(a1, a2),
                    LNot(
                        LXor(
                            LOr(
                                LOr(
                                    LXor(LImplies(LAnd(a3, a4), LImplies(a5, a6)), LOr(a7, a8)),
                                    LXor(Iff(a9, a10), a11)
                                ), LXor(LXor(a2, a2), a7)
                            ), Iff(LOr(a4, a9), LXor(LNot(a6), a6))
                        )
                    )
                ), LNot(Iff(LNot(a11), LNot(a9)))
            )
        )
    )

    rules = [
        # xor(x,⊥) → x
        ReplacementRule(
            Pattern(LXor(x__, LBot)),
            lambda x: LXor(*x)
        ),
        # xor(x, x) → ⊥
        ReplacementRule(
            Pattern(LXor(x_, x_, ___)),
            lambda x: LBot
        ),
        # and(x,⊤) → x
        ReplacementRule(
            Pattern(LAnd(x__, LTop)),
            lambda x: LAnd(*x)
        ),
        # and(x,⊥) → ⊥
        ReplacementRule(
            Pattern(LAnd(__, LBot)),
            lambda: LBot
        ),
        # and(x, x) → x
        ReplacementRule(
            Pattern(LAnd(x_, x_, y___)),
            lambda x, y: LAnd(x, *y)
        ),
        # and(x, xor(y, z)) → xor(and(x, y), and(x, z))
        ReplacementRule(
            Pattern(LAnd(x_, LXor(y_, z_))),
            lambda x, y, z: LXor(LAnd(x, y), LAnd(x, z))
        ),
        # implies(x, y) → not(xor(x, and(x, y)))
        ReplacementRule(
            Pattern(LImplies(x_, y_)),
            lambda x, y: LNot(LXor(x, LAnd(x, y)))
        ),
        # not(x) → xor(x,⊤)
        ReplacementRule(
            Pattern(LNot(x_)),
            lambda x: LXor(x, LTop)
        ),
        # or(x, y) → xor(and(x, y), xor(x, y))
        ReplacementRule(
            Pattern(LOr(x_, y_)),
            lambda x, y: LXor(LAnd(x, y), LXor(x, y))
        ),
        # iff(x, y) → not(xor(x, y))
        ReplacementRule(
            Pattern(Iff(x_, y_)),
            lambda x, y: LNot(LXor(x, y))
        ),
    ]  # yapf: disable

    result = replacer(expression, rules)

    assert result == LBot
예제 #5
0
class TestExpression:
    @pytest.mark.parametrize(
        '   expression,                                                         simplified',
        [
            (f_i(a),                                                            a),
            (f_i(a, b),                                                         f_i(a, b)),
            (f_i(_),                                                            _),
            (f_i(___),                                                          f_i(___)),
            (f_i(__),                                                           f_i(__)),
            (f_i(x_),                                                           x_),
            (f_i(x___),                                                         f_i(x___)),
            (f_i(x__),                                                          f_i(x__)),
            (f_a(f_a(a)),                                                       f_a(a)),
            (f_a(f_a(a, b)),                                                    f_a(a, b)),
            (f_a(a, f_a(b)),                                                    f_a(a, b)),
            (f_a(f_a(a), b),                                                    f_a(a, b)),
            (f_a(f(a)),                                                         f_a(f(a))),
            (f_c(a, b),                                                         f_c(a, b)),
            (f_c(b, a),                                                         f_c(a, b)),
        ]
    )  # yapf: disable
    def test_operation_simplify(self, expression, simplified):
        assert expression == simplified

    @pytest.mark.parametrize(
        '   operation,                                              operands,       expected_error',
        [
            (Operation.new('f', Arity.unary),                       [],             ValueError),
            (Operation.new('f', Arity.unary),                       [a, b],         ValueError),
            (Operation.new('f', Arity.variadic),                    [],             None),
            (Operation.new('f', Arity.variadic),                    [a],            None),
            (Operation.new('f', Arity.variadic),                    [a, b],         None),
            (Operation.new('f', Arity.binary, associative=True),    [a, a, b],      ValueError),
            (Operation.new('f', Arity.binary),                      [x_, x___],     None),
            (Operation.new('f', Arity.binary),                      [x_, x__],      None),
            (Operation.new('f', Arity.binary),                      [x_, x_, x__],  ValueError),
            (Operation.new('f', Arity.binary),                      [x_, x_, x___], None),
            (Operation.new('f', Arity.binary),                      [x_, x_],       None),
            (Operation.new('f', Arity.binary),                      [x_, x_, x_],   ValueError),
        ]
    )  # yapf: disable
    def test_operation_errors(self, operation, operands, expected_error):
        if expected_error is not None:
            with pytest.raises(expected_error):
                operation(*operands)
        else:
            _ = operation(*operands)

    @pytest.mark.parametrize(
        '   expression,     is_constant',
        [
            (a,             True),
            (x_,            False),
            (_,             False),
            (f(a),          True),
            (f(a, b),       True),
            (f(x_),         False),
        ]
    )  # yapf: disable
    def test_is_constant(self, expression, is_constant):
        assert expression.is_constant == is_constant

    @pytest.mark.parametrize(
        '   expression,     is_syntactic',
        [
            (a,             True),
            (x_,            True),
            (_,             True),
            (x___,          False),
            (___,           False),
            (x__,           False),
            (__,            False),
            (f(a),          True),
            (f(a, b),       True),
            (f(x_),         True),
            (f(x__),        False),
            (f_a(a),        False),
            (f_a(a, b),     False),
            (f_a(x_),       False),
            (f_a(x__),      False),
            (f_c(a),        False),
            (f_c(a, b),     False),
            (f_c(x_),       False),
            (f_c(x__),      False),
            (f_ac(a),       False),
            (f_ac(a, b),    False),
            (f_ac(x_),      False),
            (f_ac(x__),     False),
        ]
    )  # yapf: disable
    def test_is_syntactic(self, expression, is_syntactic):
        assert expression.is_syntactic == is_syntactic

    @pytest.mark.parametrize(
        '   expression,         symbols',
        [
            (a,                 ['a']),
            (x_,                []),
            (_,                 []),
            (f(a),              ['a', 'f']),
            (f(a, b),           ['a', 'b', 'f']),
            (f(x_),             ['f']),
            (f(a, a),           ['a', 'a', 'f']),
            (f(f(a), f(b, c)),  ['a', 'b', 'c', 'f', 'f', 'f']),
        ]
    )  # yapf: disable
    def test_symbols(self, expression, symbols):
        assert expression.symbols == Multiset(symbols)

    @pytest.mark.parametrize(
        '   expression,                 variables',
        [
            (a,                         []),
            (x_,                        ['x']),
            (_,                         []),
            (f(a),                      []),
            (f(x_),                     ['x']),
            (f(x_, x_),                 ['x', 'x']),
            (f(x_, a),                  ['x']),
            (f(x_, a, y_),              ['x', 'y']),
            (f(f(x_), f(b, x_)),        ['x', 'x']),
            (f(a, variable_name='x'),        ['x']),
            (f(f(y_), variable_name='x'),    ['x', 'y']),
        ]
    )  # yapf: disable
    def test_variables(self, expression, variables):
        assert expression.variables == Multiset(variables)

    @pytest.mark.parametrize(
        '   expression,     predicate,                  preorder_list',
        [                                               # expression        position
            (f(a, x_),      None,                       [(f(a, x_),         ()),
                                                         (a,                (0, )),
                                                         (x_,               (1, ))]),
            (f(a, f(x_)),   lambda e: e.head is None,   [(x_,               (1, 0))]),
            (f(a, f(x_)),   lambda e: e.head == f,      [(f(a, f(x_)),      ()),
                                                         (f(x_),            (1, ))])
        ]
    )  # yapf: disable
    def test_preorder_iter(self, expression, predicate, preorder_list):
        result = list(expression.preorder_iter(predicate))
        assert result == preorder_list

    GETITEM_TEST_EXPRESSION = f(a, f(x_, b), _)

    @pytest.mark.parametrize(
        '   position,       expected_result',
        [
            ((),            GETITEM_TEST_EXPRESSION),
            ((0, ),         a),
            ((0, 0),        IndexError),
            ((1, ),         f(x_, b)),
            ((1, 0),        x_),
            ((1, 0, 0),     IndexError),
            ((1, 1),        b),
            ((1, 1, 0),     IndexError),
            ((1, 2),        IndexError),
            ((2, ),         _),
            ((3, ),         IndexError),
        ]
    )  # yapf: disable
    def test_getitem(self, position, expected_result):
        if inspect.isclass(expected_result) and issubclass(expected_result, Exception):
            with pytest.raises(expected_result):
                result = self.GETITEM_TEST_EXPRESSION[position]
                print(result)
        else:
            result = self.GETITEM_TEST_EXPRESSION[position]
            assert result == expected_result

    @pytest.mark.parametrize(
        '   start,          end,    expected_result',
        [
            ((),            (),     [GETITEM_TEST_EXPRESSION]),
            ((0, ),         (0, ),  [a]),
            ((0, ),         (1, ),  [a, f(x_, b)]),
            ((0, ),         (2, ),  [a, f(x_, b), _]),
            ((0, ),         (3, ),  [a, f(x_, b), _]),
            ((1, ),         (2, ),  [f(x_, b), _]),
            ((1, 0),        (1, 1), [x_, b]),
            ((1, 0),        (2, ),  IndexError),
            ((1, ),         (0, ),  IndexError),
            ((1, 0),        (2, 0), IndexError),
        ]
    )  # yapf: disable
    def test_getitem_slice(self, start, end, expected_result):
        if inspect.isclass(expected_result) and issubclass(expected_result, Exception):
            with pytest.raises(expected_result):
                result = self.GETITEM_TEST_EXPRESSION[start:end]
                print(result)
        else:
            result = self.GETITEM_TEST_EXPRESSION[start:end]
            assert result == expected_result

    def test_getitem_slice_symbol(self):
        with pytest.raises(IndexError):
            print(a[(0, ):()])
        with pytest.raises(IndexError):
            print(a[(0, ):(1, )])
        assert a[():()] == [a]

    @pytest.mark.parametrize(
        '   expression1,                    expression2',
        [
            (a,                             b),
            (a,                             Symbol('a', variable_name='x')),
            (Symbol('a', variable_name='x'),     Symbol('a', variable_name='y')),
            (a,                             _),
            (a,                             _s),
            (a,                             x_),
            (_,                             x_),
            (_s,                            x_),
            (x_,                            y_),
            (x_,                            x__),
            (f(a),                          f(b)),
            (f(a),                          f2(a)),
            (f(a),                          f(a, a)),
            (f(b),                          f(a, a)),
            (f(a, a),                       f(a, b)),
            (f(a, a),                       f(a, a, a)),
            (a,                             f(a)),
            (x_,                            f(a)),
            (_,                             f(a)),
            (_s,                            f(a)),
            (_s,                            s_),
            (SymbolWildcard(variable_name='x'),  SymbolWildcard(variable_name='y')),
            (s_,                            ss_),
            (_s,                            __),
            (_,                             _s),
            (SymbolWildcard(SpecialSymbol), SymbolWildcard(Symbol)),
            (f(a),                          SpecialF(a)),
        ]
    )  # yapf: disable
    def test_lt(self, expression1, expression2):
        assert expression1 < expression2, "{!s} < {!s} did not hold".format(expression1, expression2)
        assert not (expression2 < expression1
                   ), "Inconsistent order: Both {0} < {1} and {1} < {0}".format(expression2, expression1)

    @pytest.mark.parametrize('expression', [a, f(a), x_, _])
    def test_lt_error(self, expression):
        with pytest.raises(TypeError):
            expression < object()

    def test_operation_new_error(self):
        with pytest.raises(ValueError):
            _ = Operation.new('if', Arity.variadic)

        with pytest.raises(ValueError):
            _ = Operation.new('+', Arity.variadic)

    def test_wildcard_error(self):
        with pytest.raises(ValueError):
            _ = Wildcard(-1, False)

        with pytest.raises(ValueError):
            _ = Wildcard(0, True)

    def test_symbol_wildcard_error(self):
        with pytest.raises(TypeError):
            _ = SymbolWildcard(object)

    @pytest.mark.parametrize(
        '   expression,                         renaming,       expected_result',
        [
            (a,                                 {},             a),
            (a,                                 {'x': 'y'},     a),
            (x_,                                {},             x_),
            (x_,                                {'x': 'y'},     y_),
            (SymbolWildcard(),                  {},             SymbolWildcard()),
            (SymbolWildcard(),                  {'x': 'y'},     SymbolWildcard()),
            (f(x_),                             {},             f(x_)),
            (f(x_),                             {'x': 'y'},     f(y_)),
        ]
    )  # yapf: disable
    def test_with_renamed_vars(self, expression, renaming, expected_result):
        new_expr = expression.with_renamed_vars(renaming)
        assert new_expr == expected_result

    @pytest.mark.parametrize('expression', SIMPLE_EXPRESSIONS)
    @pytest.mark.parametrize('other', SIMPLE_EXPRESSIONS)
    def test_hash(self, expression, other):
        expression = expression
        other = other
        if expression != other:
            assert hash(expression) != hash(other), "hash({!s}) == hash({!s})".format(expression, other)
        else:
            assert hash(expression) == hash(other), "hash({!s}) != hash({!s})".format(expression, other)

    @pytest.mark.parametrize('expression', SIMPLE_EXPRESSIONS)
    def test_copy(self, expression):
        other = expression.__copy__()
        assert other == expression
        assert other is not expression

    @pytest.mark.parametrize(
        '   expression,     subexpression,  contains',
        [
            (a,             a,              True),
            (a,             b,              False),
            (f(a),          a,              True),
            (f(a),          b,              False),
            (f(a),          f(a),           True),
            (f(a, b),       f(a),           False),
            (f(a),          f(a, b),        False),
            (f(x_, y_),     x_,             True),
            (f(x_, y_),     y_,             True),
            (f(x_, y_),     a,              False),
        ]
    )  # yapf: disable
    def test_contains(self, expression, subexpression, contains):
        if contains:
            assert subexpression in expression, "{!s} should be contained in {!s}".format(subexpression, expression)
        else:
            assert subexpression not in expression, "{!s} should not be contained in {!s}".format(subexpression, expression)
예제 #6
0
f = Operation.new('f', Arity.variadic)
f2 = Operation.new('f2', Arity.variadic)
f_u = Operation.new('f_u', Arity.unary)
f_i = Operation.new('f_i', Arity.variadic, one_identity=True)
f_c = Operation.new('f_c', Arity.variadic, commutative=True)
f_ci = Operation.new('f_ci',
                     Arity.variadic,
                     commutative=True,
                     one_identity=True)
f2_c = Operation.new('f2_c', Arity.variadic, commutative=True)
f_a = Operation.new('f_a', Arity.variadic, associative=True)
f_ac = Operation.new('f_ac',
                     Arity.variadic,
                     associative=True,
                     commutative=True)
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
d = Symbol('d')
a_x = Symbol('a', variable_name='x')
s = SpecialSymbol('s')
_ = Wildcard.dot()
_s = Wildcard.symbol()
_ss = Wildcard.symbol(SpecialSymbol)
x_ = make_dot_variable('x')
s_ = make_symbol_variable('s')
ss_ = make_symbol_variable('ss', SpecialSymbol)
y_ = make_dot_variable('y')
z_ = make_dot_variable('z')
__ = Wildcard.plus()
x__ = make_plus_variable('x')
예제 #7
0
f = Operation.new('f', Arity.variadic)
f2 = Operation.new('f2', Arity.variadic)
f_u = Operation.new('f_u', Arity.unary)
f_i = Operation.new('f_i', Arity.variadic, one_identity=True)
f_c = Operation.new('f_c', Arity.variadic, commutative=True)
f_ci = Operation.new('f_ci',
                     Arity.variadic,
                     commutative=True,
                     one_identity=True)
f2_c = Operation.new('f2_c', Arity.variadic, commutative=True)
f_a = Operation.new('f_a', Arity.variadic, associative=True)
f_ac = Operation.new('f_ac',
                     Arity.variadic,
                     associative=True,
                     commutative=True)
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
d = Symbol('d')
s = SpecialSymbol('s')
_ = Wildcard.dot()
_s = Wildcard.symbol()
_ss = Wildcard.symbol(SpecialSymbol)
x_ = make_dot_variable('x')
s_ = make_symbol_variable('s')
ss_ = make_symbol_variable('ss', SpecialSymbol)
y_ = make_dot_variable('y')
z_ = make_dot_variable('z')
__ = Wildcard.plus()
x__ = make_plus_variable('x')
y__ = make_plus_variable('y')