declarative programming lists in prolog autumn 2014

Post on 14-Dec-2015

223 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Declarative Programming

Lists in PROLOG

Autumn 2014

Example - Fibonacci numbers

Fibonacci numbers are defined as follows:

0, if i = 0 F(i) = 1, if i = 1

F(i–1) + F(i – 2), if i > 1

Example - Fibonacci numbers

Fibonacci numbers are defined as follows:

0, if i = 0 F(i) = 1, if i = 1

F(i–1) + F(i – 2), 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 computesboth 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:

0, if i = 0S(i) = 1, if i = 1

i*S(0)+ (i–1)*S(1)+...+2S(i–1), if i > 1

Example - Fibonacci numbers

What, if we want something like this:

0, if i = 0S(i) = 1, if i = 1

i*S(0)+ (i–1)*S(1)+...+2S(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 represents the empty listlist(a,nil) represents list alist(a,list(b,nil)) represents list a,blist(a,list(b,list(c,nil))) 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)))) :- X1 is X–1, fibonacci(X1,list(R1,list(R2,Z))), R is R1+R2.

Lists - predefined notation

[] represents the empty list.(a,[]) represents list a.(a,.(b,[])) represents list a,b.(a,.(b,.(c,[]))) 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 nil a

b nil

a

b

c

d

e nil

a b a X

a

b nil

a nil

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] [pulled, [off]], [each, [plum, coloured], shoe]

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 Zmary

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]).

member(X, [H|T]) :- member(X, T).

member(X, [X|_]).

member(X, [_|T]) :- member(X, T).

Notice T isn’t ‘used’

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

top related