def test_08():
    """
    P08 (**): Eliminate consecutive duplicates of list elements.

    compress(L1,L2) :- the list L2 is obtained from the list L1 by
       compressing repeated occurrences of elements into a single copy
       of the element.
       (list,list) (+,?)

    compress([],[]).
    compress([X],[X]).
    compress([X,X|Xs],Zs) :- compress([X|Xs],Zs).
    compress([X,Y|Ys],[X|Zs]) :- X \\= Y, compress([Y|Ys],Zs).
    """
    Xs, Ys, Zs = Variable.factory("Xs", "Ys", "Zs")
    db = [
        dict(compress=[], list=[]),
        dict(compress=[X], list=[X]),
        Rule(dict(compress=[X, X, *Xs], list=Zs),
             dict(compress=[X, *Xs], list=Zs)),
        Rule(
            dict(compress=[X, Y, *Ys], list=[X, *Zs]),
            Assert(lambda X, Y: X != Y),
            dict(compress=[Y, *Ys], list=Zs),
        ),
    ]
    query = dict(compress=[1, 2, 1], list=Q)
    out = list(search(db, query))
    assert out == [{Q: [1, 2, 1]}]
def test_05():
    """
    P05 (*): Reverse a list.

    my_reverse(L1,L2) :- L2 is the list obtained from L1 by reversing
       the order of the elements.
       (list,list) (?,?)

    Note: reverse(+List1, -List2) is predefined

    my_reverse(L1,L2) :- my_rev(L1,L2,[]).

    my_rev([],L2,L2) :- !.
    my_rev([X|Xs],L2,Acc) :- my_rev(Xs,L2,[X|Acc]).
    """
    L1, L2, Xs, Acc = Variable.factory("L1", "L2", "Xs", "Acc")
    db = [
        dict(my_rev=[], list_in=L2, list_out=L2),
        Rule(
            dict(my_rev=[X, *Xs], list_in=L2, list_out=Acc),
            dict(my_rev=Xs, list_in=L2, list_out=[X, *Acc]),
        ),
    ]
    query = dict(my_rev=[1, 2], list_in=Z, list_out=[])
    assert list(search(db, query)) == [{Z: [2, 1]}]
def test_03():
    """
    P03 (*): Find the K'th element of a list.
    The first element in the list is number 1.

    element_at(X,L,K) :- X is the K'th element of the list L
       (element,list,integer) (?,?,+)

    Note: nth1(?Index, ?List, ?Elem) is predefined

    element_at(X,[X|_],1).
    element_at(X,[_|L],K) :- K > 1, K1 is K - 1, element_at(X,L,K1).
    """
    K, K1 = Variable.factory("K", "K1")

    db = [
        dict(nth_element=X, list=(X, *_W), n=1),
        Rule(
            dict(nth_element=X, list=(_W, *L), n=K),
            Assert(lambda K: K > 1),
            Assign(K1, lambda K: K - 1),
            dict(nth_element=X, list=L, n=K1),
        ),
    ]
    query_1 = dict(nth_element=Z, list=["a", "b", "c"], n=1)
    assert list(search(db, query_1)) == [{Z: "a"}]

    query_2 = dict(nth_element=Z, list=["a", "b", "c"], n=2)
    assert list(search(db, query_2)) == [{Z: "b"}]
def test_17():
    """
    P17 (*): Split a list into two parts

    split(L,N,L1,L2) :- the list L1 contains the first N elements
       of the list L, the list L2 contains the remaining elements.
       (list,integer,list,list) (?,+,?,?)

    split(L,0,[],L).
    split([X|Xs],N,[X|Ys],Zs) :- N > 0, N1 is N - 1, split(Xs,N1,Ys,Zs).
    """
    X, Xs, Ys, Zs, N, N1, P, Q = Variable.factory("X", "Xs", "Ys", "Zs", "N",
                                                  "N1", "P", "Q")
    db = [
        dict(split=L, a=0, b=[], c=L),
        Rule(
            dict(split=[X, *Xs], a=N, b=[X, *Ys], c=Zs),
            Assert(lambda N: N > 0),
            Assign(N1, lambda N: N - 1),
            dict(split=Xs, a=N1, b=Ys, c=Zs),
        ),
    ]
    assert list(search(db, dict(split=[1, 2, 3, 4, 5, 6, 7, 8], a=3, b=Q,
                                c=P))) == [{
                                    Q: [1, 2, 3],
                                    P: [4, 5, 6, 7, 8]
                                }]
def test_16():
    """
    P16 (**):  Drop every N'th element from a list

    drop(L1,N,L2) :- L2 is obtained from L1 by dropping every N'th element.
       (list,integer,list) (?,+,?)

    drop(L1,N,L2) :- drop(L1,N,L2,N).

    drop(L1,N,L2,K) :- L2 is obtained from L1 by first copying K-1 elements
       and then dropping an element and, from then on, dropping every
       N'th element.
       (list,integer,list,integer) (?,+,?,+)

    drop([],_,[],_).
    drop([_|Xs],N,Ys,1) :- drop(Xs,N,Ys,N).
    drop([X|Xs],N,[X|Ys],K) :- K > 1, K1 is K - 1, drop(Xs,N,Ys,K1).
    """
    Xs, Ys, N, K, K1, Q = Variable.factory("Xs", "Ys", "N", "K", "K1", "Q")
    L1, L2 = Variable.factory("L1", "L2")
    db = [
        dict(drop=[], a=_W, b=[], c=_W),
        Rule(dict(drop=[_W, *Xs], a=N, b=Ys, c=1), dict(drop=Xs,
                                                        a=N,
                                                        b=Ys,
                                                        c=N)),
        Rule(
            dict(drop=[X, *Xs], a=N, b=[X, *Ys], c=K),
            Assert(lambda K: K > 1),
            Assign(K1, lambda K: K - 1),
            dict(drop=Xs, a=N, b=Ys, c=K1),
        ),
        Rule(dict(drop=L1, a=N, b=L2), dict(drop=L1, a=N, b=L2, c=N)),
    ]
    assert list(search(db, dict(drop=[1, 2, 3, 4, 5, 6, 7, 8, 9], a=3,
                                b=Q))) == [{
                                    Q: [1, 2, 4, 5, 7, 8]
                                }]
def test_06():
    """
    P06 (*): Find out whether a list is a palindrome
    A palindrome can be read forward or backward; e.g. [x,a,m,a,x]

    is_palindrome(L) :- L is a palindrome list
       (list) (?)

    is_palindrome(L) :- reverse(L,L).
    """
    L1, L2, Xs, Acc = Variable.factory("L1", "L2", "Xs", "Acc")
    db = [
        dict(my_rev=[], a=L2, b=L2),
        Rule(dict(my_rev=[X, *Xs], a=L2, b=Acc),
             dict(my_rev=Xs, a=L2, b=[X, *Acc])),
        Rule(dict(is_palindrome=X), dict(my_rev=X, a=X, b=[])),
    ]
    query = dict(is_palindrome=[1, 2, 1])
    assert list(search(db, query)) == [{}]
def test_14():
    """
    P14 (*): Duplicate the elements of a list

    dupli(L1,L2) :- L2 is obtained from L1 by duplicating all elements.
       (list,list) (?,?)

    dupli([],[]).
    dupli([X|Xs],[X,X|Ys]) :- dupli(Xs,Ys).
    """
    Xs, Ys = Variable.factory("Xs", "Ys")

    db = [
        dict(dupli=[], list=[]),
        Rule(dict(dupli=[X, *Xs], list=[X, X, *Ys]), dict(dupli=Xs, list=Ys)),
    ]

    query = dict(dupli=["a", "b"], list=Z)

    assert list(search(db, query)) == [{Z: ["a", "a", "b", "b"]}]
def test_02():
    """
    P02 (*): Find the last but one element of a list

    last_but_one(X,L) :- X is the last but one element of the list L
       (element,list) (?,?)

    last_but_one(X,[X,_]).
    last_but_one(X,[_,Y|Ys]) :- last_but_one(X,[Y|Ys]).
    """
    Ys = Variable("Ys")

    db = [
        dict(last_but_one=X, list=(X, _W)),
        Rule(
            dict(last_but_one=X, list=(_W, Y, *Ys)),
            dict(last_but_one=X, list=(Y, *Ys)),
        ),
    ]
    query = dict(last_but_one=Q, list=["a", "b", "c"])
    assert next(search(db, query)) == {Q: "b"}
def test_09():
    """
    P09 (**):  Pack consecutive duplicates of list elements into sublists.

    pack(L1,L2) :- the list L2 is obtained from the list L1 by packing
       repeated occurrences of elements into separate sublists.
       (list,list) (+,?)

    pack([],[]).
    pack([X|Xs],[Z|Zs]) :- transfer(X,Xs,Ys,Z), pack(Ys,Zs).

    transfer(X,Xs,Ys,Z) Ys is the list that remains from the list Xs
       when all leading copies of X are removed and transfered to Z

    transfer(X,[],[],[X]).
    transfer(X,[Y|Ys],[Y|Ys],[X]) :- X \\= Y.
    transfer(X,[X|Xs],Ys,[X|Zs]) :- transfer(X,Xs,Ys,Zs).
    """

    Xs, Ys, Zs = Variable.factory("Xs", "Ys", "Zs")
    db = [
        dict(pack=[], list=[]),
        Rule(
            dict(pack=[X, *Xs], list=[Z, *Zs]),
            dict(transfer=X, a=Xs, b=Ys, c=Z),
            dict(pack=Ys, list=Zs),
        ),
        dict(transfer=X, a=[], b=[], c=[X]),
        Rule(
            dict(transfer=X, a=[Y, *Ys], b=[Y, *Ys], c=[X]),
            Assert(lambda X, Y: X != Y),
        ),
        Rule(
            dict(transfer=X, a=[X, *Xs], b=Ys, c=[X, *Zs]),
            dict(transfer=X, a=Xs, b=Ys, c=Zs),
        ),
    ]
    query = dict(pack=[1, 2, 2, 3, 3, 3], list=Q)
    assert list(search(db, query)) == [{Q: [[1], [2, 2], [3, 3, 3]]}]
def test_04():
    """
    P04 (*): Find the number of elements of a list.

    my_length(L,N) :- the list L contains N elements
       (list,integer) (+,?)

    Note: length(?List, ?Int) is predefined

    my_length([],0).
    my_length([_|L],N) :- my_length(L,N1), N is N1 + 1.
    """
    N, N1 = Variable.factory("N", "N1")
    db = [
        dict(my_length=0, list=[]),
        Rule(
            dict(my_length=N, list=[_W, *L]),
            dict(my_length=N1, list=L),
            Assign(N, lambda N1: N1 + 1),
        ),
    ]
    query = dict(my_length=Q, list=[1, 2, 3])
    assert list(search(db, query)) == [{Q: 3}]
def test_22():
    """
    P22 (*):  Create a list containing all integers within a given range.

    range(I,K,L) :- I <= K, and L is the list containing all
       consecutive integers from I to K.
       (integer,integer,list) (+,+,?)

    range(I,I,[I]).
    range(I,K,[I|L]) :- I < K, I1 is I + 1, range(I1,K,L).
    """
    I, I1, K, L = Variable.factory("I", "I1", "K", "L")
    db = [
        dict(start=I, end=I, list=[I]),
        Rule(
            dict(start=I, end=K, list=[I, *L]),
            Assert(lambda I, K: I < K),
            Assign(I1, lambda I: I + 1),
            dict(start=I1, end=K, list=L),
        ),
    ]
    query = dict(start=2, end=5, list=Z)
    assert list(search(db, query)) == [{Z: [2, 3, 4, 5]}]
def test_get_variables():
    A, B, C = Variable.factory("A", "B", "C")
    im = ImmutableDict(a=A, b=(1, B), c=ImmutableDict(d=(C, False)))
    assert im.get_variables() == {A, B, C}
import pytest

from inference_logic import Variable
from inference_logic.algorithms import unify
from inference_logic.data_structures import UnificationError, construct
from inference_logic.equality import Equality

A, B, C = Variable.factory("A", "B", "C")


@pytest.mark.parametrize(
    "left, right, initial, final",
    [
        (A, False, None, Equality(fixed={False: {A}})),
        (True, B, None, Equality(fixed={True: {B}})),
        (1, 1, None, Equality()),
        (A, B, None, Equality(free=[{A, B}])),
        ((A, B), (1, 2), None, Equality(fixed={1: {A}, 2: {B}})),
        (dict(a=A, b=2), dict(a=1, b=B), None, Equality(fixed={1: {A}, 2: {B}}),),
        (A, C, Equality(free=[{A, B}]), Equality(free=[{A, B, C}])),
        (A, 1, Equality(free=[{A, B}]), Equality(fixed={1: {A, B}})),
        (
            (A, *B),
            (True, False),
            None,
            Equality(fixed={True: {A}, construct([False]): {B}}),
        ),
        ((A, *B), (1, 2, 3), None, Equality(fixed={1: {A}, construct([2, 3]): {B}})),
        (*B, (2, 3), None, Equality(fixed={construct([2, 3]): {B}})),
    ],
)
import pytest

from inference_logic import Rule, Variable
from inference_logic.algorithms import search
from inference_logic.data_structures import Assert, Assign, PrologList

X, Y, Z = Variable.factory("X", "Y", "Z")
L, _W = Variable.factory("L", "W")
Q = Variable("Q")


def test_01():
    """
    P01 (*): Find the last element of a list

    my_last(X,L) :- X is the last element of the list L
       (element,list) (?,?)

    Note: last(?Elem, ?List) is predefined

    my_last(X,[X]).
    my_last(X,[_|L]) :- my_last(X,L).
    """

    db = [
        dict(last=X, list=[X]),
        Rule(dict(last=X, list=[_W, *L]), dict(last=X, list=L)),
    ]

    query = dict(last=Q, list=["a", "b", "c"])
    assert list(search(db, query)) == [{Q: "c"}]
Beispiel #15
0
def test_factory():
    assert Variable.factory("A", "B") == [Variable("A"), Variable("B")]
import pytest

from inference_logic import Variable
from inference_logic.data_structures import ImmutableDict, UnificationError, construct
from inference_logic.equality import Equality

A, B, C, D = Variable.factory("A", "B", "C", "D")


def test__repr__():
    equity = Equality(free=[{A}], fixed={True: {C}})
    assert repr(equity) == "Equality([{A}], True={C})"


@pytest.mark.parametrize(
    "method, args, message",
    [
        ("__eq__", (1,), "1 must be an Equality"),
        ("get_free", (1,), "1 must be a Variable"),
        ("get_fixed", (1,), "1 must be a Variable"),
        ("_add_constant", (1, 2), "1 must be a Variable"),
        ("_add_constant", (A, B), "B may not be a Variable"),
        ("_add_constant", (A, {1, 2}), "{1, 2} must be hashable"),
        ("_add_variable", (1, 2), "1 must be a Variable"),
        ("_add_variable", (A, 2), "2 must be a Variable"),
    ],
)
def test_type_error(method, args, message):

    equity = Equality()
    with pytest.raises(TypeError) as error:
Beispiel #17
0
def test_new_frame():
    assert Variable("A", 3).new_frame(4) == Variable("A", 4)
Beispiel #18
0
def test__repr__(name, frame, message):
    assert repr(Variable(name, frame)) == message
def test_11():
    """
    P11 (*):  Modified run-length encoding

    encode_modified(L1,L2) :- the list L2 is obtained from the list L1 by
       run-length encoding. Consecutive duplicates of elements are encoded
       as terms [N,E], where N is the number of duplicates of the element E.
       However, if N equals 1 then the element is simply copied into the
       output list.
       (list,list) (+,?)

    :- ensure_loaded(p10).

    encode_modified(L1,L2) :- encode(L1,L), strip(L,L2).

    strip([],[]).
    strip([[1,X]|Ys],[X|Zs]) :- strip(Ys,Zs).
    strip([[N,X]|Ys],[[N,X]|Zs]) :- N > 1, strip(Ys,Zs).
    """
    Xs, Ys, Zs = Variable.factory("Xs", "Ys", "Zs")
    L, L1, L2, N, N1 = Variable.factory("L", "L1", "L2", "N", "N1")

    db_04 = [
        dict(my_length=0, list=[]),
        Rule(
            dict(my_length=N, list=[_W, *L]),
            dict(my_length=N1, list=L),
            Assign(N, lambda N1: N1 + 1),
        ),
    ]

    db_09 = [
        dict(pack=[], list=[]),
        Rule(
            dict(pack=[X, *Xs], list=[Z, *Zs]),
            dict(transfer=X, a=Xs, b=Ys, c=Z),
            dict(pack=Ys, list=Zs),
        ),
        dict(transfer=X, a=[], b=[], c=[X]),
        Rule(
            dict(transfer=X, a=[Y, *Ys], b=[Y, *Ys], c=[X]),
            Assert(lambda X, Y: X != Y),
        ),
        Rule(
            dict(transfer=X, a=[X, *Xs], b=Ys, c=[X, *Zs]),
            dict(transfer=X, a=Xs, b=Ys, c=Zs),
        ),
    ]

    db_10 = [
        Rule(dict(encode=L1, a=L2), dict(pack=L1, list=L),
             dict(transform=L, list=L2)),
        dict(transform=[], list=[]),
        Rule(
            dict(transform=[[X, *Xs], *Ys], list=[[N, X], *Zs]),
            dict(my_length=N, list=[X, *Xs]),
            dict(transform=Ys, list=Zs),
        ),
    ]

    db_11 = [
        Rule(
            dict(encode_modified=L1, list=L2),
            dict(encode=L1, a=L),
            dict(strip=L, list=L2),
        ),
        dict(strip=[], list=[]),
        Rule(dict(strip=[[1, X], *Ys], list=[X, *Zs]), dict(strip=Ys,
                                                            list=Zs)),
        Rule(
            dict(strip=[[N, X], *Ys], list=[[N, X], *Zs]),
            Assert(lambda N: N > 1),
            dict(strip=Ys, list=Zs),
        ),
    ]
    db = db_04 + db_09 + db_10 + db_11
    query = dict(encode_modified=[1, 2, 2, 3, 3, 3], list=Q)
    assert list(search(db, query)) == [{Q: [1, [2, 2], [3, 3]]}]
Beispiel #20
0
def test__init__error():
    with pytest.raises(ValueError) as error:
        Variable(1)
    assert str(error.value) == "name must be a string"
import pytest

from inference_logic import Rule, Variable
from inference_logic.data_structures import construct, new_frame

A, B = Variable.factory("A", "B")
A_1 = Variable("A", 1)
B_1 = Variable("B", 1)


@pytest.mark.parametrize(
    "initial, final",
    [
        (True, True),
        (A, Variable("A", 1)),
        ((A, True), (A_1, True)),
        (dict(a=A), dict(a=A_1)),
    ],
)
def test_new_frame_function(initial, final):
    assert new_frame(construct(initial), 1) == construct(final)


@pytest.mark.parametrize(
    "initial, final",
    [(Rule(dict(a=A), dict(b=B)), Rule(dict(a=A_1), dict(b=B_1)))],
)
def test_new_frame_method(initial, final):
    assert construct(initial).new_frame(1) == construct(final)