def test_reify_recursion_limit(): import platform a_lv = var() b, _ = gen_long_chain(a_lv, 10) res = reify(b, {a_lv: "a"}) assert res == gen_long_chain("a", 10)[0] r_limit = sys.getrecursionlimit() try: sys.setrecursionlimit(100) b, _ = gen_long_chain(a_lv, 200) res = reify(b, {a_lv: "a"}) exp_res, _ = gen_long_chain("a", 200) if platform.python_implementation().lower() != "pypy": # CPython has stack limit issues when comparing nested lists, but # PyPy doesn't. with pytest.raises(RecursionError): assert res == exp_res sys.setrecursionlimit(300) assert res == exp_res finally: sys.setrecursionlimit(r_limit)
def test_reify_Mapping(): x, y = var(), var() s = {x: 2, y: 4} e = [(1, x), (3, {5: y})] expected_res = [(1, 2), (3, {5: 4})] assert reify(dict(e), s) == dict(expected_res) assert reify(OrderedDict(e), s) == OrderedDict(expected_res)
def test_reify_complex(): x, y = var(), var() s = {x: 2, y: 4} e = {1: [x], 3: (y, 5)} assert reify(e, s) == {1: [2], 3: (4, 5)} assert reify((1, {2: x}), {x: slice(0, y), y: 3}) == (1, {2: slice(0, 3)})
def test_reify(): x, y, z = var(), var(), var() s = {x: 1, y: 2, z: (x, y)} assert reify(x, s) == 1 assert reify(10, s) == 10 assert reify((1, y), s) == (1, 2) assert reify((1, (x, (y, 2))), s) == (1, (1, (2, 2))) assert reify(z, s) == (1, 2)
def test_reify(): x, y, z = var(), var(), var() s = {x: 1, y: 2, z: (x, y)} assert reify(x, s) == 1 assert reify(10, s) == 10 assert reify((1, y), s) == (1, 2) assert reify((1, (x, (y, 2))), s) == (1, (1, (2, 2))) assert reify(z, s) == (1, 2)
def _reify_ExpressionTuple(t, s): """When `kanren` reifies `etuple`s, we don't want them to turn into regular `tuple`s. We also don't want to lose the expression tracking/caching information. """ res = tuple(reify(iter(t), s)) t_chg = tuple(a == b for a, b in zip(t, res) if not isvar(a) and not isvar(b)) if all(t_chg): if len(t_chg) == len(t): # Nothing changed/updated; return the original `etuple`. return t if hasattr(t, "_orig_expr"): # Everything is equal and/or there are some non-logic variables in # the result. Keep tracking the original expression information, # in case the original expression is reproduced. res = etuple(*res) res._orig_expr = t._orig_expr return res res = etuple(*res) return res
def applyo_goal(S): nonlocal o_rator, o_rands, obj o_rator_rf, o_rands_rf, obj_rf = reify((o_rator, o_rands, obj), S) if not isvar(obj_rf): # We should be able to use this goal with *any* arguments, so # fail when the ground operations fail/err. try: obj_rator, obj_rands = operator(obj_rf), arguments(obj_rf) except (ConsError, NotImplementedError): return # The object's rator + rands should be the same as the goal's yield from lall(eq(o_rator_rf, obj_rator), eq(o_rands_rf, obj_rands))(S) elif isvar(o_rands_rf) or isvar(o_rator_rf): # The object and at least one of the rand, rators is a logic # variable, so let's just assert a `cons` relationship between # them yield from conso(o_rator_rf, o_rands_rf, obj_rf)(S) else: # The object is a logic variable, but the rator and rands aren't. # We assert that the object is the application of the rand and # rators. try: obj_applied = term(o_rator_rf, o_rands_rf) except (ConsError, NotImplementedError): return yield from eq(obj_rf, obj_applied)(S)
def _reify_MetaSymbol(o, s): if isinstance(o.obj, Var): # We allow reification of the base object field for # a meta object. # TODO: This is a weird thing that we should probably reconsider. # It's part of the functionality that allows base objects to fill-in # as logic variables, though. obj = s.get(o.obj, o.obj) else: # Otherwise, if there's a base object, it should indicate that there # are no logic variables or meta terms. # TODO: Seems like we should be able to skip the reify and comparison # below. obj = None try: rands = o.rands except NotImplementedError: return o new_rands = reify(rands, s) if rands == new_rands: return o else: newobj = type(o)(*new_rands, obj=obj) return newobj
def test_objects_full(): _unify.add((Foo, Foo, dict), unify_object) _unify.add((Bar, Bar, dict), unify_object) _reify.add((Foo, dict), reify_object) _reify.add((Bar, dict), reify_object) assert unify_object(Foo(1, Bar(2)), Foo(1, Bar(var(3))), {}) == {var(3): 2} assert reify(Foo(var('a'), Bar(Foo(var('b'), 3))), {var('a'): 1, var('b'): 2}) == Foo(1, Bar(Foo(2, 3)))
def test_objects_full(): _unify.add((Foo, Foo, dict), unify_object) _unify.add((Bar, Bar, dict), unify_object) _reify.add((Foo, dict), reify_object) _reify.add((Bar, dict), reify_object) assert unify_object(Foo(1, Bar(2)), Foo(1, Bar(var(3))), {}) == {var(3): 2} assert reify(Foo(var('a'), Bar(Foo(var('b'), 3))), {var('a'): 1, var('b'): 2}) == Foo(1, Bar(Foo(2, 3)))
def test_unify_isinstance_list(): class Foo2(Foo): pass x = var('x') y = var('y') f, g = Foo2(1, 2), Foo2(x, y) _unify.add((Foo, Foo, dict), unify_object) _reify.add((Foo, dict), reify_object) assert unify(f, g, {}) assert reify(g, {x: 1, y: 2}) == f
def _reify_MetaSymbol(o, s): if isinstance(o.obj, Var): obj = s.get(o.obj, o.obj) else: obj = None rands = o.rands() new_rands = reify(rands, s) if rands == new_rands: return o else: newobj = type(o)(*new_rands, obj=obj) return newobj
def reify_all_terms(obj, s=None): """Recursively reifies all terms tuples/lists with some awareness for meta objects.""" try: if isinstance(obj, MetaSymbol): # Avoid using `operator`/`arguments` and unnecessarily # breaking apart meta objects and the base objects they # hold onto (i.e. their reified forms). res = obj.reify() if not MetaSymbol.is_meta(res): return res op, args = operator(obj), arguments(obj) op = reify_all_terms(op, s) args = reify_all_terms(args, s) return term(op, args) except (IndexError, NotImplementedError): return reify(obj, s or {})
def test_objects_full(): _unify.add((Foo, Foo, Mapping), _unify_object) _unify.add((Bar, Bar, Mapping), _unify_object) _reify.add((Foo, Mapping), _reify_object) _reify.add((Bar, Mapping), _reify_object) x, y = var(), var() assert unify(Foo(1, 2), Bar(1), {}) is False assert unify(Foo(1, Bar(2)), Foo(1, Bar(x)), {}) == {x: 2} assert reify(Foo(x, Bar(Foo(y, 3))), { x: 1, y: 2 }) == Foo(1, Bar(Foo(2, 3))) class SubFoo(Foo): pass assert unify(Foo(1, 2), SubFoo(1, 2), {}) is False
from unification.ranged_variable import RangedVar from unification.value_space import RealRange from unification.core import reify, unify x = RangedVar() y = RangedVar(range=RealRange([(0,1)])) print(unify(x, y, {})) s = {y:2} y = reify(y, s) print(y) print(unify(x, y, s)) print(x, y)
def test_unifiable(): x = var('x') f = Aslot(1, 2) g = Aslot(1, x) assert unify(f, g, {}) == {x: 2} assert reify(g, {x: 2}) == f
def test_reify_slice(): x = var('x') assert reify(slice(1, var(2), 3), {var(2): 10}) == slice(1, 10, 3)
def _reify_TheanoClasses(o, s): meta_obj = MetaSymbol.from_obj(o) return reify(meta_obj, s)
def reify_cons(lcons, s): rcar = reify(car(lcons), s) rcdr = reify(cdr(lcons), s) return cons(rcar, rcdr)
def test_reify_list(): x, y = var(), var() s = {x: 2, y: 4} e = [1, [x, 3], y] assert reify(e, s) == [1, [2, 3], 4]
def test_unifiable_slots(): x = var() f = Aslot(1, 2) g = Aslot(1, x) assert unify(f, g, {}) == {x: 2} assert reify(g, {x: 2}) == f
def test_reify_slice(): x = var('x') assert reify(slice(1, var(2), 3), {var(2): 10}) == slice(1, 10, 3)
def test_reify_complex(): x, y = var(), var() s = {x: 2, y: 4} e = {1: [x], 3: (y, 5)} assert reify(e, s) == {1: [2], 3: (4, 5)}
def test_reify_list(): x, y = var(), var() s = {x: 2, y: 4} e = [1, [x, 3], y] assert reify(e, s) == [1, [2, 3], 4]
def test_reify_dict(): x, y = var(), var() s = {x: 2, y: 4} e = {1: x, 3: {5: y}} assert reify(e, s) == {1: 2, 3: {5: 4}}
def _reify_TFlowClasses(o, s): meta_obj = metatize(o) return reify(meta_obj, s)
def test_unifiable(): x = var('x') f = A(1, 2) g = A(1, x) assert unify(f, g, {}) == {x: 2} assert reify(g, {x: 2}) == f
def test_reify_slice(): x = var() assert reify(slice(1, x, 3), {x: 10}) == slice(1, 10, 3)
def test_reify_Set(): x, y = var(), var() assert reify({1, 2, x, y}, {x: 3}) == {1, 2, 3, y} assert reify(frozenset({1, 2, x, y}), {x: 3}) == frozenset({1, 2, 3, y})
def test_reify_complex(): x, y = var(), var() s = {x: 2, y: 4} e = {1: [x], 3: (y, 5)} assert reify(e, s) == {1: [2], 3: (4, 5)}
def test_reify_nonstandard_object(): _reify.add((ast.AST, Mapping), _reify_object) x = var() assert reify(ast.Num(n=1), {}).n == 1 assert reify(ast.Num(n=x), {}).n == x assert reify(ast.Num(n=x), {x: 2}).n == 2
def _reify_TheanoClasses(o, s): meta_obj = metatize(o) return reify(meta_obj, s)
def reify_cons(lcons, s): rcar = reify(car(lcons), s) rcdr = reify(cdr(lcons), s) return cons(rcar, rcdr)
def test_reify_dict(): x, y = var(), var() s = {x: 2, y: 4} e = {1: x, 3: {5: y}} assert reify(e, s) == {1: 2, 3: {5: 4}}