Lists in Prolog

advertisement
Declarative
Programming
Lists in PROLOG
Autumn 2014
Example - Fibonacci numbers
Fibonacci numbers are defined as follows:
F(i) =
0,
1,
F(i–1) + F(i – 2),
if i = 0
if i = 1
if i > 1
Example - Fibonacci numbers
Fibonacci numbers are defined as follows:
F(i) =
0,
1,
F(i–1) + F(i – 2),
if i = 0
if i = 1
if i > 1
fibonacci(0,0).
fibonacci(1,1).
fibonacci(X,R) :- X1 is X–1, X2 is X–2, fibonacci(X1,R1),
fibonacci(X2,R2),R is R1+R2.
Example - Fibonacci numbers
We can try to write a predicate that computes
both values F(i) and F(i – 1)
fibonacci(1,1,0).
fibonacci(X,R1,R2) :- X1 is X–1,fibonacci(X1,R2,R3),R1 is R2+R3.
Example - Fibonacci numbers
If we want, we can now add a predicate just for
computing of F(i)
fibonacci(1,1,0).
fibonacci(X,R1,R2) :- X1 is X–1,fibonacci(X1,R2,R3),R1 is R2+R3.
fibonacci(0,0).
fibonacci(X,R) :- fibonacci(X,R,R1).
Example - Fibonacci numbers
What, if we want something like this:
S(i) =
0,
1,
i*S(0)+ (i–1)*S(1)+...+2S(i–1),
if i = 0
if i = 1
if i > 1
Example - Fibonacci numbers
What, if we want something like this:
S(i) =
0,
1,
i*S(0)+ (i–1)*S(1)+...+2S(i–1),
if i = 0
if i = 1
if i > 1
A predicate that computes all the values S(0)...S(i)
at once could be useful...
Lists - the idea
nil
list(a,nil)
list(a,list(b,nil))
list(a,list(b,list(c,nil)))
...
represents the empty list
represents list a
represents list a,b
represents list a,b,c
Example - list of Fibonacci numbers
fibonacci(0,list(0,nil)).
fibonacci(1,list(1,list(0,nil))).
fibonacci(X,list(R, list(R1,list(R2,Z)))) :fibonacci(X1,list(R1,list(R2,Z))), R is R1+R2.
X1 is X–1,
Lists - predefined notation
[]
.(a,[])
.(a,.(b,[]))
.(a,.(b,.(c,[])))
...
represents the empty list
represents list a
represents list a,b
represents list a,b,c
Lists - predefined notation
There is also a special shortcut notation for lists in
PROLOG
.(a,.(b,.(c,[]))) can also be written as [a,b,c]
Lists - useful operations
Often it is useful to divide non-empty list into the
first element (head) and the remaining list (tail)
head(.(H,_),H).
tail(.(_,T),T).
Lists - useful operations
There are special predicate “|” that does not require
the use of “.” notation
head([H|_],H).
tail([_|T],T).
Lists - useful operations
Any fixed number of initial elements can be accessed
first_7([F1,F2,F3,F4,F5,F6,F7|_],F1,F2,F3,F4,F5,F6,F7).
Lists (from Clocksin)

Lists are the same as in other languages (such as
ML) in that a list of terms of any length is composed
of list cells that are ‘consed’ together.

The list of length 0 is called nil, written [].

The list of length n is .(head,tail), where tail is a list
of length n-1.

So a list cell is a functor ‘.’ of arity 2. Its first
component is the head, and the second component
is the tail.
Lists - examples (from Clocksin)
nil
.(a, nil)
.(a, .(b, nil)
.(a, .(b, .(c, .(d, .(e. nil)))))
.(a,b) (note this is a pair, not a proper list)
.(a, X) (this might be a list, or might not!)
.(a, .(b, nil)), .(c, nil))
Lists can be written as trees
a
a
nil
b
nil
a
b
a
a
b
c
a
d
e
nil
a
b
nil
nil
X
Lists - PROLOG syntax
Nil is written [].
The list consisting of n elements t1, t2, …,tn is written [t1,
t2, …,tn].
.(X,Y) is written [X|Y]
[X|[]] is written [X]
The term .(a, .(b, .(c,Y))) is written [a,b,c|Y].
If Y is instantiated to [], then the term is a list, and can
be written [a,b,c|[]] or simply [a,b,c].
Lists - Exercise 1
Identify the heads and tails of these lists (if any):
[a, b, c]
[a]
[]
[[the, cat], sat]
[[the, cardinal], [pulled, [off]], [each, [plum, coloured],
shoe]
Lists - Exercise 1
Identify the heads and tails of these lists (if any):
a
[b, c]
[a]
[]
[[the, cat], sat]
[[the, cardinal], [pulled, [off]], [each, [plum, coloured],
shoe]
Lists - Exercise 1
Identify the heads and tails of these lists (if any):
[a, b, c]
a
[]
[]
[[the, cat], sat]
[[the, cardinal], [pulled, [off]], [each, [plum, coloured],
shoe]
Lists - Exercise 1
Identify the heads and tails of these lists (if any):
[a, b, c]
[a]
[] (not a list, so doesn’t have head and tail. nil is a constant)
[[the, cat], sat]
[[the, cardinal], [pulled, [off]], [each, [plum, coloured],
shoe]
Lists - Exercise 1
Identify the heads and tails of these lists (if any):
[a, b, c]
[a]
[]
[the, cat]
[sat]
[[the, cardinal], [pulled, [off]], [each, [plum, coloured],
shoe]
Lists - Exercise 1
Identify the heads and tails of these lists (if any):
[a, b, c]
[a]
[]
[[the, cat], sat]
[the, cardinal]
coloured], shoe]
[pulled, [off]], [each, [plum,
Lists - Exercise 2
For each pair of terms, determine whether they unify,
and if so, to which terms are the variables instantiated?
[X, Y, Z]
[john, likes, fish]
[cat]
[X|Y]
[X,Y|Z]
[mary, likes, wine]
[[the,Y]|Z]
[[X,answer], [is, here]]
[X, Y, X]
[a, Z, Z]
[[X], [Y], [X]] [[a], [X], [X]]
Lists - Exercise 2
A variable may be instantiated to any term.
X
Y
Z
mary
likes
wine
[mary, likes, wine]
[]
[X,Y|Z]
“member” predicate
member(X, [X|T]).
member(X, [H|T]) :- member(X, T).
Examples:
?- member(john, [paul, john]).
?- member(X, [paul, john]).
?- member(joe, [marx, darwin, freud]).
?- member(foo, X).
“member” predicate
member(X, [X|T]).
Notice T isn’t ‘used’
member(X, [H|T]) :- member(X, T).
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
Notice H isn’t ‘used’
Exercise 3
Here is a mystery predicate. What does it do?
mystery(X, A, B) :- member(X, A), member(X, B).
?- mystery(a, [b, c, a], [p, a, l]).
?- mystery(b, [b, l, u, e], [y, e, l, l, o, w]).
?- mystery(X, [r, a, p, i, d], [a, c, t, i, o, n]).
?- mystery(X, [w, a, l, n, u, t], [c, h, e, r, r, y]).
Length of a list - Exercise 4
Naïve method:
length([], 0).
length([H|T], N) :- length(T, NT), N is NT + 1.
Length of a list - Tail recursion

Procedures such as length/2:
length([], 0).
length([H|T], N) :- length(T, NT), N is NT + 1.
often crash when processing large lists, even with a few
thousand elements.

This happens because in the recursive rule, the recursive
call is not the last goal on the rhs and so may need to be
backtracked into.

For each call, Prolog must store the choice points in a
memory stack of fixed size.
Length of a list - Tail recursion

No matter how large this memory stack is, it will
overflow if the list is long enough.

This is less likely to happen if the recursive call is
the last goal on the rhs - because within each call
there is no choice point for it.

Procedures in which recursive calls appear as the
last goal in the rule(s) are known as tail recursive.

There is a way of re-writing procedures such as
length/2 to make them tail recursive.
Length of a list - Tail recursion

The accumulator algorithm for the length of a list is:
Initialise the current sub-total, LengthSoFar, to 0.
To find the length of L
while L is non-empty do
for each element of L
remove the element and add 1 to
LengthSoFar
when L is empty set Length = LengthSoFar.
Length of a list - Exercise 4
Tail-recursive method:
length(L, N) :- acc(L, 0, N).
/* acc(List, LengthSoFar, Length) */
acc([], A, A).
acc([H|T], A, N) :- A1 is A + 1, acc(T, A1, N).
Length of a list - Exercise 4
?- length([apple, pear], N).
?- length([alpha], 2).
?- length(L, 3).
Modify length to give a procedure sum such that
sum(L,N) succeeds if L is a list of integers and N is their
sum.
“concat” predicate - Exercise 5
Write a predicate for concatenating 2 lists, i.e.
?-concat([a,b,c,d],[1,2,3],Result).
Result = [a,b,c,d,1,2,3] ?
Yes
“reverse” predicate - Exercise 6
Write a predicate for reversing a list, i.e.
?-reverse([a,b,c,d],Result).
Result = [d,c,b,a] ?
Yes
“sublist” predicate - Exercise 7
Write a predicate that checks whether a given list is
a sublist (in the same order) of another, i.e.
?-sublist([a,b,c,d],[a,c]).
Yes
?-sublist([a,b,c,d],[c,a]).
No
“setify” predicate - Exercise 8
Write a predicate that removes duplicate elements from
a given list, i.e.
?-setify([a,b,a,a,c,b,a,d],Result).
Result = [a,b,c,d] ?
Yes
“split” predicate - Exercise 9
Write a predicate that splits a given list of numbers into
lists of odd and even numbers, i.e.
?-split([1,2,3,4,5,5,6,8,7,9,2,3],R1,R2).
R1 = [1,3,5,5,7,9,3],
R2 = [2,4,6,8,2] ?
Yes
Download