def test_map_anyo_misc(): q_lv = var("q") res = run(0, q_lv, map_anyo(eq, [1, 2, 3], [1, 2, 3])) # TODO: Remove duplicate results assert len(res) == 7 res = run(0, q_lv, map_anyo(eq, [1, 2, 3], [1, 3, 3])) assert len(res) == 0 def one_to_threeo(x, y): return conde([eq(x, 1), eq(y, 3)]) res = run(0, q_lv, map_anyo(one_to_threeo, [1, 2, 4, 1, 4, 1, 1], q_lv)) assert res[0] == [3, 2, 4, 3, 4, 3, 3] assert (len( run(4, q_lv, map_anyo(math_reduceo, [etuple(mul, 2, var("x"))], q_lv))) == 0) test_res = run(4, q_lv, map_anyo(math_reduceo, [etuple(add, 2, 2), 1], q_lv)) assert test_res == ([etuple(mul, 2, 2), 1], ) test_res = run(4, q_lv, map_anyo(math_reduceo, [1, etuple(add, 2, 2)], q_lv)) assert test_res == ([1, etuple(mul, 2, 2)], ) test_res = run(4, q_lv, map_anyo(math_reduceo, q_lv, var("z"))) assert all(isinstance(r, list) for r in test_res) test_res = run(4, q_lv, map_anyo(math_reduceo, q_lv, var("z"), tuple)) assert all(isinstance(r, tuple) for r in test_res) x, y, z = var(), var(), var() def test_bin(a, b): return conde([eq(a, 1), eq(b, 2)]) res = run(10, (x, y), map_anyo(test_bin, x, y, null_type=tuple)) exp_res_form = ( ((1, ), (2, )), ((x, 1), (x, 2)), ((1, 1), (2, 2)), ((x, y, 1), (x, y, 2)), ((1, x), (2, x)), ((x, 1, 1), (x, 2, 2)), ((1, 1, 1), (2, 2, 2)), ((x, y, z, 1), (x, y, z, 2)), ((1, x, 1), (2, x, 2)), ((x, 1, y), (x, 2, y)), ) for a, b in zip(res, exp_res_form): s = unify(a, b) assert s is not False assert all(isvar(i) for i in reify((x, y, z), s))
def test_pprint(): pretty_mod = pytest.importorskip("IPython.lib.pretty") et = etuple(1, etuple("a", *range(20)), etuple(3, "b"), blah=etuple("c", 0)) assert ( pretty_mod.pretty(et) == "e(\n 1,\n e('a', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19),\n e(3, 'b'),\n blah=e(c, 0))" # noqa: E501 )
def test_str(): et = etuple(1, etuple("a", 2), etuple(3, "b")) assert ( repr(et) == "ExpressionTuple((1, ExpressionTuple(('a', 2)), ExpressionTuple((3, 'b'))))" ) assert str(et) == "e(1, e(a, 2), e(3, b))" kw = KwdPair("a", 1) assert repr(kw) == "KwdPair('a', 1)" assert str(kw) == "a=1"
def test_etuple(): """Test basic `etuple` functionality.""" def test_op(*args): return tuple(object() for i in range(sum(args))) e1 = etuple(test_op, 1, 2) assert e1._evaled_obj is ExpressionTuple.null with pytest.raises(ValueError): e1.evaled_obj = 1 e1_obj = e1.evaled_obj assert len(e1_obj) == 3 assert all(type(o) == object for o in e1_obj) # Make sure we don't re-create the cached `evaled_obj` e1_obj_2 = e1.evaled_obj assert e1_obj == e1_obj_2 # Confirm that evaluation is recursive e2 = etuple(add, (object(), ), e1) # Make sure we didn't convert this single tuple value to # an `etuple` assert type(e2[1]) == tuple # Slices should be `etuple`s, though. assert isinstance(e2[:1], ExpressionTuple) assert e2[1] == e2[1:2][0] e2_obj = e2.evaled_obj assert type(e2_obj) == tuple assert len(e2_obj) == 4 assert all(type(o) == object for o in e2_obj) # Make sure that it used `e1`'s original `evaled_obj` assert e2_obj[1:] == e1_obj # Confirm that any combination of `tuple`s/`etuple`s in # concatenation result in an `etuple` e_radd = (1, ) + etuple(2, 3) assert isinstance(e_radd, ExpressionTuple) assert e_radd == (1, 2, 3) e_ladd = etuple(1, 2) + (3, ) assert isinstance(e_ladd, ExpressionTuple) assert e_ladd == (1, 2, 3)
def gen_long_add_chain(N=None, num=1): b_struct = num if N is None: N = sys.getrecursionlimit() for i in range(0, N): b_struct = etuple(add, num, b_struct) return b_struct
def single_math_reduceo(expanded_term, reduced_term): """Construct a goal for some simple math reductions.""" x_lv = var() return lall( isinstanceo(x_lv, Real), isinstanceo(x_lv, ExpressionTuple), conde( [ eq(expanded_term, etuple(add, x_lv, x_lv)), eq(reduced_term, etuple(mul, 2, x_lv)), ], [ eq(expanded_term, etuple(log, etuple(exp, x_lv))), eq(reduced_term, x_lv) ], ), )
def test_etuplize(): e0 = etuple(add, 1) e1 = etuplize(e0) assert e0 is e1 assert etuple(1, 2) == etuplize((1, 2)) with raises(TypeError): etuplize("ab") assert "ab" == etuplize("ab", return_bad_args=True) op_1, op_2 = Operator("*"), Operator("+") node_1 = Node(op_2, [1, 2]) node_2 = Node(op_1, [node_1, 3, ()]) assert etuplize(node_2) == etuple(op_1, etuple(op_2, 1, 2), 3, ()) assert type(etuplize(node_2)[-1]) == tuple assert etuplize(node_2, shallow=True) == etuple(op_1, node_1, 3, ())
def test_etuplize(): e0 = etuple(add, 1) e1 = etuplize(e0) assert e0 is e1 assert etuple(1, 2) == etuplize((1, 2)) with raises(TypeError): etuplize("ab") assert "ab" == etuplize("ab", return_bad_args=True) op_1, op_2 = Operator("*"), Operator("+") node_1 = Node(op_2, [1, 2]) node_2 = Node(op_1, [node_1, 3, ()]) assert etuplize(node_2) == etuple(op_1, etuple(op_2, 1, 2), 3, ()) assert type(etuplize(node_2)[-1]) == tuple assert etuplize(node_2, shallow=True) == etuple(op_1, node_1, 3, ()) def rands_transform(x): if x == 1: return 4 return x assert etuplize(node_2, rands_transform_fn=rands_transform) == etuple( op_1, etuple(op_2, 4, 2), 3, ()) def rator_transform(x): if x == op_1: return op_2 return x assert etuplize(node_2, rator_transform_fn=rator_transform) == etuple( op_2, etuple(op_2, 1, 2), 3, ())
def test_etuple_apply(): """Test `etuplize` and `etuple` interactions with `apply`.""" assert apply(add, (1, 2)) == 3 assert apply(1, (2, )) == (1, 2) # Make sure that we don't lose underlying `evaled_obj`s # when taking apart and re-creating expression tuples # using `kanren`'s `operator`, `arguments` and `term` # functions. e1 = etuple(add, (object(), ), (object(), )) e1_obj = e1.evaled_obj e1_dup = (rator(e1), ) + rands(e1) assert isinstance(e1_dup, ExpressionTuple) assert e1_dup.evaled_obj == e1_obj e1_dup_2 = apply(rator(e1), rands(e1)) assert e1_dup_2 == e1_obj
def test_unification(): from cons import cons uni = importorskip("unification") var, unify, reify = uni.var, uni.unify, uni.reify a_lv, b_lv = var(), var() assert unify(etuple(add, 1, 2), etuple(add, 1, 2), {}) == {} assert unify(etuple(add, 1, 2), etuple(a_lv, 1, 2), {}) == {a_lv: add} assert reify(etuple(a_lv, 1, 2), {a_lv: add}) == etuple(add, 1, 2) res = unify(etuple(add, 1, 2), cons(a_lv, b_lv), {}) assert res == {a_lv: add, b_lv: etuple(1, 2)} res = reify(cons(a_lv, b_lv), res) assert isinstance(res, ExpressionTuple) assert res == etuple(add, 1, 2) et = etuple(a_lv, ) res = reify(et, {a_lv: 1}) assert isinstance(res, ExpressionTuple) et = etuple(a_lv, ) # We choose to allow unification with regular tuples. if etuple(1) == (1, ): res = unify(et, (1, )) assert res == {a_lv: 1} et = etuple(add, 1, 2) assert et.evaled_obj == 3 res = unify(et, cons(a_lv, b_lv)) assert res == {a_lv: add, b_lv: et[1:]} # Make sure we've preserved the original object after deconstruction via # `unify` assert res[b_lv]._parent is et assert ((res[a_lv], ) + res[b_lv])._evaled_obj == 3 # Make sure we've preserved the original object after reconstruction via # `reify` rf_res = reify(cons(a_lv, b_lv), res) assert rf_res is et et_lv = etuple(add, a_lv, 2) assert reify(et_lv[1:], {})._parent is et_lv # Reify a logic variable to another logic variable assert reify(et_lv[1:], {a_lv: b_lv})._parent is et_lv # TODO: We could propagate the parent etuple when a sub-etuple is `cons`ed # with logic variables. # et_1 = et[2:] # et_2 = cons(b_lv, et_1) # assert et_2._parent is et # assert reify(et_2, {a_lv: 1})._parent is et e1 = KwdPair("name", "blah") e2 = KwdPair("name", a_lv) assert unify(e1, e2, {}) == {a_lv: "blah"} assert reify(e2, {a_lv: "blah"}) == e1 e1 = etuple(add, 1, name="blah") e2 = etuple(add, 1, name=a_lv) assert unify(e1, e2, {}) == {a_lv: "blah"} assert reify(e2, {a_lv: "blah"}) == e1
def test_walko_reverse(): """Test `walko` in "reverse" (i.e. specify the reduced form and generate the un-reduced form).""" q_lv = var("q") test_res = run(2, q_lv, term_walko(math_reduceo, q_lv, 5)) assert test_res == ( etuple(log, etuple(exp, 5)), etuple(log, etuple(exp, etuple(log, etuple(exp, 5)))), ) assert all(e.eval_obj == 5.0 for e in test_res) # Make sure we get some variety in the results test_res = run(2, q_lv, term_walko(math_reduceo, q_lv, etuple(mul, 2, 5))) assert test_res == ( # Expansion of the term's root etuple(add, 5, 5), # Expansion in the term's arguments etuple(mul, etuple(log, etuple(exp, 2)), etuple(log, etuple(exp, 5))), # Two step expansion at the root # etuple(log, etuple(exp, etuple(add, 5, 5))), # Expansion into a sub-term # etuple(mul, 2, etuple(log, etuple(exp, 5))) ) assert all(e.eval_obj == 10.0 for e in test_res) r_lv = var("r") test_res = run(4, [q_lv, r_lv], term_walko(math_reduceo, q_lv, r_lv)) expect_res = ( [etuple(add, 1, 1), etuple(mul, 2, 1)], [etuple(log, etuple(exp, etuple(add, 1, 1))), etuple(mul, 2, 1)], [etuple(), etuple()], [ etuple(add, etuple(mul, 2, 1), etuple(add, 1, 1)), etuple(mul, 2, etuple(mul, 2, 1)), ], ) assert list( unify(a1, a2) and unify(b1, b2) for [a1, b1], [a2, b2] in zip(test_res, expect_res))
def test_walko_misc(): q_lv = var(prefix="q") expr = etuple(add, etuple(mul, 2, 1), etuple(add, 1, 1)) res = run(0, q_lv, walko(eq, expr, expr)) # TODO: Remove duplicates assert len(res) == 162 expr2 = etuple(add, etuple(mul, 2, 1), etuple(add, 2, 1)) res = run(0, q_lv, walko(eq, expr, expr2)) assert len(res) == 0 def one_to_threeo(x, y): return conde([eq(x, 1), eq(y, 3)]) res = run( 1, q_lv, walko( one_to_threeo, [1, [1, 2, 4], 2, [[4, 1, 1]], 1], q_lv, ), ) assert res == ([3, [3, 2, 4], 2, [[4, 3, 3]], 3], ) assert run(2, q_lv, walko(eq, q_lv, q_lv, null_type=ExpressionTuple)) == ( q_lv, etuple(), ) res = run( 1, q_lv, walko( one_to_threeo, etuple( add, 1, etuple(mul, etuple(add, 1, 2), 1), etuple(add, etuple(add, 1, 2), 2), ), q_lv, # Only descend into `add` terms rator_goal=lambda x, y: lall(eq(x, add), eq(y, add)), ), ) assert res == (etuple(add, 3, etuple(mul, etuple(add, 1, 2), 1), etuple(add, etuple(add, 3, 2), 2)), )
def test_map_anyo_reverse(): """Test `map_anyo` in "reverse" (i.e. specify the reduced form and generate the un-reduced form).""" # Unbounded reverse q_lv = var() rev_input = [etuple(mul, 2, 1)] test_res = run(4, q_lv, map_anyo(math_reduceo, q_lv, rev_input)) assert test_res == ( [etuple(add, 1, 1)], [etuple(log, etuple(exp, etuple(add, 1, 1)))], # [etuple(log, etuple(exp, etuple(mul, 2, 1)))], [ etuple(log, etuple(exp, etuple(log, etuple(exp, etuple(add, 1, 1))))) ], # [etuple(log, etuple(exp, etuple(log, etuple(exp, etuple(mul, 2, 1)))))], [ etuple( log, etuple( exp, etuple( log, etuple(exp, etuple(log, etuple(exp, etuple(add, 1, 1))))), ), ) ], ) # Guided reverse test_res = run( 4, q_lv, map_anyo(math_reduceo, [etuple(add, q_lv, 1)], [etuple(mul, 2, 1)]), ) assert test_res == (1, )
def test_eq_assoc(): assoc_op = "assoc_op" associative.index.clear() associative.facts.clear() fact(associative, assoc_op) assert run(0, True, eq_assoc(1, 1)) == (True, ) assert run(0, True, eq_assoc((assoc_op, 1, 2, 3), (assoc_op, 1, 2, 3))) == (True, ) assert not run(0, True, eq_assoc((assoc_op, 3, 2, 1), (assoc_op, 1, 2, 3))) assert run(0, True, eq_assoc((assoc_op, (assoc_op, 1, 2), 3), (assoc_op, 1, 2, 3))) == (True, ) assert run(0, True, eq_assoc((assoc_op, 1, 2, 3), (assoc_op, (assoc_op, 1, 2), 3))) == (True, ) o = "op" assert not run(0, True, eq_assoc((o, 1, 2, 3), (o, (o, 1, 2), 3))) x = var() res = run(0, x, eq_assoc((assoc_op, 1, 2, 3), x, n=2)) assert res == ( (assoc_op, (assoc_op, 1, 2), 3), (assoc_op, 1, 2, 3), (assoc_op, 1, (assoc_op, 2, 3)), ) res = run(0, x, eq_assoc(x, (assoc_op, 1, 2, 3), n=2)) assert res == ( (assoc_op, (assoc_op, 1, 2), 3), (assoc_op, 1, 2, 3), (assoc_op, 1, (assoc_op, 2, 3)), ) y, z = var(), var() # Check results when both arguments are variables res = run(3, (x, y), eq_assoc(x, y)) exp_res_form = ( (etuple(assoc_op, x, y, z), etuple(assoc_op, etuple(assoc_op, x, y), z)), (x, y), ( etuple(etuple(assoc_op, x, y, z)), etuple(etuple(assoc_op, etuple(assoc_op, x, y), z)), ), ) for a, b in zip(res, exp_res_form): s = unify(a, b) assert s is not False, (a, b) assert all(isvar(i) for i in reify((x, y, z), s)) # Make sure it works with `cons` res = run(0, (x, y), eq_assoc(cons(x, y), (assoc_op, 1, 2, 3))) assert res == ( (assoc_op, ((assoc_op, 1, 2), 3)), (assoc_op, (1, 2, 3)), (assoc_op, (1, (assoc_op, 2, 3))), ) res = run(1, (x, y), eq_assoc(cons(x, y), (x, z, 2, 3))) assert res == ((assoc_op, ((assoc_op, z, 2), 3)), ) # Don't use a predicate that can never succeed, e.g. # associative_2 = Relation("associative_2") # run(1, (x, y), eq_assoc(cons(x, y), (x, z), op_predicate=associative_2)) # Nested expressions should work now expr1 = (assoc_op, 1, 2, (assoc_op, x, 5, 6)) expr2 = (assoc_op, (assoc_op, 1, 2), 3, 4, 5, 6) assert run(0, x, eq_assoc(expr1, expr2, n=2)) == ((assoc_op, 3, 4), )
((x, 1, y), (x, 2, y)), ) for a, b in zip(res, exp_res_form): s = unify(a, b) assert s is not False assert all(isvar(i) for i in reify((x, y, z), s)) @pytest.mark.parametrize( "test_input, test_output", [ ([], ()), ([1], ()), ([ etuple(add, 1, 1), ], ([etuple(mul, 2, 1)], )), ([1, etuple(add, 1, 1)], ([1, etuple(mul, 2, 1)], )), ([etuple(add, 1, 1), 1], ([etuple(mul, 2, 1), 1], )), ( [etuple(mul, 2, 1), etuple(add, 1, 1), 1], ([etuple(mul, 2, 1), etuple(mul, 2, 1), 1], ), ), ( [ etuple(add, 1, 1), etuple(log, etuple(exp, 5)), ], ( [etuple(mul, 2, 1), 5], [etuple(add, 1, 1), 5],
def test_etuple_kwargs(): """Test keyword arguments and default argument values.""" e = etuple(a=1, b=2) assert e._tuple == (KwdPair("a", 1), KwdPair("b", 2)) assert KwdPair("a", 1) in e._tuple assert hash(KwdPair("a", 1)) == hash(KwdPair("a", 1)) def test_func(a, b, c=None, d="d-arg", **kwargs): assert isinstance(c, (type(None), int)) return [a, b, c, d] e1 = etuple(test_func, 1, 2) assert e1.evaled_obj == [1, 2, None, "d-arg"] # Make sure we handle variadic args properly def test_func2(*args, c=None, d="d-arg", **kwargs): assert isinstance(c, (type(None), int)) return list(args) + [c, d] e0 = etuple(test_func2, c=3) assert e0.evaled_obj == [3, "d-arg"] e11 = etuple(test_func2, 1, 2) assert e11.evaled_obj == [1, 2, None, "d-arg"] e2 = etuple(test_func, 1, 2, 3) assert e2.evaled_obj == [1, 2, 3, "d-arg"] e3 = etuple(test_func, 1, 2, 3, 4) assert e3.evaled_obj == [1, 2, 3, 4] e4 = etuple(test_func, 1, 2, c=3) assert e4.evaled_obj == [1, 2, 3, "d-arg"] e5 = etuple(test_func, 1, 2, d=3) assert e5.evaled_obj == [1, 2, None, 3] e6 = etuple(test_func, 1, 2, 3, d=4) assert e6.evaled_obj == [1, 2, 3, 4] # Try evaluating nested etuples e7 = etuple(test_func, etuple(add, 1, 0), 2, c=etuple(add, 1, etuple(add, 1, 1))) assert e7.evaled_obj == [1, 2, 3, "d-arg"] # Try a function without an obtainable signature object e8 = etuple( enumerate, etuple(list, ["a", "b", "c", "d"]), start=etuple(add, 1, etuple(add, 1, 1)), ) assert list(e8.evaled_obj) == [(3, "a"), (4, "b"), (5, "c"), (6, "d")] # Use "evaled_obj" kwarg and make sure it doesn't end up in the `_tuple` object e9 = etuple(add, 1, 2, evaled_obj=3) assert e9._tuple == (add, 1, 2) assert e9._evaled_obj == 3
def test_basics(): x_lv = var() res = unify(etuple(log, etuple(exp, etuple(log, 1))), etuple(log, etuple(exp, x_lv))) assert res[x_lv] == etuple(log, 1)
def test_eq_comm(): x, y, z = var(), var(), var() commutative.facts.clear() commutative.index.clear() comm_op = "comm_op" fact(commutative, comm_op) assert run(0, True, eq_comm(1, 1)) == (True, ) assert run(0, True, eq_comm((comm_op, 1, 2, 3), (comm_op, 1, 2, 3))) == (True, ) assert run(0, True, eq_comm((comm_op, 3, 2, 1), (comm_op, 1, 2, 3))) == (True, ) assert run(0, y, eq_comm((comm_op, 3, y, 1), (comm_op, 1, 2, 3))) == (2, ) assert run(0, (x, y), eq_comm((comm_op, x, y, 1), (comm_op, 1, 2, 3))) == ( (2, 3), (3, 2), ) assert run(0, (x, y), eq_comm((comm_op, 2, 3, 1), (comm_op, 1, x, y))) == ( (2, 3), (3, 2), ) assert not run(0, True, eq_comm(("op", 3, 2, 1), ("op", 1, 2, 3))) # not commutative assert not run(0, True, eq_comm((3, comm_op, 2, 1), (comm_op, 1, 2, 3))) assert not run(0, True, eq_comm((comm_op, 1, 2, 1), (comm_op, 1, 2, 3))) assert not run(0, True, eq_comm(("op", 1, 2, 3), (comm_op, 1, 2, 3))) # Test for variable args res = run(4, (x, y), eq_comm(x, y)) exp_res_form = ( (etuple(comm_op, x, y), etuple(comm_op, y, x)), (x, y), (etuple(etuple(comm_op, x, y)), etuple(etuple(comm_op, y, x))), (etuple(comm_op, x, y, z), etuple(comm_op, x, z, y)), ) for a, b in zip(res, exp_res_form): s = unify(a, b) assert s is not False assert all(isvar(i) for i in reify((x, y, z), s)) # Make sure it can unify single elements assert (3, ) == run(0, x, eq_comm((comm_op, 1, 2, 3), (comm_op, 2, x, 1))) # `eq_comm` should propagate through assert (3, ) == run( 0, x, eq_comm(("div", 1, (comm_op, 1, 2, 3)), ("div", 1, (comm_op, 2, x, 1)))) # Now it should not assert () == run( 0, x, eq_comm(("div", 1, ("div", 1, 2, 3)), ("div", 1, ("div", 2, x, 1)))) expected_res = {(1, 2, 3), (2, 1, 3), (3, 1, 2), (1, 3, 2), (2, 3, 1), (3, 2, 1)} assert expected_res == set( run(0, (x, y, z), eq_comm((comm_op, 1, 2, 3), (comm_op, x, y, z)))) assert expected_res == set( run(0, (x, y, z), eq_comm((comm_op, x, y, z), (comm_op, 1, 2, 3)))) assert expected_res == set( run( 0, (x, y, z), eq_comm(("div", 1, (comm_op, 1, 2, 3)), ("div", 1, (comm_op, x, y, z))), )) e1 = (comm_op, (comm_op, 1, x), y) e2 = (comm_op, 2, (comm_op, 3, 1)) assert run(0, (x, y), eq_comm(e1, e2)) == ((3, 2), ) e1 = ((comm_op, 3, 1), ) e2 = ((comm_op, 1, x), ) assert run(0, x, eq_comm(e1, e2)) == (3, ) e1 = (2, (comm_op, 3, 1)) e2 = (y, (comm_op, 1, x)) assert run(0, (x, y), eq_comm(e1, e2)) == ((3, 2), ) e1 = (comm_op, (comm_op, 1, x), y) e2 = (comm_op, 2, (comm_op, 3, 1)) assert run(0, (x, y), eq_comm(e1, e2)) == ((3, 2), )
def test_eq_assoccomm(): x, y = var(), var() ac = "commassoc_op" commutative.index.clear() commutative.facts.clear() fact(commutative, ac) fact(associative, ac) assert run(0, True, eq_assoccomm(1, 1)) == (True, ) assert run(0, True, eq_assoccomm((1, ), (1, ))) == (True, ) assert run(0, True, eq_assoccomm(x, (1, ))) == (True, ) assert run(0, True, eq_assoccomm((1, ), x)) == (True, ) # Assoc only assert run(0, True, eq_assoccomm((ac, 1, (ac, 2, 3)), (ac, (ac, 1, 2), 3))) == (True, ) # Commute only assert run(0, True, eq_assoccomm((ac, 1, (ac, 2, 3)), (ac, (ac, 3, 2), 1))) == (True, ) # Both assert run(0, True, eq_assoccomm((ac, 1, (ac, 3, 2)), (ac, (ac, 1, 2), 3))) == (True, ) exp_res = set(( (ac, 1, 3, 2), (ac, 1, 2, 3), (ac, 2, 1, 3), (ac, 2, 3, 1), (ac, 3, 1, 2), (ac, 3, 2, 1), (ac, 1, (ac, 2, 3)), (ac, 1, (ac, 3, 2)), (ac, 2, (ac, 1, 3)), (ac, 2, (ac, 3, 1)), (ac, 3, (ac, 1, 2)), (ac, 3, (ac, 2, 1)), (ac, (ac, 2, 3), 1), (ac, (ac, 3, 2), 1), (ac, (ac, 1, 3), 2), (ac, (ac, 3, 1), 2), (ac, (ac, 1, 2), 3), (ac, (ac, 2, 1), 3), )) assert set(run(0, x, eq_assoccomm((ac, 1, (ac, 2, 3)), x))) == exp_res assert set(run(0, x, eq_assoccomm((ac, 1, 3, 2), x))) == exp_res assert set(run(0, x, eq_assoccomm((ac, 2, (ac, 3, 1)), x))) == exp_res # LHS variations assert set(run(0, x, eq_assoccomm(x, (ac, 1, (ac, 2, 3))))) == exp_res assert run(0, (x, y), eq_assoccomm((ac, (ac, 1, x), y), (ac, 2, (ac, 3, 1)))) == ( (2, 3), (3, 2), ) assert run(0, True, eq_assoccomm((ac, (ac, 1, 2), 3), (ac, 1, 2, 3))) == (True, ) assert run(0, True, eq_assoccomm((ac, 3, (ac, 1, 2)), (ac, 1, 2, 3))) == (True, ) assert run(0, True, eq_assoccomm((ac, 1, 1), ("other_op", 1, 1))) == () assert run(0, x, eq_assoccomm((ac, 3, (ac, 1, 2)), (ac, 1, x, 3))) == (2, ) # Both arguments unground op_lv = var() z = var() res = run(4, (x, y), eq_assoccomm(x, y)) exp_res_form = ( (etuple(op_lv, x, y), etuple(op_lv, y, x)), (y, y), ( etuple(etuple(op_lv, x, y)), etuple(etuple(op_lv, y, x)), ), ( etuple(op_lv, x, y, z), etuple(op_lv, etuple(op_lv, x, y), z), ), ) for a, b in zip(res, exp_res_form): s = unify(a, b) assert (op_lv not in s or (s[op_lv], ) in associative.facts or (s[op_lv], ) in commutative.facts) assert s is not False, (a, b) assert all(isvar(i) for i in reify((x, y, z), s))
def test_reduceo(): q_lv = var() # Reduce/forward res = run(0, q_lv, math_reduceo(etuple(log, etuple(exp, etuple(log, 1))), q_lv)) assert len(res) == 1 assert res[0] == etuple(log, 1) res = run( 0, q_lv, math_reduceo(etuple(log, etuple(exp, etuple(log, etuple(exp, 1)))), q_lv), ) assert res[0] == 1 assert res[1] == etuple(log, etuple(exp, 1)) # Expand/backward res = run(3, q_lv, math_reduceo(q_lv, 1)) assert res[0] == etuple(log, etuple(exp, 1)) assert res[1] == etuple(log, etuple(exp, etuple(log, etuple(exp, 1))))
def test_etuple_generator(): e_gen = etuple(lambda v: (i for i in v), range(3)) e_gen_res = e_gen.evaled_obj assert isinstance(e_gen_res, GeneratorType) assert tuple(e_gen_res) == tuple(range(3))