def test_conde_basics(): a, b = var(), var() res = list(conde([eq(1, a), eq(2, b)], [eq(1, b), eq(2, a)])({})) assert res == [{a: 1, b: 2}, {b: 1, a: 2}] res = list(conde([eq(1, a), eq(2, 1)], [eq(1, b), eq(2, a)])({})) assert res == [{b: 1, a: 2}] aa, ab, ba, bb, bc = var(), var(), var(), var(), var() res = list( conde( [eq(1, a), conde([eq(11, aa)], [eq(12, ab)])], [ eq(1, b), conde([eq(111, ba), eq(112, bb)], [eq(121, bc)]), ], )({})) assert res == [ { a: 1, aa: 11 }, { b: 1, ba: 111, bb: 112 }, { a: 1, ab: 12 }, { b: 1, bc: 121 }, ] res = list(conde([eq(1, 2)], [eq(1, 1)])({})) assert res == [{}] assert list(lconj(eq(1, 1))({})) == [{}] res = list(lconj(conde([eq(1, 2)], [eq(1, 1)]))({})) assert res == [{}] res = list( lconj(conde([eq(1, 2)], [eq(1, 1)]), conde([eq(1, 2)], [eq(1, 1)]))({})) assert res == [{}]
def test_disequality(): a_lv, b_lv = var(), var() q_lv, c_lv = var(), var() goal_sets = [ ([neq(a_lv, 1)], 1), ([neq(cons(1, a_lv), [1]), eq(a_lv, [])], 0), ([neq(cons(1, a_lv), [1]), eq(a_lv, b_lv), eq(b_lv, [])], 0), ([neq([1], cons(1, a_lv)), eq(a_lv, b_lv), eq(b_lv, [])], 0), # TODO FIXME: This one won't work due to an ambiguity in `cons`. # ( # [ # neq([1], cons(1, a_lv)), # eq(a_lv, b_lv), # # Both make `cons` produce a list # conde([eq(b_lv, None)], [eq(b_lv, [])]), # ], # 0, # ), ([neq(cons(1, a_lv), [1]), eq(a_lv, b_lv), eq(b_lv, tuple())], 1), ([neq([1], cons(1, a_lv)), eq(a_lv, b_lv), eq(b_lv, tuple())], 1), ( [ neq([1], cons(1, a_lv)), eq(a_lv, b_lv), # The first should fail, the second should succeed conde([eq(b_lv, [])], [eq(b_lv, tuple())]), ], 1, ), ([neq(a_lv, 1), eq(a_lv, 1)], 0), ([neq(a_lv, 1), eq(b_lv, 1), eq(a_lv, b_lv)], 0), ([neq(a_lv, 1), eq(b_lv, 1), eq(a_lv, b_lv)], 0), ([neq(a_lv, b_lv), eq(b_lv, c_lv), eq(c_lv, a_lv)], 0), ] for i, (goal, num_results) in enumerate(goal_sets): # The order of goals should not matter, so try them all for goal_ord in permutations(goal): res = list(lconj(*goal_ord)({})) assert len(res) == num_results, (i, goal_ord) res = list(lconj(*goal_ord)(ConstrainedState())) assert len(res) == num_results, (i, goal_ord) assert len(run(0, q_lv, *goal_ord)) == num_results, (i, goal_ord)
def test_lconj_basics(): a, b = var(), var() res = list(lconj(eq(1, a), eq(2, b))({})) assert res == [{a: 1, b: 2}] res = list(lconj(eq(1, a))({})) assert res == [{a: 1}] res = list(lconj_seq([])({})) assert res == [{}] res = list(lconj(eq(1, a), eq(2, a))({})) assert res == [] res = list(lconj(eq(1, 2))({})) assert res == [] res = list(lconj(eq(1, 1))({})) assert res == [{}] def gen(): for i in [succeed, succeed]: yield i res = list(lconj(gen())({})) assert res == [{}] def gen(): return res = list(lconj_seq([gen()])({})) assert res == []
def test_disequality_basic(): a_lv, b_lv = var(), var() ks = ConstrainedState() de = DisequalityStore({a_lv: {1}}) ks.constraints[DisequalityStore] = de assert unify(a_lv, 1, ks) is False ks = unify(a_lv, b_lv, ks) assert unify(b_lv, 1, ks) is False res = list(lconj(neq({}, 1))({})) assert len(res) == 1 res = list(lconj(neq(1, {}))({})) assert len(res) == 1 res = list(lconj(neq({}, {}))({})) assert len(res) == 0 res = list(lconj(neq(a_lv, 1))({})) assert len(res) == 1 assert isinstance(res[0], ConstrainedState) assert res[0].constraints[DisequalityStore].lvar_constraints[a_lv] == {1} res = list(lconj(neq(1, a_lv))({})) assert len(res) == 1 assert isinstance(res[0], ConstrainedState) assert res[0].constraints[DisequalityStore].lvar_constraints[a_lv] == {1} res = list(lconj(neq(a_lv, 1), neq(a_lv, 2), neq(a_lv, 1))({})) assert len(res) == 1 assert isinstance(res[0], ConstrainedState) assert res[0].constraints[DisequalityStore].lvar_constraints[a_lv] == {1, 2} res = list(lconj(neq(a_lv, 1), eq(a_lv, 2))({})) assert len(res) == 1 assert isinstance(res[0], ConstrainedState) # The constrained variable is already ground and satisfies the constraint, # so it should've been removed from the store assert a_lv not in res[0].constraints[DisequalityStore].lvar_constraints assert res[0][a_lv] == 2 res = list(lconj(eq(a_lv, 1), neq(a_lv, 1))({})) assert res == []