def test_unify_variable_with_itself_should_not_unify(): # Regression test for https://github.com/logpy/logpy/issues/33 valido = Relation() fact(valido, "a", "b") fact(valido, "b", "a") x = var() assert run(0, x, valido(x, x)) == ()
def test_fact(): rel = Relation() fact(rel, 1, 2) assert (1, 2) in rel.facts assert (10, 10) not in rel.facts facts(rel, (2, 3), (3, 4)) assert (2, 3) in rel.facts assert (3, 4) in rel.facts
def test_eq_comm_object(): x = var("x") fact(commutative, Add) fact(associative, Add) assert run(0, x, eq_comm(add(1, 2, 3), add(3, 1, x))) == (2, ) assert set(run(0, x, eq_comm(add(1, 2), x))) == set((add(1, 2), add(2, 1))) assert set(run(0, x, eq_assoccomm(add(1, 2, 3), add(1, x)))) == set( (add(2, 3), add(3, 2)))
def test_assoccomm_objects(): fact(commutative, Add) fact(associative, Add) x = var() assert run(0, True, eq_assoccomm(add(1, 2, 3), add(3, 1, 2))) == (True,) assert run(0, x, eq_assoccomm(add(1, 2, 3), add(1, 2, x))) == (3,) assert run(0, x, eq_assoccomm(add(1, 2, 3), add(x, 2, 1))) == (3,)
def test_eq_comm_object(): x = var('x') fact(commutative, Add) fact(associative, Add) assert run(0, x, eq_comm(add(1, 2, 3), add(3, 1, x))) == (2, ) assert set(run(0, x, eq_comm(add(1, 2), x))) == set((add(1, 2), add(2, 1))) assert set(run(0, x, eq_assoccomm(add(1, 2, 3), add(1, x)))) == \ set((add(2, 3), add(3, 2)))
def test_assoc_flatten(): add = "add" mul = "mul" fact(commutative, add) fact(associative, add) fact(commutative, mul) fact(associative, mul) assert (run( 0, True, assoc_flatten((mul, 1, (add, 2, 3), (mul, 4, 5)), (mul, 1, (add, 2, 3), 4, 5)), ) == (True, )) x = var() assert (run( 0, x, assoc_flatten((mul, 1, (add, 2, 3), (mul, 4, 5)), x), ) == ((mul, 1, (add, 2, 3), 4, 5), )) assert (run( 0, True, assoc_flatten(("op", 1, (add, 2, 3), (mul, 4, 5)), ("op", 1, (add, 2, 3), (mul, 4, 5))), ) == (True, )) assert run(0, x, assoc_flatten(("op", 1, (add, 2, 3), (mul, 4, 5)), x)) == (("op", 1, (add, 2, 3), (mul, 4, 5)), )
def test_eq_assoccomm(): x, y = var(), var() eqac = eq_assoccomm ac = 'commassoc_op' fact(commutative, ac) fact(associative, ac) assert results(eqac(1, 1)) assert results(eqac((1, ), (1, ))) assert results(eqac(x, (1, ))) assert results(eqac((1, ), x)) assert results(eqac((ac, (ac, 1, x), y), (ac, 2, (ac, 3, 1)))) assert results((eqac, 1, 1)) assert results(eqac((a, (a, 1, 2), 3), (a, 1, 2, 3))) assert results(eqac((ac, (ac, 1, 2), 3), (ac, 1, 2, 3))) assert results(eqac((ac, 3, (ac, 1, 2)), (ac, 1, 2, 3))) assert not results(eqac((ac, 1, 1), ('other_op', 1, 1))) assert run(0, x, eqac((ac, 3, (ac, 1, 2)), (ac, 1, x, 3))) == (2, )
def test_objects(): fact(commutative, Add) fact(associative, Add) assert tuple(goaleval(eq_assoccomm(add(1, 2, 3), add(3, 1, 2)))({})) assert tuple(goaleval(eq_assoccomm(add(1, 2, 3), add(3, 1, 2)))({})) x = var('x') assert reify(x, tuple(goaleval(eq_assoccomm( add(1, 2, 3), add(1, 2, x)))({}))[0]) == 3 assert reify(x, next(goaleval(eq_assoccomm( add(1, 2, 3), add(x, 2, 1)))({}))) == 3 v = add(1, 2, 3) with variables(v): x = add(5, 6) assert reify(v, next(goaleval(eq_assoccomm(v, x))({}))) == x
def test_expr(): add = 'add' mul = 'mul' fact(commutative, add) fact(associative, add) fact(commutative, mul) fact(associative, mul) x, y = var('x'), var('y') pattern = (mul, (add, 1, x), y) # (1 + x) * y expr = (mul, 2, (add, 3, 1)) # 2 * (3 + 1) assert run(0, (x, y), eq_assoccomm(pattern, expr)) == ((3, 2), )
def test_objects(): fact(commutative, Add) fact(associative, Add) assert tuple(goaleval(eq_assoccomm(add(1, 2, 3), add(3, 1, 2)))({})) assert tuple(goaleval(eq_assoccomm(add(1, 2, 3), add(3, 1, 2)))({})) x = var('x') assert reify( x, tuple(goaleval(eq_assoccomm(add(1, 2, 3), add(1, 2, x)))({}))[0]) == 3 assert reify(x, next(goaleval(eq_assoccomm(add(1, 2, 3), add(x, 2, 1)))({}))) == 3 v = add(1, 2, 3) with variables(v): x = add(5, 6) assert reify(v, next(goaleval(eq_assoccomm(v, x))({}))) == x
def test_unify_variable_with_itself_should_unify(): valido = Relation() fact(valido, 0, 1) fact(valido, 1, 0) fact(valido, 1, 1) x = var() assert run(0, x, valido(x, x)) == (1, )
def test_assoccomm_algebra(): add = "add" mul = "mul" fact(commutative, add) fact(associative, add) fact(commutative, mul) fact(associative, mul) x, y = var(), var() pattern = (mul, (add, 1, x), y) # (1 + x) * y expr = (mul, 2, (add, 3, 1)) # 2 * (3 + 1) assert run(0, (x, y), eq_assoccomm(pattern, expr)) == ((3, 2),)
def test_unify_tuple(): # Tests that adding facts can be unified with unpacked versions of those # facts. valido = Relation() fact(valido, (0, 1)) fact(valido, (1, 0)) fact(valido, (1, 1)) x = var() y = var() assert set(run(0, x, valido((x, y)))) == set([0, 1]) assert set(run(0, (x, y), valido((x, y)))) == set([(0, 1), (1, 0), (1, 1)]) assert run(0, x, valido((x, x))) == (1, )
from unification import var from kanren.facts import fact from kanren.assoccomm import commutative, associative from ...tensorflow.meta import mt, TFlowMetaOperator # TODO: We could use `mt.*.op_def.obj.is_commutative` to capture # more/all cases. fact(commutative, TFlowMetaOperator(mt.AddV2.op_def, var())) fact(commutative, TFlowMetaOperator(mt.AddN.op_def, var())) fact(commutative, TFlowMetaOperator(mt.Mul.op_def, var())) fact(associative, TFlowMetaOperator(mt.AddN.op_def, var())) fact(associative, TFlowMetaOperator(mt.AddV2.op_def, var()))
def test_eq_assoc_args(): assoc_op = "assoc_op" fact(associative, assoc_op) assert not run(0, True, eq_assoc_args(assoc_op, (1, ), [1], n=None)) assert run(0, True, eq_assoc_args(assoc_op, (1, ), (1, ), n=None)) == (True, ) assert run(0, True, eq_assoc_args(assoc_op, (1, 1), (1, 1))) == (True, ) assert run(0, True, eq_assoc_args(assoc_op, (1, 2, 3), (1, (assoc_op, 2, 3)))) == (True, ) assert run(0, True, eq_assoc_args(assoc_op, (1, (assoc_op, 2, 3)), (1, 2, 3))) == (True, ) assert run(0, True, eq_assoc_args(assoc_op, (1, (assoc_op, 2, 3), 4), (1, 2, 3, 4))) == (True, ) assert not run( 0, True, eq_assoc_args(assoc_op, (1, 2, 3), (1, (assoc_op, 2, 3), 4))) x, y = var(), var() assert run(0, True, eq_assoc_args(assoc_op, (x, ), (x, ), n=None)) == (True, ) assert run(0, x, eq_assoc_args(assoc_op, x, (y, ), n=None)) == ((y, ), ) assert run(0, x, eq_assoc_args(assoc_op, (y, ), x, n=None)) == ((y, ), ) assert run(0, x, eq_assoc_args(assoc_op, (1, x, 4), (1, 2, 3, 4))) == ((assoc_op, 2, 3), ) assert run(0, x, eq_assoc_args(assoc_op, (1, 2, 3, 4), (1, x, 4))) == ((assoc_op, 2, 3), ) assert run(0, x, eq_assoc_args(assoc_op, [1, x, 4], [1, 2, 3, 4])) == ([assoc_op, 2, 3], ) assert run(0, True, eq_assoc_args(assoc_op, (1, 1), ("other_op", 1, 1))) == () assert run(0, x, eq_assoc_args(assoc_op, (1, 2, 3), x, n=2)) == ( ((assoc_op, 1, 2), 3), (1, (assoc_op, 2, 3)), ) assert run(0, x, eq_assoc_args(assoc_op, x, (1, 2, 3), n=2)) == ( ((assoc_op, 1, 2), 3), (1, (assoc_op, 2, 3)), ) assert run(0, x, eq_assoc_args(assoc_op, (1, 2, 3), x)) == ( ((assoc_op, 1, 2), 3), (1, (assoc_op, 2, 3)), (1, 2, 3), ) assert () not in run(0, x, eq_assoc_args(assoc_op, (), x, no_ident=True)) assert (1, ) not in run(0, x, eq_assoc_args(assoc_op, (1, ), x, no_ident=True)) assert (1, 2, 3) not in run(0, x, eq_assoc_args(assoc_op, (1, 2, 3), x, no_ident=True)) assert (run( 0, True, eq_assoc_args( assoc_op, (1, (assoc_op, 2, 3)), (1, (assoc_op, 2, 3)), no_ident=True, ), ) == ()) assert (run( 0, True, eq_assoc_args( assoc_op, (1, (assoc_op, 2, 3)), ((assoc_op, 1, 2), 3), no_ident=True, ), ) == (True, ))
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), )
Sigma_rng_lv, name=Sigma_name_lv) y_name_lv = var("y_name") y_size_lv = var("y_size") y_rng_lv = var("y_rng") V_lv = var("V") f_mt = var("f") Y_mt = mt.MvNormalRV(f_mt, V_lv, y_size_lv, y_rng_lv, name=y_name_lv) y_mt = var("y") Y_obs_mt = mt.observed(y_mt, Y_mt) n_post_mt = etuple(mt.add, n_lv, etuple(mt.Shape, Y_obs_mt)) # wishart_posterior_exprs = etuple(mt.MvStudentTRV, # m_expr, C_expr, # y_size_lv, y_rng_lv) # return (Sigma_prior_mt, wishart_posterior_exprs) norm_norm_prior_post = _create_normal_normal_goals() fact( conjugate, # An unconjugated observation backed by an MvNormal likelihood with MvNormal prior mean norm_norm_prior_post[0], # The corresponding conjugated distribution norm_norm_prior_post[1], )
name=var()) gamma_mt = mt.GammaRV(var(), var(), size=var(), rng=var(), name=var()) exponential_mt = mt.ExponentialRV(var(), size=var(), rng=var(), name=var()) # TODO: Add constraints for different variations of this. Also, consider a # check for exact equality of the two dists, or simply normalize/canonicalize # the graph first. fact( derived_dist, mt.true_div( mt.NormalRV(0., 1., size=var('_ratio_norm_size'), rng=var('_ratio_norm_rng'), name=var()), mt.NormalRV(0., 1., size=var('_ratio_norm_size'), rng=var(), name=var())), mt.CauchyRV(0., 1., size=var('_ratio_norm_size'), rng=var('_ratio_norm_rng'))) # TODO: # fact(stable_dist, # normal_mt, ('StableRV', # 2., 0., # normal_mt.owner.inputs[1], # normal_mt.owner.inputs[1]))
gamma_mt = mt.GammaRV(var(), var(), size=var(), rng=var(), name=var()) exponential_mt = mt.ExponentialRV(var(), size=var(), rng=var(), name=var()) # TODO: Add constraints for different variations of this. Also, consider a # check for exact equality of the two dists, or simply normalize/canonicalize # the graph first. fact( derived_dist, mt.true_div( mt.NormalRV(0.0, 1.0, size=var("_ratio_norm_size"), rng=var("_ratio_norm_rng"), name=var()), mt.NormalRV(0.0, 1.0, size=var("_ratio_norm_size"), rng=var(), name=var()), ), mt.CauchyRV(0.0, 1.0, size=var("_ratio_norm_size"), rng=var("_ratio_norm_rng")), ) # TODO: # fact(stable_dist, # normal_mt, ('StableRV', # 2., 0., # normal_mt.owner.inputs[1],
@dispatch(tt_class_abstractions) def tuple_expression(x): return tuple_expression(mt(x)) 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 {}) fact(commutative, mt.add) fact(commutative, mt.mul) fact(associative, mt.add) fact(associative, mt.mul) __all__ = ['debug_unify', 'reify_all_terms', 'etuple', 'tuple_expression']
from kanren.facts import Relation, facts, fact from kanren.core import var, run from kanren.goals import membero ukuran = Relation() warna = Relation() gelap = Relation() jenis = Relation() facts(ukuran, ("beruang", "besar"), ("gajah", "besar"), ("semuat", "kecil"), ("kucing", "kecil")) facts(warna, ("beruang", "cokelat"), ("kucing", "hitam"), ("semut", "hitam"), ("gajah", "kelabu")) facts(jenis, ("beruang", "karnivora"), ("kucing", "karnivora"), ("semut", "omnivora"), ("gajah", "herbivora")) fact(gelap, "hitam") fact(gelap, "cokelat") x = var() herbivora = run(0, x, jenis(x, "karnivora")) print("hewan jenis karnivora :", herbivora)
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_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), )
import pytest from unification import reify, var, variables from kanren.core import run, goaleval from kanren.facts import fact from kanren.assoccomm import (associative, commutative, groupsizes_to_partition, assocunify, eq_comm, eq_assoc, eq_assoccomm, assocsized, buildo, op_args) from kanren.dispatch import dispatch a = 'assoc_op' c = 'comm_op' x, y = var('x'), var('y') fact(associative, a) fact(commutative, c) class Node(object): def __init__(self, op, args): self.op = op self.args = args def __eq__(self, other): return (type(self) == type(other) and self.op == other.op and self.args == other.args) def __hash__(self): return hash((type(self), self.op, self.args))
def test_relation(): parent = Relation() fact(parent, "Homer", "Bart") fact(parent, "Homer", "Lisa") fact(parent, "Marge", "Bart") fact(parent, "Marge", "Lisa") fact(parent, "Abe", "Homer") fact(parent, "Jackie", "Marge") x = var('x') assert set(run(5, x, parent("Homer", x))) == set(("Bart", "Lisa")) assert set(run(5, x, parent(x, "Bart"))) == set(("Homer", "Marge")) def grandparent(x, z): y = var() return conde((parent(x, y), parent(y, z))) assert set(run(5, x, grandparent(x, "Bart"))) == set(("Abe", "Jackie")) foo = Relation('foo') assert 'foo' in str(foo)