You are on page 1of 79

2/20/2013

Prolog Programming

Introduction to logic programming


Declarative vs. procedural
Prolog components: facts, rules, queries
How logic programming works
Sample Prolog programs
Prolog exercise

1
2/20/2013

Prolog (PROgramming in LOGic)


Declarative (though they also have a procedural element)
Knowledge engineer provides logic and specifies a goal to be
achieved
Specify what problem needed to be solved rather than how to solve it
Describe properties of objects and relations between them (i.e. using
if-then rules)
colour(roses, red). if cheeky(X) then happy(X)
cheeky(danial)
therefore happy(danial)
Non-procedural
Unlike conventional procedural languages (i.e. programmer specify
steps to solve a problem), Prolog interpreter, on the other hand,
works out how to achieve the goal.

JAVA PROLOG

2
2/20/2013

How logic programming works


Logic programming uses a collection of facts and
rules stored in the knowledge base.
Query as mode of operation
by posing queries (i.e. questions) about information in
the knowledge base
Prolog infers from the facts and rules to answer queries.

Consider the following Prolog program:

and the following queries:


?- animal(fluffy). Is fluffy an animal?
?- cat(X). Is it possible to find cat?, lets call it X
?- cat(mischief). Is mischief a cat?
?- animal(belle). Is belle an animal?

Explain how Prolog responds to the above queries.

3
2/20/2013

For the 1st query: given that any X is an animal if


X is a cat, and fluffy is a cat, Prolog infers fluffy
is an animal.
For the 3rd query: mischief is not a cat -- on a
presumption that, as far as the program is
concerned, what is not currently known to be true
is false (i.e. closed world assumption).
For the 4th query: rules declare things that are
true depending on a given condition/facts.

4
2/20/2013

Write a program to put the following logical


statement into Prolog rule.

X is happy if X is cheeky (for any X)

By adding appropriate facts into a knowledge


base and posing queries, try to understand how
Prolog derives answers to the queries.

cheeky(danial).
% danial is cheeky

happy(X) :- cheeky(X).
% For all X, X is happy if X is cheeky

?- cheeky(X).
X = danial

?- happy(X).
X = danial

?- happy(danial).
yes

?- cheeky(danial).
yes

5
2/20/2013

PROLOG: Programming for Artificial Intelligence by Ivan Bratko


(Addison Wesley)

6
5/3/2013

Prolog Programming

Prolog consists of data object of different


types:
atoms, numbers, variables, compound terms such
as structures, and lists
they differ by its syntactic form
Also called terms

1
5/3/2013

An atom can be written in several ways:


begins with a lower-case letter followed by letters
(either case) or digits, or the underscore character.
cheeky red_apple wAES2106
using special characters + - * / = < > : . ~ which
may be in the form of sequence of characters or a
single character
:- predefined meaning in Prolog, read as if
% for insertion of a line of comment
a string of any characters enclosed within single
quotes.
WAES2106 123abc Kuala Lumpur Suite 12-8

Consists of sequence of integer or real


numbers
with/without a + or sign
may contain a single decimal point, anywhere
except before a + or - sign
-123 +25 12.3 -.123 +246.

2
5/3/2013

Begins with a capital letter, which can be


followed by letters (either case) or digits, or
the underscore character.
X123 Y Zara Kuala_Lumpur
Anonymous variables
using the underscore character _ for such case
where we are not interested to know the value of a
particular variable
for all Y, Y is a mother if Y has a daughter
mother(Y) :- daughter(_,Y).

Begins with an atom, known as functor,


followed by one or more arguments (separated
by a comma) and enclosed within parentheses.
Each argument is a term of any kind
(including a compound term)
Number of arguments is called its arity
colour(roses, red) happy(X) likes(myra, durian)
student('Sarah Ahmad', dob(12, february, 2000), age(12))
substract(10, 2, 8)

3
5/3/2013

An ordered collection of terms of any kind


(separated by a comma) and enclosed within
square brackets
[ ] an empty list
['kuala lumpur', 'shah alam', kuching]
[[white, blue, green], [yellow, orange, red]]
[prolog, ali, publication_year(22, january, 2012)]

To satisfy a goal, Prolog works through the


clauses in the KB in turn, from top to bottom
until a match is found.
happy(X) and happy(danial) are identical, thus can
be matched/unified by instantiating variable X to
danial (i.e. giving X the value)

4
5/3/2013

If Term1 and Term2 are constants, then they


match only if they are the same object
apples = apples

If Term1 is a variable and Term2 is anything,


then they match. Term1 is instantiated to
Term2 (and vice versa)
likes(myra, X) = likes(Y, chocolate)
X = chocolate Y = myra

If Term1 and Term2 are structures, then they


match only if
Term1 and Term2 have the same principal functor
all their corresponding components match
date(D,F, 2012) = date(D1, february, Y1)
D = D1 (binds two differently named variables to single,
unique variable)
F = february (F is instantiated to february )
Y1 = 2012 (Y1 is instantiated to 2012)

5
5/3/2013

Term 1 Term 2 Match?


doll X
parent(X, sarah) Y
colour (blue, green, yellow) colour(X, Y)
colour (a, b, c) col(a, b, c)
a b
parent(X, Y, Z) parent(ali, 35, doctor)
[a, cake(X, Y), B) [Q, R, c]

Term 1 Term 2 Match?


doll X Succeed
X = doll
parent(X, sarah) Y Succeed
Y = parent(X, sarah)
X is still unbound
colour (blue, green, yellow) colour(X, Y) Fails. The terms have different arity
colour (a, b, c) col(a, b, c) Fails. The terms have different functor

a b Fails as they are not identical


parent(X, Y, Z) parent(ali, 35, doctor) Succeed. X, Y, Z are instantiated to ali,
35, doctor, respectively
[a, cake(X, Y), B] [Q, R, c] Succeed.
Q=a
R = cake(X, Y)
B=c

6
5/3/2013

chases(X,Y) :- cat(X), bird(Y).


Procedural reading:
determines how Prolog satisfies a list of goals
depend on the order of goals and clauses
The procedural meaning is to satisfy chases(X,Y), first satisfy
cat(X), then satisfy bird(X)

big(bear).
big(elephant).
small(cat).
brown(bear).
black(cat).
gray(elephant).

dark(Z) :- black(Z).
dark(Z) :- brown(Z).

?- dark(X), big(X).

7
5/3/2013

Consider the following rule:


chases(X,Y) :- cat(X), bird(Y).
Declarative reading:
Determines whether a given goal is true and if so, for
what values of variables it is true.
The declarative meaning says chases(X,Y) is true if X and Y are
true

A variant of a clause C
an instance of the clause C where each variable is substituted by another
variable

An instance of a clause C
the clause C with each of its variables substituted by some term

father_of(X,Y) :- parent(X,Y), male(X).

father_of(A,B) :- parent(A,B), male(A). % variant of clause

father_of(tom,Y) :- parent(tom,Y), male(tom). % an instance of clause

8
5/3/2013

Given a program and a goal G, the declarative


meaning says:
G is true if and only if:
(1) there is a clause (i.e. C) in the program such that
(2) there is a clause instance (i.e. I) of C such that
(a) the head of I is identical to G, and
(b) all the goals in the body of I are true

male(tom).
parent_of(tom,sarah).

father_of(X,Y):-parent_of(X,Y), male(X).

G is father_of(tom,Y)

The program has C (i.e. rule) father_of(X,Y):-parent_of(X,Y), male(X)

and C (i.e. facts) parent_of(tom,sarah)and male(tom)

then father_of(tom,Y):-parent_of(tom,Y), male(tom)

and then

I is an instance of C father_of(tom,sarah) :- parent_of(tom, sarah), male(tom)

9
5/3/2013

Write a program to put the following logical statement into


Prolog rule.
For all X and Y,
X will be jealous of Y if
X likes Z and
Y likes Z
By adding appropriate facts into a knowledge base and
posing the query, ?- jealous(X,Y), try to understand
and trace how Prolog derives answer(s) to the query.

likes(irfan, zara).
likes(danial, zara).
jealous(X, Y):-
likes(X, Z),
likes(Y, Z).

Consider the following query, ?- jealous(X, Y). There are four


ways Prolog can satisfy the query. Work through the program carefully
and explain how does Prolog answer the above query by giving four
different solutions.

10
5/3/2013

PROLOG: Programming for Artificial Intelligence by Ivan Bratko (4th


edition), Addison Wesley.

11
15/3/2013

Prolog Programming

Proof search (and search tree)


How Prolog searches a KB to see if a query is
satisfied.
Constructing Prolog program
family.pl

1
15/3/2013

Prolog process query, searching the KB in left


to right depth-first order to find out whether
a query can be satisfied.

p(a). ?- w(What).
p(b).
q(a).
q(b).
r(b).
w(X) :- p(X), q(X), r(X).

?- w(What).

2
15/3/2013

p(a). ?- w(What).
p(b). What = X
q(a). ?- p(X), q(X), r(X).
q(b).
r(b). X=a X=b
w(X) :- p(X), q(X), r(X).
?- q(a), r(a). ?- q(b), r(b).
?- w(What).
What = b ?- r(a). ?- r(b).

Fails backtrack!

likes(irfan, zara). ?- jealous(X,Y).


likes(danial, zara).

jealous(X, Y):-
likes(X, Z),
likes(Y, Z).

?- jealous(A, B).

3
15/3/2013

likes(irfan, zara). ?- jealous(X,Y).


likes(danial, zara). X=A Y=B
?- likes(X,Z), likes(Y,Z).
jealous(X, Y):-
likes(X, Z), X = irfan Y = zara X = danial Y = zara
likes(Y, Z).
?- likes(Y,zara) ?- likes(Y,zara)
?- jealous(A, B).

X= Y = irfan
X = irfan Y = danial
Y = irfan Y = danial Y = irfan Y = danial
X = danial Y = irfan
X = Y = danial

Consider the following Prolog clauses:


v('A').
v(a).
x(b).
w(c,'A').
w(c, b).
m(X,Y,Z):-v(X), x(Y), w(Z,X).
Give all the variable instantiations during Prolog execution for the query
?- m(X,Y,_). Use backtracking to force Prolog to find more than one
solution. Where relevant, indicates whether the instantiations lead to
failures.
Draw the proof search tree for the query.

4
15/3/2013

v('A'). Variable instantiations during Prolog execution.


v(a). Step 1
x(b). X = A
w(c,'A'). Y=b
Z=c
w(c, b).
m(X,Y,Z):-v(X), x(Y), w(Z,X). Step 2 (backtrack)

?- m(X,Y,_). X = A
Y=b
Z=c
X = A
b\= A
Y=b;
Step 3 (backtrack)
no.
X=a
Y=b

A \= a
b \= a

Write a Prolog program called family.pl which contains information about family of
three generations as shown below.

Define the following relations using rules in Prolog.


- father
- mother
- sister
- aunty
- cousin

5
15/3/2013

What will be Prologs answers to the following queries?

sister(X,Y).

father_of(david,_).

aunty(X, james).

aunty(patricia, dora).

cousin(james, X).

mother_of(X,betty), aunty(X, james).

\+parent_of(tom, patricia).

parent_of(max,_); cousin(max, betty).

6
15/3/2013

?- sister(X, Y). ?- father_of(david, _). Conjoined goals AND


yes ?- mother_of(X, betty), aunty(X, james).
X = sarah , X = sarah ;
Y = max ; ?- aunty(X, james).
X = sarah ; no
X = sarah ,
Y = patricia ; no Negative goal NOT
?- \+parent_of(tom, patricia).
X = patricia ,
?- aunty(patricia, dora). no
Y = max ;
yes
X = patricia , Disjoint goals OR
Y = sarah ; ?- parent_of(max, _); cousin(max, betty).
Backtracking produced
duplicate results! Prolog no
X = dora ,
regards that each answers
Y = betty ;
as separate pieces of data. ?- cousin(james, X).
X = betty , X = dora ;
Y = dora ;
no X = betty ;

no

Consider the following clause:


play(dora, doll).

?- play(dora, What). % Dora plays with what?


What = doll.

go:-play(dora, What),
write('Dora likes to play with '), write(What), nl.

predicate go/0 (with no argument) enables query to be entered brief, i.e.

?- go.
Dora likes to play with doll
yes

7
27/3/2013

Prolog Programming

So far, we used functor, followed by a number of arguments in


parentheses to represent fact, e.g. likes(myra, durian)
As alternative, the fact can be written using infix operator.
This enables functor (i.e. likes) to be written between the two
arguments with no parentheses: myra likes durian.
To aid readability, you may write rule such as:
likes(dora, X) :- cat(X)
as dora likes X :- X is a cat.

1
27/3/2013

To perform arithmetic calculations:


+ addition
- subtraction
* multiplication
/ division The result is the whole number part of a division
mod remainder The result is the remainder of a division
sqrt(X)

The built-in predicate 'is' is used to evaluate an expression. Examples:

?- X is 1 + 2.
X=3

?- X is 3 + 5
X=8

X>Y X is greater than Y


X<Y X is less than Y
X >= Y X is greater than or equal to Y
X =< Y X is less than or equal to Y
X =:= Y the values of X and Y are equal
X is Y X is Y, if X matches the value of Y (where X is a variable or a constant
and Y is an arithmetic expression
X \== Y X is not literally equal to Y
X=Y X is equal to Y, if X and Y match
Examples:
?- 4 > 3. ?- 2 =:= 2.
yes yes
?- X is 2 + 2, X < 2. ?- 2 \== 3.
no yes
?- X is 2 + 2. ?- zara = zara.
X=4 yes

2
27/3/2013

?- Y is 10, Z is Y+1.
?- X is sqrt(36).
?- 10 is 7+13-11+9.
?- 88+15-3=:=110-5*2.
?- 6+4=:=6*3-8.
Consider the following rules:
greater_than(X,Y) :- X > Y.
add_3_and_double(X,Y) :- Y is (X+3)*2.
and the following queries:
?- greater_than(2,5).
?- add_3_and_double(2,Y)
Define a predicate sum that holds only when its 3rd argument is the sum of
the first two arguments. For example, sum(1,2,3) should hold, but
sum(2,2,5) should not

Y = 10 , Z = 11
X=6
no
yes
yes
no
Y = 10
sum(X, Y, Z) :- Z is X+Y.

3
27/3/2013

In ordinary arithmetic, 1+2*3 means (1+(2*3)) and 6-3-1 means (6-3)-1


(i.e. from left to right - equal precedence). Prolog follows the ordinary
arithmetic standard usage.
1+2*3 expression has the structure +(1,*(2,3))
6-3-1 has the structure -(-(6,3),1)

Consider the following expression:


a+b*c
In Prolog, the convention is that, operators with lower precedence bind
stronger
The operator with the highest precedence in a term is the principle functor
of the term.
Therefore in Prolog, the precedence of + is defined higher than the
precedence of * (and therefore * binds stronger than +).
The precedence of operators decides what is the correct interpretation of an
expression, and so the expression a + b * c is understood as +(a,*(b, c))
and not as *(+a,b),c).

4
27/3/2013

Prolog operators: binary

Infix: An infix operator appears between its two arguments (e.g. 2+3)
xfx non-associative
xfy right to left
yfx left to right
Prolog operators: unary

Prefix: Prefix operator appears before its single argument (e.g. 8)


fx non-associative
fy left to right

Postfix: Postfix operator appears after its single argument (e.g. 2 factorial)
xf non-associative
yf right to left

The definition of an operator includes three parts and is accomplished by issuing a directive
to Prolog.
op(<Precedence>, <Type>, <Operator>)

<Precedence> is an integer between 1 and 1200, the higher the number, the higher the
precedence of the operator. Atoms always have precedence 0.
<Type> is one of
xfx, xfy, yfx for binary operators,
fx, fy for prefix unary operators,
xf, yf for postfix unary operators
<Operator> is an atom or a list of atoms that represents the operator symbol(s). It is possible
to define two operators with the same symbol, as long as the type of each is different i.e.
infix, prefix or postfix.
xfx is non associative operator, which suggests that the operator is between two arguments.
f stands for the operator which acts as a point of reference to distinguish between the left
and right arguments (left or right for unary operators).
'x' and 'y' denote arguments.
xfy defines a right-associative operator and the type yfx, a left-associative operator.

5
27/3/2013

:-op(300,yfx,-). :-op(300,xfy,-).

?- display(4-1-2). ?- display(4-1-2).
-(-(4,1),2) -(4,-(1,2))
yes yes

?- X is 4-1-2. ?- X is 4-1-2.
X=1 X = 5 wrong

:-op(500,yfx,-). :-op(300,yfx,-).
:-op(400,yfx,/). :-op(400,yfx,/).

?- display(5-6/2). ?- display(5-6/2).
-(5,/(6,2)) /(-(5,6),2)
yes yes

?- X is 5-6/2. ?- X is 5-6/2.
X=2 X = -0.5 wrong

6
27/3/2013

:- op(500, yfx, [+,-]). :- op(500, xfy, [+,-]).

?- display(3-2+1). ?- display(3-2+1).
+(-(3,2),1) -(3,+(2,1))
yes yes

?- X is 3-2+1. ?- X is 3-2+1.
X=2 X = 0 wrong

:-op(500,yfx,+). :-op(400,yfx,+).
:-op(400,yfx,*). :-op(500,yfx,*).

?- display(1+2*3). ?- display(1+2*3).
+(1,*(2,3)) *(+(1,2),3)
yes yes

?- X is 1+2*3. ?- X is 1+2*3.
X=7 X = 9 wrong

7
27/3/2013

:- op(1200, xfx, [:-, -->])


:- op(1200, fx, [:-, ?-])
:- op(1100, xfy, ';)
:- op(1050, xfy, ->)
:- op(1000, xfy, ,)
:- op(700, xfx, [=, \=, ==, @<. @=<. @>, @>=, is,
=:=, =\=, <, >, =< <=, >=])
:- op(500, yfx, [+, -])
:- op(400, yfx, [*, /, //, mod])
:- op(200, xfx, **)

Using Prolog predefined arithmetic operators as follows:

:-op(500,yfx,[+, -]).
:-op(400,yfx,[/, *]).

What is the structure of the following arithmetic expression?

6/3-1*2+3

8
27/3/2013

?- display(6/3-1*2+3).
+(-(/(6,3),*(1,2)),3)
yes

?- Answer is 6/3-1*2+3.
Answer = 3

:-op(600, xfx, likes). :-op(100,fy,turn_on).

likes(myra,durian). turn_on(the_tv).

?- myra likes What. ?- turn_on the_tv.


What = durian yes

?- turn_on What
What = the_tv

9
27/3/2013

Consider the following statement:

danial likes drawing and reading

and the following operator definitions:

:- op(300,xfx,likes).
:- op(200,xfy,and).

Note that, an operator for 'and' can be defined as right-associative operator


according to Bratko (Prolog Pogramming for Artificial Intelligence).

How is this this statement understood by Prolog? What is their


structure?

Give 3 Prolog queries to demonstrate your answer.

likes(danial, and(drawing, reading))

danial likes What.


What = drawing and reading
danial likes What and reading.
What = drawing
danial likes drawing and What.
What = reading

10
27/3/2013

Define appropriate operators (and, inside) to be able to write


sentence as follow:

ball and marble inside blue_box inside red_box

and then ask Prolog the following query:

?- What and What2 inside blue_box inside red_box


What = ball
What2 = marble

:-op(300,xfy,and).
:-op(400,yfx,inside). % left associative

inside(inside(and(ball, marble), blue_box), red_box)

?- What and What2 inside blue_box inside red_box.


What = ball ,
What2 = marble

11
27/3/2013

Change the following statement into Prolog rule.

For all X and Y,


X chases Y if X is a dog and Y is a cat.

Define appropriate operator chases so that Prolog can answer


the following query:

?- Who chases Whom.

:-op(700,yfx,chases).

cat(tom).
dog(buddy).

chases(X,Y) :- dog(X), cat(Y).

?- Who chases Whom. display


Who = buddy ,
Whom = tom

12
27/3/2013

PROLOG: Programming for Artificial Intelligence by Ivan Bratko


(Addison Wesley)

13
29/3/2013

Prolog Programming

Prolog offers 2 ways to perform computations repetitively:


Backtracking (more on this in the next few lectures)
Recursion

Recursive programming
One of the most basic and most important concepts in computer
science (and mathematics) in general.

1
29/3/2013

The basic idea of recursion principle is the following:


To solve a complex problem, provide the solution for the simplest
problem of its kind (i.e. base case) and provide a rule for transforming
such a (complex) problem into a slightly simpler problem (i.e. a recursion
rule)
Recursive rule means a rule calls itself until some final point is reached (i.e.
the base case).
In Prolog what this means is that we have a first fact that acts as some
stopping condition followed up by some rule(s) that performs some
operation before reinvoking itself.

Suppose we want to print a table of the integers 1 to 5 and their


squares:

1 1
2 4
3 9
4 16
5 25

2
29/3/2013

The recursive algorithm for the problem is as follows:


To print square beginning with N:
If N > 5,
print bye
Otherwise,
print N and N2, then print squares beginning with N + 1.

Exercise
Now, transform the above algorithm into Prolog clauses.

In Prolog:

print_squares(N) :- N > 5, write(bye), nl.

print_squares(N) :-
S is N * N,
write(N), write(' '), write(S), nl,
M is N + 1,
print_squares(M).

3
29/3/2013

The sample of query is as follows:

| ?- print_squares(1).

1 1
2 4
3 9
4 16
5 25
bye
yes

Write a Prolog program to print integers from Last to First inclusive. The
sample run is as follow:

?- print_integers(5,2).
5
4
3
2
end

yes

4
29/3/2013

print_integers(First, First) :- write(First), nl,


write('end'), nl.

print_integers(Last, First) :- Last=\=First,


write(Last), nl,
N is Last-1,
print_integers(N, First).

Consider facts and a rule given below:

en_route(kajang).
en_route(Place):-
travel(Place,Travelling_by,NewPlace),
en_route(NewPlace).

travel(brighton,train,london).
travel(london,plane,dubai).
travel(dubai,plane,kuala_lumpur).
travel(kuala_lumpur,car,kajang).

?- en_route(brighton).

5
29/3/2013

What happens when we submit this query :

?- en_route(brighton).

Explain your answer.

What is Factorial?
The factorial N! of a natural number N is defined as the product
of all natural numbers from 1 to N.
The factorial of 1 is 1.
The factorial any larger integer N is N times the factorial of N-1.

6
29/3/2013

Heres a more formal, recursive definition:

1! = 1 (base case)
n! = (n 1)! n for n > 1 (recursion rule)

What is the answer for 5! ?


5! = 5 x 4 x 3 x 2 x 1 = 120

The definition of a Prolog predicate to compute factorials:

factorial(1, 1). % base case

factorial(N, Result) :- % recursion step


N > 1,
N1 is N - 1,
factorial(N1, Temp),
Result is Temp * N.

Provide Prolog trace for:


?- factorial(3, Result).

7
29/3/2013

How it works?
To compute the 3! we have to pass through the second part of
that definition 2 times until we get to the base case and are able
to calculate the overall result.
The procedure factorial calls itself to compute the factorial of the
next smaller integer, then uses the result to compute the factorial
of the integer, 3.
The recursion stops when the number whose factorial is to be
computed is 1.

8
18/4/2013

Prolog Programming

Lists is a sequence of Prolog objects of any kind and


can also be lists.
An empty list in Prolog:
[]
A non empty:
[violet, indigo, green, yellow].
The first item (i.e. violet) is the head of the list.
The remaining part of the list is the tail.
The head can be any Prolog data objects, however,
the tail has to be a list.

1
18/4/2013

What are the head and tail for the following lists?
[do, [re, mi]]
[do, re, [mi]]
[[do]]
[do, [re], mi]
Example of prolog query:
?- [Head | Tail] = [do, re, mi].
Head = do, Tail = [re, mi]

2
18/4/2013

[do, [re, mi]]


Head = do,
Tail = [[re, mi]]
[do, re, [mi]].
Head = do,
Tail = [re, [mi]]
[[do]]
Head = [do],
Tail = []
[do, [re], mi]
Head = do,
Tail = [[re], mi]

Given the lists 1 and 2 below, what are the values for the instantiated
variables?

Lists 1 Lists 2
[X, Y | Z] [do, re, mi]

[re] [X | Y]

[Orange | Apple] [[do], re, mi]

[X | [Y | [Z | W]]] [do, re, mi]

Example of prolog query:

?- [X, Y | Z] = [do, re, mi].


X = do, Y = re, Z = [mi]

3
18/4/2013

[re] = [X | Y].
X = re,
Y = []
[Orange | Apple] = [[do], re, mi].
Orange = [do],
Apple = [re,mi]
[X | [Y | [Z | W]]] = [do, re, mi].
X = do,
Y = re,
Z = mi,
W = []

Checking if some object is an element of a list.


Concatenating of two lists to obtain a third list.
Counting the length of a list (i.e. number of
elements the list contains).
Adding a new object to a list
Deleting some object from a list.
Sublist such that a list S occurs within L as its
sublist.
Permutating a list such that one list is a
permutation of the other list.

4
18/4/2013

The membership relation can be based on either of the


following cases:
X is the head of L
X is a member of the tail of L, if it can be proved that
X is a member of the Tail
In Prolog clauses:

member(X, [X | Tail]).

member(X, [Head | Tail]):-


member(X, Tail).

Describe how Prolog solve the following


query:

?- my_member(b, [a, b, c]).

5
18/4/2013

The concatenation relation can be based


on either of the following cases:
If the 1st argument is the empty list
then the 2nd and the 3rd argument
must be the same list, i.e.
conc([], L, L).
If the first argument of is non-empty
list then it has a head and a tail, i.e.
[X|L1]
For example:
conc([1, 2], [3, 4], [1, 2, 3, 4])

6
18/4/2013

In Prolog clauses:
conc([X | L1], L2, [X | L3]):-
conc(L1, L2, L3)
conc can be used (in the inverse direction) to decompose a given
list into two lists, e.g.
?- conc(L1, L2, [1, 2, 3]).
L1 = []
L2 = [1, 2, 3];
L1 = [1]
L2 = [2, 3];
L1 = [1, 2]
L2 = [3];
:

Describe how Prolog solve the following


query:

?- my_conc([a,b],[c,d],R).

7
18/4/2013

Can be based on either of the following cases:


If the list is empty, then its length is 0
If the list is not empty then List = [Head | Tail];
then its length is equal to 1 plus to the length of the
tail Tail
In Prolog clauses:
length([],0).
length([_| Tail], N):-
length(Tail,N1), N is N1+1.

8
18/4/2013

To add an item, i.e. X in front of the list, thus becomes the


new head of the list.
In Prolog clause: add(X, L, [X | L]).
For example:

?- add(2,[3,4],[X|L]).

X = 2,
L = [3,4]

?- add(2,[3,4,5],N).
N = [2,3,4,5]

Can be based on either of the following cases:


If X is the head of the list then the result (after the deletion)
is the tail of the list
If X is in the tail then it is deleted from there
In Prolog clauses:
del(X, [X | Tail], Tail).
del(X, [Y | Tail], [Y | Tail1]):-
del(X, Tail, Tail1).
For example:
del(a, [a, b, a], L).
L = [b, a];
L = [a, b];

9
18/4/2013

del can be used (in the inverse direction) to insert


a new item anywhere in the list.
For example:
?- del(z, L, [1, 2, 3]).
L = [z, 1, 2, 3];
L = [1, z, 2, 3];
L = [1, 2, z, 3];
L = [1, 2, 3, z];
no

The sublist relation can be based on either of the


following cases:
L can be decomposed into two lists, giving L1 and
L2
L2 can be further decomposed into two lists, giving
S and some L3.
In Prolog clauses:
sublist(S, L) :- conc(L1, L2, L),
conc(S, L3, L2).

10
18/4/2013

For example:
sublist([1, 2, 3], [0, 0, 1, 2, 3, 4])

Can also be used to find all sublists of a given list, for example:
?- sublist(S, [1, 2, 3]).

S = [];
S = [1];
S = [1, 2];
S = [1, 2, 3];
S = [];
S = [2];
:
:

The permutation relation can be based on either of the following


cases:
If the first list is empty then the second list is also empty
If the first list is not empty -- first permute L obtaining L1 and
then insert X at any position into L1.

In Prolog clauses:
permutation ([], []).
permutation ([X | L], P):-
permutation(L, L1),
insert(X, L1, P).

insert(X,List,AnotherList):-
del(X,AnotherList,List).

11
18/4/2013

For example:
?- permutation([apple, berry, cherry], P).
P = [apple,berry,cherry] ;
P = [berry,apple,cherry] ;
P = [berry,cherry,apple] ;
P = [apple,cherry,berry] ;
P = [cherry,apple,berry] ;
P = [cherry,berry,apple] ;
no

PROLOG: Programming for Artificial


Intelligence by Ivan Bratko (Addison Wesley)

12
25/05/2013

Prolog Programming

 The Cut Operator !

 Problems with Cuts

 Negation as Failure

 Using fail
 Backtracking using fail
 Cut using fail

1
25/05/2013

 Sometimes we need a way to prevent Prolog finding all solutions,


i.e. a way to stop backtracking.

 There are cases, however, where backtracking is not desirable.

 The cut operator ! is a predefined Prolog predicate that prevents


backtracking and can be placed anywhere inside a rules body.

 Executing the subgoal ! will always succeed, but afterwards,


backtracking into subgoals placed before the cut inside the same
rule body is not possible anymore.

 Consider the following facts in the KB


p(1).
p(2) :- !.
p(3).

 Write all Prologs answers to the following queries:


?- p(X).
?- p(X), p(Y).
?- p(X),!,p(Y).

2
25/05/2013

?- p(X). ?- p(X),!,p(Y).
X = 1 ; X = Y = 1 ;

X = 2 X = 1 ,
Y = 2
?- p(X), p(Y).
X = Y = 1 ;

X = 1 ,
Y = 2 ;

X = 2 ,
Y = 1 ;

X = Y = 2

 max, without cut:

max(A, B, A) :- A > B.
max(A, B, B) :- A =< B.

?- max(2, 5, X).
X = 5

?- max(3, 1, X).
X = 3 ;

 These two rules are mutually exclusive. If the first one succeeds then the
second one will fails, and vice versa.

3
25/05/2013

 max, with cut:

max(A, B, A) :- A > B, !.
max(A, B, B).

?- max(3, 5, X).
X = 5

?- max(3, 1, X).
X = 3

Represent the following facts in Prolog form.

The query, marks(80, Grade) should succeed, thus Grade = A

4
25/05/2013

marks(N,A) :- N>=80,!.
marks(N,B) :- N>=65,!.
marks(N,C) :- N>=55,!.
marks(N,D) :- N>=50,!.
marks(N,pass) :- N>=40,!.
marks(N,fail) :- N<40.

Consider the following Prolog clauses:

% shopping day on weekend in fair weather and on public


% holiday

holiday(friday, feb1).
holiday(wednesday,may1).
weekend(saturday).
weather(saturday,fair_weather).

shopping(Day) :- holiday(Day,_), !.
shopping(Day) :- weather(Day, fair_weather), weekend(Day).

1. Explain how Prolog respond to the query, ?- shopping(When).


2. What can you conclude from Prolog program in exercise 2 and 3?

5
25/05/2013

 Cut changes the declarative meaning of the program.


 Need to use it with care only where needed.
 Green cuts can be inserted for efficiency (i.e. program
in exercise 2).
 Red cuts should be considered carefully (i.e. program
in exercise 3).

 Cuts are very useful to guide the Prolog interpreter towards a


solution.
 However, by introducing cuts, we give up some of the declarative
meaning of Prolog towards a more procedural meaning.
 This can sometimes lead to unexpected results.
 Two types of cut:
 Green cut: makes a program more efficient without affecting the
set of solutions that the program generates
 Red cuts: prevents the program from generating solution it would
otherwise give

6
25/05/2013

 Sometimes we might not want to ask whether a certain goal


succeeds, but whether it fails.

 In Prolog this is possible using the \+ operator.

 In other words, \+ Goal succeeds, if Prolog fails to derive a


proof for Goal.

 Prologs negation is defined as the failure to provide a proof.

 Consider the following facts:

married(ahmad, lina).
married(ben, nancy).
married(chong, julia).
married(dani, damia).

 Then we can define single/1 that succeeds if the argument given


can neither be found as the first nor as the second argument in any
of the married/2 facts.

7
25/05/2013

 Consider the following predicate, single/1:


single(Person) :-
\+ married(Person, _),
\+ married(_, Person).
% use anonymous variable because its value would be
% irrelevant.

 and the following queries:

?- single(damia).
no
?- single(nour).
yes

Nour is assumed to be single, because she cannot be proved to


be married.

 Where to use \+:


 The \+ operator can be applied to any valid Prolog goal.

 Goals are either:


(sub)goals of a query or
(sub)goals of a rule-body.

 Facts and rule-heads arent goals. Hence, it is not possible to


negate a fact or the head of a rule.

8
25/05/2013

 fail is a symbol that will immediately fail when Prolog encounters


it as a goal. When fails, Prolog tries to backtrack.

 fail used in combination with automatic backtracking allow Prolog


to search through the KB to find all possible values of X that satisfy
the goal, say for example, list_all(X).

 fail used in combination with cut, blocks backtracking.

 Consider the following KB:

candy(vanilla).
candy(strawberry).
candy(chocolate).

list_all :- candy(X), write(X),


write( flavoured candy), nl, fail.
list_all.

 How does Prolog respond to the query, ?- list_all.

 The second clause list_all. ensure that, after the KB has been
searched, the goal succeeds. However, with only the first line, any call
to list_all. will eventually fail.

9
25/05/2013

 Suppose the KB contains the following clauses.


bird(robin).
bird(parrot).
bird(penguin).
can_fly(X) :- bird(X).
 The following query, ?- can_fly(penguin) gives
undesired result. Why?
 If we add new clause, can_fly(penguin):- fail. and
having the clause, can_fly(X) :- bird(X).
immediately following the new clause, the query still gives
undesired result. Why?
 How can we solve this problem using fail?

 The desired result can be achieved by defining the new clause as


follow:

bird(robin).
bird(parrot).
bird(penguin).
can_fly(penguin):- !, fail. % cut with failure
can_fly(X) :- bird(X).

 Cut using fail helps to specify few exceptions to general rules, in


this case, penguin cannot fly.
 But, if we pose the query, ?- can_fly(X) -- the answer is no.
How do we solve the problem?

10
25/05/2013

bird(robin).
bird(parrot).
bird(penguin).
can_fly(X) :- bird(X), X \== penguin .

 Write a program that repeatedly prompts the user to enter series of


numbers and outputs a message indicating whether each is an odd
or even number. The program stops when the user has entered 10
numbers.

Use recursion and ! operator.

11
25/05/2013

 Write a program that repeatedly prompts the user to enter series of


numbers and outputs a message indicating whether each is an odd
or even number. The program stops when the user has entered a
number 10.

Use repeat, ! and =:= operators.

 Write appropriate Prolog clauses that says:

Lina likes all candy flavours except orange flavour.

 Use appropriate queries to demonstrate your solution.

12
25/05/2013

likes(lina,X) :- candy(X), X == 'Orange', !, fail.


likes(lina,X) :- candy(X).

candy(X) :- candy_flav(X).

candy_flav('Strawberry').
candy_flav('Lemon').
candy_flav('Mint').

The queries, ?- likes(lina, Mint), yes


?- likes(lina, Orange), no

Explain how Prolog responds to the above queries.

13
5/25/2013

Prolog Programming

 Testing the types of terms


 Constructing and decomposing terms: =.., functor, arg
 Testing for equality and comparisons (see lecture note on arithmetic
and operations)
 Control facilities: !, fail, true, not(P), repeat, if-else construct
 Database manipulation
 Finding solutions: bagof, setof, findall
 Input and output

1
5/25/2013

 Predicates: var, nonvar, atom, integer, float, number, atomic,


compound
 var(Y): succeeds if Y is currently an uninstantiated variable.
 nonvar(Y): succeeds if Y is not a variable, or Y is an already
instantiated variable.
 atom(Y): checks if Y is instantiated to an atom.
 integer(Y): checks if Y is instantiated to an integer.
 float(Y): checks if Y is instantiated to a real number
 number(Y): checks if Y is instantiated to a number.
 atomic(Y): true if Y is either an atom or a number
 compound(Y): checks if Y is instantiated to a compound term (i.e.
a structure).

?- var(Y), Y =2. ?- atom('cake').


Y = 2 yes

?- X = 2, var(X). ?- atomic(22.5).
no no

?- atom(cake). ?- compound(mm(s)).
yes yes

?- atom(2).
no

2
5/25/2013

 Predicates: =.. , functor, arg

 Term =.. L
 Written as an infix operator and reads as univ. The goal Term =.. L
is true if L is a list that contains the principle functor of Term,
followed by its arguments.
Term =.. [Functor | ArgumentList]

?- a(b,c) =.. L.
L = [a,b,c]

?- Z =..[p,1,2].
Z = p(1,2).

 functor(Term, F, N)
 True if F is the principal functor of Term and N is the arity of F.

?- functor(t(a, b, c), X, Arity)


X = t
Arity = 3

3
5/25/2013

 arg(N, Term, A)
 True if A is the Nth argument of Term, numbering left to right from 1.

?- arg(2, f(a, b, c, d), X).


X = b

?- arg(3, f(a, x(b), y(c)), Z).


Z = y(c)

 !
 reads as cut, prevents backtracking

 fail
 a goal that always fails

 true
 a goal that always succeeds

 not(P)
 negation as failure

4
5/25/2013

 Repeat
 Is use to do a loop. The predicate in which it is used is repeated
until every goal succeeds.

pword :- repeat,
write('Please enter a password'),
read(X),(X == prolog).

?- pword.
Please enter a password|: hello.
Please enter a password|: world.
Please enter a password|: prolog.
yes

 (P -> Q; R)
 Is an if-then-else construct. It read as: if P then Q else R. The
arrow -> is an infix operator whose priority is less than that of ;
and greater than that of a comma.

?- X = 10, Y = 15, (X >= Y -> Colour = pink; Colour


= green).
X = 10 ,
Y = 15 ,
Colour = green

5
5/25/2013

 Prolog 'throws away' old solutions (and is not accessible any more)
as it backtracks to generate new solution. The predicates bagof,
setof and findall can be used if we prefer to have all generated
solutions available.
 bagof( X, P, L)
 This produces a list L of all the objects X such that a goal P is
satisfied.
 setof( X, P, L)
 This produces a list L of all the objects X that satisfy P. This time,
duplicate items will be eliminated and it defines the ordering
among terms.
 findall( X, P, L)
 Similar to bagof.
The difference: findall will return an empty list if a goal P has
no solutions, whereas bagof would fail in such situation.

Consider the following KB:

likes(myra, durian).
likes(danial, strawberry).
likes(zara, orange).
likes(irfan, durian).
likes(lana, apple).

?- bagof(Child, likes(Child, durian), L).


Child = _ ,
L = [myra,irfan]

?- bagof(Child, Fruit ^ likes(Child, Fruit), L).


Child = _ ,
Fruit = _ ,
L = [myra,danial,zara,irfan,lana]

6
5/25/2013

?- bagof(Child, likes(Child, Fruit), L).


Child = _ ,
Fruit = apple ,
L = [lana] ;
Child = _ ,
Fruit = durian ,
L = [myra,irfan] ;
Child = _ ,
Fruit = orange ,
L = [zara] ;
Child = _ ,
Fruit = strawberry ,
L = [danial] ;

?- bagof(Fruit, likes(Child, Fruit), L).


Fruit = _ ,
Child = danial ,
L = [strawberry] ;
Fruit = _ ,
Child = irfan ,
L = [durian] ;
Fruit = _ ,
Child = lana ,
L = [apple] ;
Fruit = _ ,
Child = myra ,
L = [durian] ;
Fruit = _ ,
Child = zara ,
L = [orange] ;

7
5/25/2013

likes(myra, durian).
likes(danial, strawberry).
likes(zara, orange).
likes(irfan, durian).
likes(lana, apple).

?- setof(Child, Fruit ^ likes(Child, Fruit), CList),


setof(Fruit, Child ^ likes(Child, Fruit), FList).
Child = _ ,
Fruit = _ ,
CList = [danial,irfan,lana,myra,zara] ,
FList = [apple,durian,orange,strawberry]

?- setof(Fruit/Child, likes(Child, Fruit), L).


Fruit = _ ,
Child = _ ,
L = [apple/lana, durian/irfan, durian/myra,
orange/zara, strawberry/danial]

likes(myra, durian).
likes(danial, strawberry).
likes(zara, orange).
likes(irfan, durian).
likes(lana, apple).

?- findall(Child, likes(Child, Fruit), L).


Child = _ ,
Fruit = _ ,
L = [myra,danial,zara,irfan,lana]

?- findall(Child, likes(Child, banana), L).


Child = _ ,
L = []

If there is no object X that satisfy condition P, then findall will succeed with
L = [ ]. Note that if the query ?- bagof(Child, likes(Child,
banana), L), then bagof will not succeed.

8
5/25/2013

 PROLOG: Programming for Artificial Intelligence by Ivan Bratko,


3rd edition, Addison Wesley