Пример #1
0
def test_goaleval():
    x, y = var('x'), var('y')
    g = eq(x, 2)
    assert goaleval(g) == g
    assert callable(goaleval((eq, x, 2)))
    with raises(EarlyGoalError):
        goaleval((membero, x, y))
    assert callable(goaleval((lallgreedy, (eq, x, 2))))
Пример #2
0
        def seq_apply_anyo_sub_goal(s):

            nonlocal i_any, null_type

            l_in_rf, l_out_rf = reify((l_in, l_out), s)

            i_car, i_cdr = var(), var()
            o_car, o_cdr = var(), var()

            conde_branches = []

            if i_any or (isvar(l_in_rf) and isvar(l_out_rf)):
                # Consider terminating the sequences when we've had at least
                # one successful goal or when both sequences are logic variables.
                conde_branches.append([eq(l_in_rf, null_type), eq(l_in_rf, l_out_rf)])

            # Extract the CAR and CDR of each argument sequence; this is how we
            # iterate through elements of the two sequences.
            cons_parts_branch = [
                goaleval(conso(i_car, i_cdr, l_in_rf)),
                goaleval(conso(o_car, o_cdr, l_out_rf)),
            ]

            conde_branches.append(cons_parts_branch)

            conde_relation_branches = []

            relation_branch = None

            if not skip_cars:
                relation_branch = [
                    # This case tries the relation continues on.
                    relation(i_car, o_car),
                    # In this conde clause, we can tell future calls to
                    # seq_apply_anyo that we've had at least one successful
                    # application of the relation (otherwise, this clause
                    # would fail due to the above goal).
                    _seq_apply_anyo(relation, i_cdr, o_cdr, True, null_type),
                ]

                conde_relation_branches.append(relation_branch)

            base_branch = [
                # This is the "base" case; it is used when, for example,
                # the given relation isn't satisfied.
                eq(i_car, o_car),
                _seq_apply_anyo(relation, i_cdr, o_cdr, i_any, null_type),
            ]

            conde_relation_branches.append(base_branch)

            cons_parts_branch.append(conde(*conde_relation_branches))

            g = conde(*conde_branches)
            g = goaleval(g)

            yield from g(s)
Пример #3
0
def test_lanyseq():
    x = var('x')
    g = lanyseq(((eq, x, i) for i in range(3)))
    assert list(goaleval(g)({})) == [{x: 0}, {x: 1}, {x: 2}]
    assert list(goaleval(g)({})) == [{x: 0}, {x: 1}, {x: 2}]

    # Test lanyseq with an infinite number of goals.
    assert set(run(3, x, lanyseq(((eq, x, i) for i in count())))) == {0, 1, 2}
    assert set(run(3, x, (lanyseq, ((eq, x, i) for i in count())))) == \
           {0, 1, 2}
Пример #4
0
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
Пример #5
0
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
Пример #6
0
    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)
Пример #7
0
    def seq_apply_anyo_init_goal(s):

        nonlocal null_type, skip_op

        # We need the `cons` types to match in the end, which involves
        # using the same `cons`-null (i.e. terminating `cdr`).
        if null_type is False:
            l_out_, l_in_ = reify((l_out, l_in), s)

            out_null_type = False
            if isinstance(l_out_, (ConsPair, ConsNull)):
                out_null_type = type(l_out_)()

            in_null_type = False
            if isinstance(l_in_, (ConsPair, ConsNull)):
                in_null_type = type(l_in_)()

                if out_null_type is not False and not type(in_null_type) == type(out_null_type):
                    yield from fail(s)
                    return

            null_type = (
                out_null_type
                if out_null_type is not False
                else in_null_type
                if in_null_type is not False
                else []
            )

        g = _seq_apply_anyo(
            relation,
            l_in,
            l_out,
            False,
            null_type,
            skip_cars=isinstance(null_type, ExpressionTuple) and skip_op,
        )
        g = goaleval(g)

        yield from g(s)
Пример #8
0
    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)
Пример #9
0
def results(g, s={}):
    return tuple(goaleval(g)(s))
Пример #10
0
def test_membero_can_be_reused():
    g = membero(x, (0, 1, 2))
    assert list(goaleval(g)({})) == [{x: 0}, {x: 1}, {x: 2}]
    assert list(goaleval(g)({})) == [{x: 0}, {x: 1}, {x: 2}]
Пример #11
0
def test_membero_can_be_reused():
    g = membero(x, (0, 1, 2))
    assert list(goaleval(g)({})) == [{x: 0}, {x: 1}, {x: 2}]
    assert list(goaleval(g)({})) == [{x: 0}, {x: 1}, {x: 2}]
Пример #12
0
def solve(n, expr, env, value, maxdepth=3):
    goals = eval_expro(expr, env, value, depth=0, maxdepth=maxdepth)
    results = map(partial(reify, expr), goaleval(lall(goals))({}))
    return take(n, unique(results, key=multihash))