def test_run(): x, y, z = map(var, 'xyz') assert run(1, x, eq(x, 1)) == (1, ) assert run(2, x, eq(x, 1)) == (1, ) assert run(0, x, eq(x, 1)) == (1, ) assert run(1, x, eq(x, (y, z)), eq(y, 3), eq(z, 4)) == ((3, 4), ) assert set(run(2, x, conde([eq(x, 1)], [eq(x, 2)]))) == set((1, 2))
def reduceo_goal(s): nonlocal in_term, out_term in_term_rf, out_term_rf = reify((in_term, out_term), s) # The result of reducing the input graph once term_rdcd = var() # Are we working "backward" and (potentially) "expanding" a graph # (e.g. when the relation is a reduction rule)? is_expanding = isvar(in_term_rf) # One application of the relation assigned to `term_rdcd` single_apply_g = (relation, in_term, term_rdcd) # Assign/equate (unify, really) the result of a single application to # the "output" term. single_res_g = eq(term_rdcd, out_term) # Recurse into applications of the relation (well, produce a goal that # will do that) another_apply_g = reduceo(relation, term_rdcd, out_term) # We want the fixed-point value to show up in the stream output # *first*, but that requires some checks. if is_expanding: # When an un-reduced term is a logic variable (e.g. we're # "expanding"), we can't go depth first. # We need to draw the association between (i.e. unify) the reduced # and expanded terms ASAP, in order to produce finite # expanded graphs first and yield results. # # In other words, there's no fixed-point to produce in this # situation. Instead, for example, we have to produce an infinite # stream of terms that have `out_term` as a fixed point. # g = conde([single_res_g, single_apply_g], # [another_apply_g, single_apply_g]) g = lall(conde([single_res_g], [another_apply_g]), single_apply_g) else: # Run the recursion step first, so that we get the fixed-point as # the first result g = lall(single_apply_g, conde([another_apply_g], [single_res_g])) g = goaleval(g) yield from g(s)
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_run(): x, y, z = var(), var(), var() res = run(None, x, eq(x, 1)) assert isinstance(res, Iterator) assert tuple(res) == (1, ) assert run(1, x, eq(x, 1)) == (1, ) assert run(2, x, eq(x, 1)) == (1, ) assert run(0, x, eq(x, 1)) == (1, ) assert run(1, x, eq(x, (y, z)), eq(y, 3), eq(z, 4)) == ((3, 4), ) assert set(run(2, x, conde([eq(x, 1)], [eq(x, 2)]))) == set((1, 2))
def test_conde(): x = var() assert results(conde([eq(x, 2)], [eq(x, 3)])) == ({x: 2}, {x: 3}) assert results(conde([eq(x, 2), eq(x, 3)])) == () assert set(run(0, x, conde([eq(x, 2)], [eq(x, 3)]))) == {2, 3} assert set(run(0, x, conde([eq(x, 2), eq(x, 3)]))) == set() goals = ([eq(x, i)] for i in count()) # infinite number of goals assert run(1, x, conde(goals)) == (0, ) assert run(1, x, conde(goals)) == (1, )
def _gapplyo(s): nonlocal in_graph, out_graph in_graph_rf, out_graph_rf = reify((in_graph, out_graph), s) _gapply = partial(graph_applyo, relation, preprocess_graph=preprocess_graph) graph_reduce_gl = (relation, in_graph_rf, out_graph_rf) # We need to get the sub-graphs/children of the input graph/node if not isvar(in_graph_rf): in_subgraphs = preprocess_graph(in_graph_rf) in_subgraphs = None if length_hint(in_subgraphs, 0) == 0 else in_subgraphs else: in_subgraphs = in_graph_rf if not isvar(out_graph_rf): out_subgraphs = preprocess_graph(out_graph_rf) out_subgraphs = None if length_hint(out_subgraphs, 0) == 0 else out_subgraphs else: out_subgraphs = out_graph_rf conde_args = ([graph_reduce_gl],) # This goal reduces sub-graphs/children of the graph. if in_subgraphs is not None and out_subgraphs is not None: # We will only include it when there actually are children, or when # we're dealing with a logic variable (e.g. and "generating" # children). subgraphs_reduce_gl = seq_apply_anyo(_gapply, in_subgraphs, out_subgraphs) conde_args += ([subgraphs_reduce_gl],) g = conde(*conde_args) g = goaleval(g) yield from g(s)
def grandparent(x, z): y = var() return conde((parent(x, y), parent(y, z)))
def test_conde(): x = var('x') assert results(conde([eq(x, 2)], [eq(x, 3)])) == ({x: 2}, {x: 3}) assert results(conde([eq(x, 2), eq(x, 3)])) == ()
def sibling(x, y): temp = var() return conde((parent(temp, x), parent(temp, y)))
def grandparent(x, y): temp = var() return conde((parent(x, temp), parent(temp, y)))
def uncle(x, y): temp = var() return conde((parent(temp, x), grandparent(temp, y)))
def eq_permute(x, y): return conde([eq(x, y)], [permuteo(a, b) for a, b in zip(x, y)])