0% found this document useful (0 votes)
45 views

Prolog Tutor

Uploaded by

Apram Singh
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views

Prolog Tutor

Uploaded by

Apram Singh
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 39

Prolog Self Tutor

Dave Saunders
(modified by Graem Ringwood)
Department of Computer Science
Queen Mary and Westfield College
0.
The notes are based on four weeks' of practical. Most statements in these notes hold for all
ersions of !rolog. They use "S# !rolog.
0.1 References
There are many books on !rolog and $". The following are the better ones%
&lach ! '())*+ Simply ,ogicial- Wiley
#'.eefe '())/+ The Craft of !rolog- M"T !ress
Shoham 0 '())*+ $rtificial "ntelligence Techni1ues in !rolog- Morgan .aufmann
2Sterling ,S and Shapiro 30 '())*+ The $rt of !rolog 4nd ed- M"T !ress
The one marked with a 2 is introductory.
0.2 Accessing Prolog
5nder 5ni6- !rolog may be accessed by typing%
prolog
in an 7term or telnet session. "f there is a prolog system running on the machine you will get
a prompt something like%
SICStus 2.1 #8: Wed Jan 19 12:23:17 GMT 1994
| ?-
There is an online manual for Sicstus !rolog which can be accessed on the Web with the
58,% http% 9 9 www. dcs.1mw.ac.uk%:/:/9 manuals 9 S"CStus;man9 sicstus;toc.html
Sicstus !rolog is both compiled and interpreted . !rograms are usually loaded from files. $
number of procedures are built-in- that is they are present before any user program is loaded.
#ne of these is consult- which loads a program from a file Type%
consult(file).
in response to the prompt to load the file called file.pl. Note the full-stop at the end. <y
conention- !rolog filenames end in .pl. "t is not necessary to type this e6tension. "f the
filename starts with a capital letter- or contains non= alphanumeric characters- you hae to
enclose it within 1uotes%
consult('file.pl').
To e6it the !rolog system type%
halt.
or
^D.
$ summary of all the built=ins is gien in the manual.
(
1. Week 1
1.1. Introduction
!rolog is a relational language. "t is a based on a subset of &#,. There are some non= logical
parts for finer control of program e6ecution.
1.2. The usual example
The following is a !rolog program representing a family database. This is the usual first
!rolog program.
mother'fred->ill+.
mother'flo->erri+.
mother'terry->erri+.
mother'>ames-rowena+.
mother'>ill-roberta+.
mother'rob-henrietta+.
mother'harry-petra+.
father'fred->ames+.
father'flo->ames+.
father'terry->ack+.
father'>ames-rob+.
father'>ill-re6+.
father'rob-harry+.
father're6-harry+.
father'harry-peter+.
parent'7-0+ %= mother'7-0+.
parent'7-0+ %= father'7-0+.
grandparent'7-0+ %= parent'7-?+-parent'?-0+.
ancestor'7-0+ %= parent'7-0+.
ancestor'7-0+ %= parent'7-?+-ancestor'?-0+.
$ll predicates are to be read in similar fashion eg father'fred->ames+ is read 'fred is the father
of >ames'. The family tree aboe looks like%
4
fred flo terry
jack jerri
jill james
roberta rex rowena rob
henrietta harry
petra peter
1.3. Prolog syntax
$ program is made up of such facts and rules. <oth are called definite clauses. Within these
are predicate expressions such as mother'>ames-rowena+ and ancestor'7-?+. $ predicate
e6pression consists of a predicate name followed by the arguments in parentheses- separated
by commas. "f there are no arguments then the parentheses are omitted. $ll the predicates
e6pressions in the aboe e6ample hae two arguments but there may be any number.
@ames of ob>ects may contain the underline symbol ;- letters and digits- but cannot start
with a digit. @ames starting with a lower case letter are constants and functions. @ames
starting with capital letters or underline represent ariables and are assumed to be
uniersally 1uantified. The scope of a ariable is the definite clause. Strings like (4A or =*A4
are integers in the usual way. Definite clauses are terminated with a period and a carriage
return- as can be seen aboe.
$ fuller account of the synta6 is gien in the manual.
1.4. Logical interpretation
$ !rolog rule- of the form%
p'7(-...7n+ %= 1'7(-...7n-0(-...0m+
has the logical reading
'7(-...7n+'p'7(-...7n+ '0(-...0m+'1'7(-...7n-0(-...-0m+++
or alternatiely
'7(-...7n-0(-...0m+'p'7(-...7n+ 1'7(-...7n-0(-...-0m++
Thus the last statement of the program has the logical reading
'7-0-?+'ancestor'7-0+ parent'7-?+ ancestor'?-0++
@ote therefore that a !rolog statement implicitly has uniersal 1uantification oer all
ariables in it. ,ogical or can be written using two !rolog statements.
To say that B7 is the parent of 0 if 7 is the mother of 0 #8 7 is the father of 0B
'7-0+'parent'7-0+ mother'7-0+ father'7-0++
would appear in !rolog as the two rules
parent'7-0+ %= mother'7-0+.
A
parent'7-0+ %= father'7-0+.
@ote that a fact such as father'fred->ames+ can be thought of as a rule 'father'fred->ames+ %= .+-
ie- fred is the father of >ames if ...- ie you don't need any condition to proe that the father of
fred is >ames. $ rule such as ' %= p'7+.+ is e1uialent to nothing can be concluded from p'7+-
ie p'7+ is false. This is more easily seen if we note the following e1uialences%
"S# !rolog logic
1 %= p. 1p
and hence
1 %= p. 1 Cp
1 %= . 1
%= p. C p
1.. The Prolog interpreter.
1..1. !etting "tarted
Copy the file 9i mport 9 t eaching9 $dMSc9 M$S9 family.pl to your own directory. Start up
the !rolog interpreter as described aboe and consult the file family. This is done by
responding
consult 'family+.
to the prompt. $ shorter way is simply DfamilyE.. #ou $%"T put a period &.& at the end.
The interpreter then checks for synta6 errors etc- but if there are none it replies with a
message indicating the consultation followed by%
yes
F G=
The yes means that it has satisfied the consultation. "f there were errors it would hae
indicated the position of the first error and then said no. $nything you respond to the
prompt is regarded as a 1uery which it tries to satisfy. The last line is then >ust another
prompt.
$ fuller account of how to run !rolog is gien in the maual.
1..2. 'uerying facts
0ou can now 1uery the fact and rule base.
Thus
F G= father'flo->ames+.
yes
'83M3M<38 T# !5T TH3 '. &$T TH3 3@D.+
F G= father'fred-flo+.
no
F G=
*
"f you gie a 1uery with ariables in it- the system tries to find all ways of satisfying the
1uery = after each success it asks whether you wish it to continue. "f you want any other
answers type ( if not type .. Thus%
F G= mother'fred-7+.
7 I >ill J
no
F G= mother'7->erri+.
7 I flo J
7 I terry J
no
F G= father'7->ames+.
7 I fred .
yes
F G=
We could also hae tried father'7-0+ which would hae yielded all pairs 7-0 where the
father of 7 is 0- eg
F G= father'7-0+.
7 I fred
0 I >ames J
7 I flo
0 I >ames J
7 I terry
0 I >ack .
yes
F G=
1..3. 'uerying facts deri)ed from rules.
This is essentially the same- thus%
F G= parent'fred-M+.
M I >ill J
K
M I >ames J
no
F G= parent'M->ames+.
M I fred J
M I flo J
no
F G=
The system tries to satisfy parent'fred-M+. $ccordingly it runs through the facts and rules
until it finds parent in a head of a rule. The first such is parent'7-0+ %= mother'7-0+.. "t unifies
fred with 7 'more on unification later+ and tries to satisfy the body of the rule with this
unification ie it tries to satisfy mother'fred-M+. To do this it runs through the knowledge
base till it comes to mother'fred->ill+ which gies us the first solution M I >ill. #n receiing
the semicolon from us it tries again- but can't find any other occurences of mother with fred
as first argument. "t then looks again for a rule head containing parent. The ne6t such is
parent'7-0+ %= father'7-0+. so it tries to satisfy father'fred-M+ which gies another solution M
I >ames. #n receiing another semicolon it tries again- but can't satisfy parent'fred-M+ in
any other way. Trying to satisfy parent'M->ames+ is similar but this time mother neer can
be satisfied with >ames as second argument- but father can be satisfied twice.
@ote that the 1uery parent'terry->ack+ would first try to satisfy mother'terry->ack+ which fails-
and then father'terry->ack+ which succeeds- thus%
F G= parent'terry->ack+.
yes
F G= parent'>ames-fred+.
no
F G=
5sing the other predicates% grandparent- ancestor is similar.
F G= grandparent'fred-rowena+.
yes
F G= grandparent'7->ames+.
no
F G= ancestor'7-fred+.
no
F G= grandparent'>ames-<+.
< I henrietta J
L
< I harry J
no
F G= grandparent'7-rob+.
7 I fred J
7 I flo J
no
F G=
#f course- >ames probably has * grandparents- but only two of them seem to be in the
knowledge base. To satisfy grandparent'>ames-<+ it finds the rule grandparent etc and tries
to satisfy parent'>ames-?+ which it first does by trying to satisfy mother*>ames-?+ which
succeeds with ?Irowena. "t then tries to satisfy parent'rowena-<+ but fails. "t then backtracks
to the preious predicate ie parent'>ames-?+ and tries to resatisfy this. @eedless to say >ames
doesn't hae another mother so it tries using the other parent rule ie tries to satisfy
father'>ames-?+. "t can do this by setting ?Irob. "t then tries parent'rob-<+. "t can do this by
satisfying mother'rob-<+ with < I henrietta. $fter the semicolon it then satisfies
parent'rob-<+ again using father'rob-<+ with < I harry. "t tries again after the ne6t
semicolon- but there are no more solutions.
!randparent'7-rob+ is done similarly. "t tries to satisfy parent'7-?+ and hence mother'7-?+.
This can be done with 7Ifred-?I>ill. Howeer- parent'>ill-rob+ then fails. "t then tries
7Iflo-?I>erri but then parent'>erri-rob+ fails. This continues until it runs out of ways of
satisfying mother'7-?+- and tries father'7-?+ instead. "t satisfies this with 7Ifred-?I>ames-
and it tries to satisfy parent'>ames-rob+. This succeeds as father'>ames-rob+ succeeds.
grandparent'7-rob+ therefore succeeds with 7I fred. The ne6t attempt obtains the other
solution- and any further attempt fails.
0ou can watch all these contortions by doing
F G= trace.
Ma message about creepingN
yes.
F G= grandparent'7-rob+.
@ote the recursie definition of ancestor. ,ogically the interpretation is
'7-0+'ancestor'7-0+ parent'7-0++

'7-0+'ancestor'7-0+ ''?+'parent'7-?+ ancestor'?-0+++


ie
'7-0+'ancestor'7-0+parent'7-0+ '?+'parent'7-?+ ancestor'?-0+++
or- moing all 1uantification to the front-
'7-0-?+'ancestor'7-0+'parent'7-0+ 'parent'7-?+ ancestor'?-0+++
which is easier to read.
#perationally- if we enter a 1uery ancestor'fred->ames+- the interpreter first tries to satisfy
parent'fred->ames+- and to do this it first tries to satisfy mother'fred->ames+ and then
father'fred->ames+ which succeeds causing parent'fred->ames+ and then ancestor'fred->ames+
O
to succeed. "f we enter a 1uery ancestor'>ill-petra+ it tries to satisfy parent'>ill-petra+ as
indicated aboe and- when this fails- tries the other rule for ancestor. Thus it tries to satisfy
parent'>ill-?+ using mother'>ill-?+- which can be done with ?Iroberta. "t then tries to satisfy
ancestor'roberta-petra+. To do this it first tries parent'roberta-petra+ which fails- as both
mother'roberta-petra+ and father'roberta-petra+ fail. "t then tries the other definition for
ancestor. "t tries parent'roberta-?+ but finds no occurences of either mother or father with
roberta as first argument. ancestor'roberta-petra+ then fails- and it backtracks to
mother'>ill-?+. There is no other mother for >ill- and so it tries the other possibility for
parent'>ill-?+ ie father'>ill-?+. This succeeds with ?Ire6- and it tries to satisfy
ancestor're6-petra+. parent're6-petra+ fails so it tries the second definition for ancestor.
parent're6-?+ succeeds with ?Iharry- so it goes on to ancestor'harry-petra+. This time
parent'harry-petra+ succeeds as mother'harry-petra+ does- so ancestor'>ill-petra+ succeeds.
The se1uence of calls were as follows 'as indicated by trace+ where " hae added the
indentation to improe readability. @ote that each +all is matched with a ,ail or an -xit 'a
success+ = .ac/ to corresponds to another attempt to satisfy a predicate that has been
preiously attempted- but failed.
'(+ ( Call% ancestor'>ill-petra+ G
'4+ 4 Call% parent'>ill-petra+
'A+ A Call% mother'>ill-petra+ G
'A+ A &ail% mother'>ill-petra+
'*+ * Call% father'>ill-petra+ G
'*+ * &ail% father'>ill-petra+
'4+ 4 &ail% parent'>ill-petra+
'K+ K Call% parent'>ill-;LKLAO+ G
'L+ L Call% mother'>ill-;LKLAO+ G
'L+ L 36it% mother'>ill-roberta+
'K+ K 36it% parent'>ill-roberta+
'O+ K Call% ancestor'roberta-petra+ G
':+ L Call% parent'roberta-petra+ G
')+ O Call% mother'roberta-petra+ G
')+ O &ail% mother'roberta-petra+
'(/+ : Call% father'roberta-petra+ G
'(/+ : &ail% father'roberta-petra+
':+ L &ail% parent'roberta-petra+
'((+ ) Call% parent'roberta-;LKLLL+ G
'(4+ (/ Call% mother'roberta-;LKLLL+ G
'(4+ (/ &ail% mother'roberta-;LKLLL+
'(A+ (( Call% father'roberta-;LKLLL+ G
'(A+ (( &ail% father'roberta-;LKLLL+
'((+ ) &ail% parent'roberta-;LKLLL+
'O+ K <ack to% ancestor'roberta-petra+ G
'O+ K &ail% ancestor'roberta-petra+
'L+ L <ack to% mother'>ill-;LKLAO+ G
'L+ L &ail% mother'>ill-;LKLAO+
'(*+ (4 Call% father'>ill-;LKLAO+ G
'(*+ (4 36it% father'>ill-re6+
:
'K+ K 36it% parent'>ill-re6+
'(K+ K Call% ancestor're6-petra+ G
'(L+ L Call% parent're6-petra+ G
'(O+ O Call% mother're6-petra+ G
'(O+ O &ail% mother're6-petra+
'(:+ : Call% father're6-petra+ G
'(:+ : &ail% father're6-petra+
'(L+ L &ail% parent're6-petra+
'()+ ) Call% parent're6-;LKLLL+ G
'4/+ (/ Call% mother're6-;LKLLL+ G
'4/+ (/ &ail% mother're6-;LKLLL+
'4(+ (( Call% father're6-;LKLLL+ G
'4(+ (( 36it% father're6-harry+
'()+ ) 36it% parent're6-harry+
'44+ ) Call% ancestor'harry-petra+ G
'4A+ (/ Call% parent'harry-petra+ G
'4*+ (( Call% mother'harry-petra+ G
'4*+ (( 36it% mother'harry-petra+
'4A+ (/ 36it% parent'harry-petra+
'44+ ) 36it% ancestor'harry-petra+
'(K+ K 36it% ancestor're6-petra+
'(+ ( 36it% ancestor'>ill-petra+
$ fuller account of debugging is gien in the manual.
1.0. $ore exercises
(+ Set up a family knowledge base with facts
male'fred+.
male'>ames+.
female '>ill+.
female 'flo+.
parent'fred->ames+.
parent'fred->ill+.
parent'flo->ames+.
and rule
father'7-0+male'0+-parent'7-0+.
Make up a few more rules reflecting other family relationship nomenclature- eg
greatgrandparent- uncle- aunt- sister- 1rother and si1ling . Try arious 1ueries on this
knowledge base. Try using trace before entering a 1uery to see the effect of the 1uery 'press
83T58@ wheneer you get the G prompt when tracing = you could try some of the other
trace features in the manual+.
4+ Consider the following diagram.
)
D
C
B
A
E
F
G
H
I
a+ 8epresent in !rolog the facts describing the relationships between the named blocks. 5se
two predicates% a1o)e1 which says that a block is immediately aboe another and
1aseleft1 which says that a block is immediately to the left of another. #nly gie facts
of the second type for blocks which are at the bottom of stacks.
b+ Write another predicate a1o)e which is true wheneer its first argument is a block
anywhere in a stack aboe the block gien in the second argument.
c+ Write another predicate stac/left1 when a block is in a stack which is immediately to the
left of the second block.
d+ Write predicates 1aseleft and stac/left with the same meaning as 1aseleft1 and stac/left1
e6cept that the first block can be any number of blocks to the left of the second block.
e+ Try a few 1ueries.
A+ Try some other e6ercises from a !rolog book.
*+ ,ook at Programming -xamples in the Sicstus manual web page.
To lea)e a Prolog session type +2NT32L d.
(/
2. Week 2
2.1. $ulticondition 4ueries
"f in the preious e6ample family knowledge base of Week ( we wished to know about
greatgrandparents- we could use a multicondition 1uery%
F G= parent'7-?+-grandparent'?-0+.
and this would gie us all triples 7-0-? which satisfy both predicate e6pressions. Similarly
F G= parent'flo-?+-grandparent'?-0+.
would gie us all the ?-0 pairs satisfying both predicate e6pressions.
$ny alid body of a clause is a alid 1uery. Such a 1uery could be used to define a
predicate%
greatgrandparent'7-0+ %= parent'7-?+-grandparent'?-0+.
2.2. 2rder
2.2.1. 2rder of facts 5ith the same predicate name
We saw from the family e6ample that the !rolog system gies the answers in the order that
they were written in the file. Thus with
father'fred->ames+.
father'flo->ames+.
and the 1uery father'7->ames+ we are gien the solutions in the order fred- flo. This normally
will not matter as in most cases we wish to find all possible solutions.
2.2.2. 2rder of rules 5ith the same head
Similarly- gien rules
parent'7-0+ %= mother'7-0+.
parent'7-0+ %= father'7-0+.
and the 1uery parent'fred-7+- we get the solutions in the order >ill- >ames because it first
satisfies parent'fred-7+ using mother'fred-7+- and then using father'fred-7+. "n this case it
does not matter as we wish all parents. "n some cases it simply changes the amount of work
that needs to be done by the system. This is not considered good programming practice and
should be aoided if possible.
2.2.3. 2rder of predicate expressions inside a 4uery
The order of predicates e6pressions in a 1uery has the operational interpretation of
se1uencing% Bsatisfy the first and then satisfy the secondB. This can hae unfortunate effects
in the search for a solution. While in the logical reading the order does not matter- in
practice the search can be made more efficient by a suitable ordering of the atoms. $ general
rule is situate those prediates with fewer soluitons to the left.
2.3. Lists
2.3.1. +onstant lists and simple 4ueries.
!rolog proides for handling linked lists. These are denoted in !rolog using 's1uare+
brackets with commas separating the indiidual elements in the list- eg%
Dmonday-tuesday-wednesday-thursday-friday-saturday-sundayE
Thus we might hae the following facts
5ee/days 'Dmonday-tuesday-wednesday-thursday-fridayE+.
((
5ee/end 'Dsaturday-sundayE+.
Consider the following !rolog session
F G= 5ee/days 'D+.
D I Dmonday-tuesday-wednesday-thursday-fridayE J
no
F G= 5ee/end '7+.
7 I Dsaturday-sundayE .
yes
F G= 5ee/end 'D7-0E+.
7 I saturday
0 I sunday J
no
F G= 5ee/end 'Dsaturday-7E+.
7 I sunday J
no
F G= 5ee/end 'Dsunday-saturdayE+.
no
F G= 5ee/end 'Dsaturday-sundayE+.
yes
F G= 5ee/end 'D7E+.
no
F G= 5ee/end 'D7-0-?E+.
no
Thus the 1uery succeeds if the argument in the 1uery can be unified 'ie matched+
appropriately with the argument in the fact. @ote that it is treated strictly as a list- and not a
set ie Dsaturday-sundayE Dsunday-saturdayE. Similarly- note that Da-aE DaE. @ote that D7-0E
will only match with lists of length 4- D7E will only match with lists of length (- 7 will match
with lists of any length.
(4
2.3.2. 6ead 7 Tail representation
$ list of one or more elements can be represented using D7F0E- where the bar ' F+ separates
the head and tail of the list. The bar can be put after any number of elements- and the name
put after it refers to the rest of the list from that point. DE denotes the empty list. Thus
F G= 5ee/days 'D7F0E+.
7 I monday
0 I Dtuesday-wednesday-thursday-fridayE J
no
F G= 5ee/days 'D7-0-?F WE+.
7 I monday
0 I tuesday
? I wednesday
W I Dthursday-fridayE J
no
F G= 5ee/end 'D7-0F WE+.
7 I saturday
0 I sunday
W I DE J
no
2.3.3. +ommon list predicates
Consider the following predicates
first'D7F,E-7+.
tail 'D7F,E-,+.
last'D7E-7+.
last'D0F,E-7+ %= last',-7+.
mem1er'7-D7F,E+.
mem1er'7-D0F,E+ %= mem1er'7-,+.
The first of these is e1uialent to Bfirst'0-7+ is true iff 0 has the form D7F,EB ie the head of the
list gien as the first argument is the same as the alue in the second argument. Thus it acts
as a deduction rule een though it is e6pressed as a fact. This relies on !rolog's unification
abilities- which are more e6tensie than those of other languages such as M, or Miranda. $
similar comment applies to the predicate tail . Thus%
F G= first'Da-b-cE-a+.
yes
(A
F G= first'Db-c-dE-a+.
no
F G= first'Da-b-cE-7+.
7 I a J
no
F G= first'DM-b-cE-a+.
M I a J
no
F G= first'DaF !E-a+.
! I ;/ J
no
F G= first'D7E-a+.
7 I a J
no
F G= first'7-a+.
7 I DaF ;LE J
no
F G= first'D7F,E-7+.
7 I ;/
, I ;( J
no
F G= first'D7F,E-0+.
7 I ;/
, I ;(
0 I ;/ J
no
(*
Thus !rolog tries to unify the first argument with the D7F,E and the second with 7. "n the
first e6ample it was able to do this with 7Ia- and ,IDb-cE. "n the second there was no way to
do it. "n all other cases there was only one way in which it could do this. "n some of these
the list is not fully bound to a constant- but ariables such as ;/- ;L are inoled. "gnore the
numbers in these = they are actually meaningless- e6cept where they indicate that two alues
are the same. The third last e6ample shows that it can be done- if 7 is a list with a at the head-
with any tail. The second last says again that it can be done if 7-, were instantiated to
anything 'though , would hae to be a list = this is not indicated+. "n the last the solution
says it can be done if 7 and 0 hae the same alue.
The tail predicate behaes similarly.
F G= tail 'DE-,+.
no
F G= tail 'DaE-,+.
, I DE J
F G= tail 'D7F aE-a+.
7 I ;/ J
F G= tail 'D7-b-cE-,+.
7 I ;/ , I Db-cE J
F G= tail 'D7-b-cE-Db-0E+.
7 I ;/ 0 I c J
F G= tail 'D7-b-cE-DbF0E+.
7 I ;/ 0 I DcE J
The aboe predicates were gien their definition as facts- the ne6t two are recursie
definitions- with one of them essentially a stopping rule.
last'D7E-7+.
last'D0F,E-7+ %= last',-7+.
mem1er'7-D7F,E+.
mem1er'7-D0F,E+ %= mem1er'7-,+.
#perationally they work by trying to match the arguments of the 1uery with the arguments
in the heads of the definition.
Consider two 1ueries- the first being last'DwE-w+- and the second last'!-w+. The first works as
follows% last'DwE-w+ can unify D7E with DwE by 7Iw which then fits the second argument as
well so the 1uery is satisfied. The 1uery last'!-w+ would use the first definition yielding
!IDwE. #n being re1uested to find other solutions- it would try the second rule- unifying
7Iw and 0-, temporarily with ariablesJ it would try to find these 0-, by satisfying the
1uery last',-7+ in the body of the rule. 7Iw already- so it tries to find an , so that last',-w+
succeeds. To do this it starts again with the first rule- satisfying it with ,IDwE. This gies a
second solution !ID;K-wE. The system will continue finding solutions with progressiely
longer lists with w in the final position- and ariables in the other positions.
The effect of the 1uery last'Da-b-cE-M+ can be seen from the following trace
F G= last'Da-b-cE-!+.
'(+ ( Call% last'Da-b-cE-;L+ G
'4+ 4 Call% last'Db-cE-;L+ G
'A+ A Call% last'DcE-;L+ G
'A+ A 36it% last'DcE-c+
'4+ 4 36it% last'Db-cE-c+
(K
'(+ ( 36it% last'Da-b-cE-c+
! I c J
'A+ A <ack to% last'DcE-;L+ G
'*+ 4 Call% last'DE-;L+ G
'*+ 4 &ail% last'DE-;L+
'A+ A &ail% last'DcE-;L+
'4+ 4 &ail% last'Db-cE-;L+
'(+ ( &ail% last'Da-b-cE-;L+
no
F G=
where "'e added the indentation for readability. Thus it works its way to the end of the list
using the recursie definition- until it satisfies the first clause of last- and then e6its with the
first solution. #n retrying- it starts where it stopped and tries the recursie definition again.
The call fails- which causes all the calls it was embedded in to fail.
@ote that both rules for last could hae been gien with the same head by writing the first as
last'D0F,E-7+ %= 7 8 0-, 8 DE.
where I is a built=in predicate that denotes e1uality. "n !rolog e1uality is syntatic so 7I0 is
understood as 7 unfies with 0. &or e6ample- Dc-7-bE I Dc-dF ,E by setting 7Id-,IDbE.
@ote that a 1uery mem1er'7-Da-b-cE+ will hae A solutions for 7 and the 1uery mem1er'7-
Da-b-a-a-a-cE+ will hae L solutions for 7. The 1uery mem1er'7-DE+ will simply fail as did
last'DE-7+. 8emember that 1ueries can be combined- so we can find the last weekday by
F G= 5ee/days 'D+-last'D-7+
2.3.4 2ther useful list predicates
Two lists can be appended by progressiely sticking the elements of the first onto the the
second 'using first- for e6ample+. "t is easier using the following- which takes adantage of
unification%
concatenate'DE-,-,+.
concatenate'D7F,(E-,4-D7F,AE+ %= concatenate',(-,4-,A+.
where the second rule reads as
Bif ,A is ,( concatenated onto ,4 then D7F,AE is D7F,(E concatenated onto ,4B.
The e6amples aboe showed that predicates could be used in seeral ways% with arious of
the arguments either bound to constants 'eg w- Da-b-cE+- completely unbound 'ie as a simple
ariable eg M+- gien as a structure with its parts unbound 'eg D7F,E+- or gien as a structure
with only some of its parts unbound 'eg Da-7-bF ,E+.
"f a predicate has been written properly- this will always be the case. This is usually easy if
we can get a strict logical interpretation to what we hae written. Consider concatenate- and
only the possibilities of completely bound or unbound. The following 'slightly abbreiated+
e6amples show what happens.
F G= concatenate'Da-bE-Dc-dE-Da-b-c-dE+.
yes
F G= concatenate'Da-bE-Dc-dE-,+.
, I Da-b-c-dE
F G= concatenate'Da-bE-,-Da-b-c-dE+.
(L
, I Dc-dE
F G= concatenate',-Dc-dE-Da-b-c-dE+.
, I Da-bE
F G= concatenate',-M-Da-b-cE+.
,IDE MIDa-b-cE J
,IDaE MIDb-cE J
,IDa-bE MIDcE J
,IDa-b-cE MIDE J
F G= concatenate',-Da-bE-M+.
,IDE MIDa-bE J
,ID;(E MID;(-a-bE J
,ID;(-;4E MID;(-;4-a-bE
etc till we tell it to stop
F G= concatenate'Da-bE-,-M+.
,I;/ MIDa-bF ;/E
F G= concatenate',-M-@+.
,IDE MI;( @I ;( J
,ID;:E MI;( @ID;:F ;(E
etc till we tell it to stop
"t will also work with some of its arguments partially bound- eg concatenate'Da-7E-DbF ,E-
D0-c-W-d-7E+ will be satisfied with 7Ic- 0Ia- WIb- ,IDd-cE. This ability to use properly
written predicates in many ways makes logic programming powerful = you do not hae to
write lots of separate functions.
2.4. Lists of lists
We can hae hae lists embedded in lists. These can be dealt with similarly. Thus we could
define deepmem1er'7-,+ to mean that 7 is an element of , or one of its sublists by
deepmem1er'7-D0F,E+ %= 7I0.
deepmem1er'7-D0F,E+ %= deepmem1er'7-0+.
deepmem1er'7-D0F,E+ %= deepmem1er'7-,+.
@ote that deepmem1er'7-DDa-bE-DDc-DdEE-eE+ has as solutions all of
Da-bE-a-b-DDc-DdEE-eE-Dc-DdEE-c-DdE-d-e
as- for e6ample- Da-bE is an element of the original list. "f we only wanted indiidual items
then we would also hae to specify that 7 was not a list- ie that it did not hae the form D?F
WE- as we shall see later this is not the same as saying that it is an atom. Thus we might hae
deepatommem1er'7-M+ %= deepmem1er'7-M+- 9 : 78D?F WE.
where PQ 7I0 means 7 not e4ual to 0. $s e1uality in !rolog is syntatic- 9 : 780 means that
the term 7 does not unify 5ith the term 0. 'There will be more on negation later.+
We could substitute in the definition of deepmem1er to obtain
deepatommem1er'7-D7F,E+%=7I0.
deepatommem1er'7-D0F,E+ %=deepmem1er'7-0+.
deepatommem1er'7-D0F,E+ %=deepmem1er'7-,++- PQ 7ID?F WE.
This still contains calls to deepmem1er- and we might like to remoe these so that
deepatommem1er recurses only on itself. "t then becomes
deepatommem1er'7-D0F,E+ %= 7I0.
(O
deepatommem1er'7-D0F,E+ %= deepatommem1er'7-0+.
deepatommem1er'7-D0F,E+ %= deepatommem1er'7-,++- PQ 7ID?F WE.
The 1uery deepatommem1er'7-DDa-bE-DDc-DdEE-eE+ has solutions a-b-c-d-e.
2.. "ets as lists
We noted that mem1er'7-Da-b-a-a-a-c-a-b-bE+ would hae solutions a-b-a-a-a-c-a-b-b.
Sometimes we only wish to obtain uni1ue solutions eg a-b-c in this case. $ useful 1uilt-in
'system+ predicate for this is setof . The 1uery
setof '7-mem1er'7-Da-b-a-a-a-c-a-b-bE+-,+
would be satisfied with ,IDa-b-cE. Thus setof has A arguments- with the second being a
predicate e6pression. Similarly
F G= setof '7-deepmem1er'7-DDa-bE-DDc-DdEE-eE+-,+.
, I DDa-bE-a-b-DDc-DdEE-eE-Dc-DdEE-c-DdE-d-eE
F G= setof '7-deepatommem1er'7-DDa-bE-DDc-DdEE-eE+-,+.
, I Da-b-c-d-eE
F G= setof '7-deepatommem1er'7-DDa-bE-DDc-DbEE-aE+-,+.
, I Da-b-cE
F G= setof 'D,-ME-concatenate',-M-Da-b-cE+-.+.
. I DDDE-Da-b-cEE-DDaE-Db-cEE-DDa-bE-DcEE-DDa-b-cE-DEEE.
"t should be noted that the BresultB is still represented as a list howeer. Sometimes we do
want all alues that satisfy some predicate- duplicates included. The 1agof built=in predicate
does >ust this%
F G= 1agof '7-deepatommem1er'7-DDa-bE-DDc-DbEE-aE+-,+.
, I Da-b-c-b-aE
2.0. $ixing List Predicates
"n defining predicates we can use other predicates. Thus
su1set 'DE-,+.
su1set 'D7F ME-@+ %= mem1er'7-@+-su1set 'M-@+.
though this doesn't test whether things are actually sets rather than lists.
<elow we gie two ersions of a reersing predicate- the first of which is simple but slow-
and the second of which makes use of another predicate with e6tra parameter.
nai)e3e)erse 'DE-DE+.
nai)e3e)erse 'D7F,E-M+ %= nai)e3e)erse ',-@+-concatenate'@-D7E-M+.
re)erse',-M+ %= re)erse;',-DE-M+.
re)erse;'DE-0-0+.
re)erse;'D7F,E-0-M+ %= re)erse;',-D7F0E-M+.
2.<. Practical 2
(+ Write a predicate flatten so that flatten'7-0+ is true when 0 is the list containing all
the atomic elements of 7 in the sense that flatten'DDa-bE-DDc-DdEE-eEE-Da-b-c-d-eE+ is true. What
happens to the 1uery flatten'7-Da-b-cE+G
4+ Write a predicate su1st with four arguments so that su1st '6-y-D6-DR-6EE-M+ is satisfied
with MIDy-DR-yEE. What happens with the 1uery su1st '6-y-M-Dy-DR-yEE+G With su1st 'M-@-D6-
(:
DR-6EE-Dy-DR-yEE+G What other uses can be made of such a predicateG Modify the predicate so
that su1st '6-y-6-M+ is also satisfied with MIy.
A+ Write a predicate delete with A arguments so that delete'7-0-?+ is true when ? is the
same as 0 with all occurences of 7 remoed- eg delete'a-D6-Da-b-DaEE-cE-D6-Db-DEE-cE+ is true.
$gain inestigate what happens with arious combinations of the arguments bound and
unbound.
*+ Write a predicate su1se4uence with two list arguments which is true when the
elements in the first list occur in that order in the second list eg su1se4uence 'Da-b-cE-
Dd-a-6-y-b-g-cE+ is true.
K+ Write a predicate denil with two arguments so that denil 'Da-DDE-b-DDEEE-cE-M+ is
satisfied with MIDa-DbE-cE.
O+ Write a predicate =ipped with three arguments so that =ipped 'Da-b-cE-D6-y-RE-M+ is
satisfied with MIDDa-6E-Db-yE-Dc-REE. Set it to do something sensible if the first two arguments
are of different length. What happens if the arguments in the 1uery are not
bound-bound-unbound in that order = e6periment a bitG
:+ Write a predicate tail,rom with three arguments- so that tail,rom'$-7s-0s+ is true
when 0s is the list starting from the first occurrence of $ in 7s- containing $ and all the
subse1uent elements- eg tail,rom'a-Db-c-a-c-a-dE-Da-c-a-dE+ is true- and tail,rom'a-Db-c-a-c-a-dE-
Da-dE+ is false.
)+ Try a few more e6amples from the Sicstus !rolog Manual !rogramming 36amples.
()
3. Week 3
3.1. %sing "tructures
3.1.1. "tructures as trees
The data structures are the terms used in logic. These are implemnted with recursie data
structures 'trees+. The facts we used in earlier e6amples were fairly simple ones such as
father'fred->ames+. @ote that a list D7F,E is regarded as a dotted pair ie in predicate form .
'7-,+- and hence that a list such as Da-b-cE would be .'a-.'b-.'c.DE+++.
$n e6ample from <ratko 'another not so good book on !rolog and $"+ gies information
about a family in the form
family'person'tom-fo6-date'O-may-()K/+-works'bbc-(K4//++-
person'ann-fo6-date')-may-()K(+-works'ici-(OK//++-
D person'pat-fo6-date'K-may-()OA+-unemployed+-
person'>im-fo6-date'K-may-()OA+-unemployed+ E +.
"f each predicate name becomes the root of a subtree- then the whole structure can be
thought of as haing the following tree structure.
fami l y
person
.
tom fox date
works
person
anne fox date

may
!"#$ bbc!#%$$
"
may
!"#!
works
i ci !#$$
person
pat fox date
#
may
!"&
'nempl oyed
.
person
j i m fox date
#
may
!"&
()
'nempl oyed
3.1.2. >nonymous Terms
Sometimes we wish to find the alues of only some arguments of a predicate- or general
structure- ie we don't care what alues the other arguments hae. To indicate this we use the
anonymous ariable ; rather than find another name. This anonymous ariable matches
anything- and if more than one appears in an e6pression they may match different alues.
$ssume that we hae a database of facts about families such as the aboe- and add the
following rules%
hus1and'7+ %= family'7-;-;+.
5ife '7+ %= family';-7-;+.
child'7+ %= family';-;-Children+- mem1er'7-Children+.
4/
ali)e'7+ %= hus1and'7+
ali)e'7+ %= 5ife '7+
ali)e'7+ %= child'7+.
dateof1irth'person';-;-Date-;+-Date+.
salary'person';-;-;-works';-S++-S+.
salary'person';-;-;-unemployed-/+.
When 1ueries are entered the system tries to match structures- with ; matching anything.
Thus the 1uery 5ife 'person'@ame-fo6-;-Tob++ would try to satisfy
family';-person'@ame-fo6-;-Tob+-;+. This structure looks like
fami l y
*
person
name
fox
j ob
*
*
and thus is matched with @ameIann and TobIworks'ici-(OK//+. To get the names of all
people in the database we could do
F G= ali)e'person'@-M-;-;++.
which would return solutions one at a time. To get all children born in ():( we would do
F G= child'7+-dateof1irth'7-date';-;-():(++.
$ll unemployed people born before ()LA
F G= ali)e'person'@-M-date';-;-0+-unemployed++-0?()LA.
The predicate M is built=in and is used infi6 'more on this later+. $ll people born before ()K/
whose salary is less than )///
F G= ali)e'!+-dateof1irth'!-date';-;-0++-0?()K/-salary'!-S+-SM)///.
Surnames of fathers with at least A children
F G= family'person';-@-;-;+-;-D;-;-;F ;E+.
3..3. 3estricting num1er of arguments
"n the aboe we asked for the names of all people using ali)e'person'@-M-;-;++ and respond
with a semi=colon to the interpreter until we had all the names we re1uired. We might think
instead to simply ask for the setof of all @-M pairs satisfying the aboe using something like
setof 'D@-ME-alie'person'@-M-;-;++-,+ W8#@S = W8#@S = W8#@S
To see what this does let's try a smaller e6ample with setof . Consider the following database
li/es 'tom-beer+.
li/es 'dick-beer+.
li/es 'harry-beer+.
li/es 'april-whisky+.
li/es 'may-whisky+.
li/es '>une-whisky+.
4(
and the following !rolog session
F G= setof '7-likes'7-0+-,+.
7 I ;/
0 I beer
, I Ddick-harry-tomE J
7 I ;/
0 I whisky
, I Dapril->une-mayE J
no
F G= setof '7-likes'7-;+-,+.
7 I ;/
, I Ddick-harry-tomE J
7 I ;/
, I Dapril->une-mayE J
"gnore the 7I lines as they are irreleant. @ote that the first 1uery satisfies the setof twice-
once for each alue of 0. The setof 1uery with anonymous ariable is e1uialent to this = it
>ust doesn't print the 0I line. The way to find the set of all people who like something is as
follows
F G= setof '7-0Ulikes'7-0+-,+.
7 I ;/
0 I ;(
, I Dapril-dick-harry->une-may-tomE J
"f you wanted the set of all 0s- each with the corresponding set of 7s you would do
something like
F G= setof ''0-S+-setof '7-likes'7-0+-S+-SS+.
0 I ;/
S I ;(
7 I ;L
SS I D'beer-Ddick-harry-tomE+-'whisky-Dapril->une-mayE+E J
Thus to get a list of name-surname pairs for <ratko's family e6ample we do
F G= setof 'D@-ME-7U0Ualie'person'@-M-7-0++-,+.
which is to be read as B, is the list of all D@-ME such that there e6ists 7-0 with
ali)e'person'@-M-7-0++B where implicitly the 7-0 may depend on @-M. The U functor is
only used inside setof and bagof.
3.2. 2perator notation
"n ordinary arithmetic we use infi6 notation and operator precedence to understand that
4QA2* means '4Q'A2*++ ie (* rather than '4QA+2* ie 4/. We also know that O=*=4 means 'O=*+=4
rather than O='*=4+ ie we work left to right for operators of e1ual precedence. !rolog
arithmetic follows this standard usage. Such e6pressions should be thought of as structures
or trees- eg 4QA2* is Q'4-2'A-*++ ie
44
Q
4
2
A
*
Thus we wish O=*=4 to stand for the structure ='='O-*+-4+ ie the tree
=
4
=
O
*
$toms always hae precedence /- and a smaller number denotes higher precedence.
#perators must be defined to be one of the following forms.
infi6 operators of three types% 6f6- 6fy- yf6
prefi6 operators of two types% f6- fy
postfi6 operators of two types% 6f- yf
To achiee the appropriate calculations the arithmetic operators in !rolog hae the
precedence etc of
%= op'O//-6f6-DI-is-M-N etcE+.
%= op'K//-yf6-DQ-=E+.
%= op'K//-f6-DQ-=E+.
%= op'*//-yf6-D2-9E+.
With these definitions =L9A= *2OQ(4 is calculated as '''='L9A++='*2O++Q(4+ and has the structure
Q'='='9'L-A++-2'*-O++-(4+. This has tree form
4A
Q
(4
=
=
*
9
A
2
L
O
Within an e6pression the principal functor is the operator with largest precedence eg 'Q' in
the aboe. The operators with the smallest alue bind the strongest eg '2' in the aboe. "n a
specifier the 6 indicates that the argument on that side must hae a lower precedence than
the operator- and the y indicates that the argument must hae precedence less than or e1ual
than the operator. Thus with op'K//-yf6-'='+ the first argument of '=' must hae a precedence
no more than K// and the second argument must hae precedence less than K//. The tree
aboe corresponds to the precedence structure%
yK//6
/
yK//6
yK//6 y*//6
/
/
/
/
y*//6
!recendence can be applied to predicates as well as functors. Consider the following
program
%= op'4//-6fy-and+.
%= op'(K/-f6-the+.
4*
%= op'A//-6f6-supports+.
the table supports the ase.
the floor supports the chair and the table and the lamp.
the chair supports fred.
The structures corresponding to these last three statements are
supports'the'table+-the'ase++
supports'the'floor+-and'the'chair+-and'the'table+-the'lamp++++
supports'the'chair+-fred+
We can now 1ueries like
F G= What supports fred.
What I the chair
F G= the floor supports What.
What I the chair and table and the lamp
3.3. >rithmetic
3.3.1. Introduction
While natural number arithmetic can be done with the !eano term representation- for large
numbers it is inefficient. !rolog proides built=ins to handle arithmentic in the usual
postional representation.
3.3.2. +omparisons
@umbers can be compared with built=in comparison operators. Thus we could define a
predicate positi)e by%
positi)e '7+ %= 7 @ /.
so that positi)e 'A+ is true- and positi)e '=)+ is false. #ur preious comments and e6ercises
hae led us to ask what happens if we use the 1uery positi)e '7+ with 7 unbound = maybe it
will generate all 7 such that the 1uery is true. <ut no. @ow we hae problems- because some
!rologs gie an error message and some like Sicstus >ust say no.
The buit=in arithmetic predicates are normally used in infi6 form. They include @- ?- @8 and
8? 'see the manual for more+. @ote the following%
F G= AIA.
yes
F G= AI:.
no
F G= AI0.
0 I A
F G= AQ4I:=A.
no
ie e1uality carries out an e1uality check of two numbers but not the alue of two
e6pressions. "f necessary it will satisfy the 1uery with a simple BassignmentB.
3.1.3. >ssignment
Syntatic e1uality can do a form of assignment- but
F G= 0I4QA.
0 I 4QA
4K
in which case 0 is unified with the e6pression 4QA and not its alue. To unify it with the
alue we use the buit=in predicate is%
F G= 0 is 4QA.
0 I K
We can hae general arithmetic e6pressions on the right hand side of the is. @ote that is is
also a predicate of which is satisfied when the left hand side is e1ual to the alue of the right
hand side- ie the first thing it does is try to ealuate the right hand side- which must
therefore be ealuable in arithmetic. Thus
F G= 0 is AQ42:.
0 I ().
F G= AQ4 is 7.
no
We can use arithmetic in other predicates eg%
len'DE-/+.
len'D7F,E-0+ %= len',-@+- 0 is @Q(.
add-m'DE-/+.
add-m'D7F,E-M+ %= addem',-@+- M is 7Q@.
max'7-0-?+ %= 7 @8 0- ? is 7.
max'7-0-?+ %= 7 ? 0- ? is 0.
3.2. .ound and un1ound )aria1les - )ar 7 non)ar
We noted aboe that 7 is 0Q? only works if it is being used with 0 and ? already bound.
<ut we know how to sole KI0QA- why doesn't !rologG The answer is that that e6ample is
simple- but a lot of arithmetic e6pressions are harder to reerse eg L.4K I 727. "f we want
arithmetic predicates to work all ways we hae to program them ourseles to cope with
arious combinations of bound and unbound ariables. $ccordingly there are two built=in
predicates which test whether a ariable is unbound or bound = called )ar and no)ar.
Consider the e6ample ? is 7Q0. There are * easy cases = when all are bound 'that's >ust an
e1uality check+- when 0-7 are bound 'a simple addition+- and when ? and either 0 or 7 are
bound 'a simple subtraction+. So%
add'7-0-?+ %= non)ar'7+-non)ar'0+-non)ar'?+- S is 7Q0- ?8S.
add'7-0-?+ %= )ar'7+-non)ar'0+-non)ar'?+- 7 is ?=0.
add'7-0-?+ %= non)ar'7+-)ar'0+-non)ar'?+- 0 is ?=7.
add'7-0-?+ %= non)ar'7+-non)ar'0+-)ar'?+- ? is 7Q0.
3.3. 2ther term chec/s
Tust as ar and nonar test to see whether a term is unbound or bound- the predicate integer
is true if its argument is bound to an integer. The predicate atom is true if its argument is
bound to an atom 'ie not a list or number+- and the predicate atomic is true if its argument is
bound to either an atom or a number.
3.4.1. +onstructing and decomposing terms - uni)
"t is useful to be able to interchange between list and structure representations. This can be
done using the 8.. built=in predicate 'called uni)+. This is defined as an infi6 predicate- and
7 8.. 0 is true when 7 is the structure corresponding to the list 0. Thus%
F G= f'a-b+ 8.. ,.
, I Df-a-bE
F G= T 8.. Drectangle-A-KE.
4L
T I rectangle'A-K+
F G= ? 8.. Dp-7-f'7-0+E
? I p'7-f'7-0++
This is useful when we hae such structures as representations for data ob>ects in a program.
"t is also useful for writing general purpose predicates for altering facts about different
structures. Consider a program which contains information about geometric ob>ects with
predicates s1uare'Side+- rectangle'Side(-Side4+- circle'8+. Suppose we wish to hae a general
purpose enlargement predicate to increase the siRe of any ob>ect- so we need to be able to
multiply the single argument of a s1uare or circle by some appropriate factor &- but also
multiply both arguments of a rectangle etc. Thus gien any shape Type'7(-...-7n+ we need to
be able to multiply all of 7(-...7n and hae this work for any such Type. We want to be able
to say enlarge'Type'7(-...-7n+-&-Type'0(-...0n++- but we can neither hae such a dotted list in
!rolog 'of indefinite length+- nor can the predicate name Type be a ariable. "nstead we use
I.. as follows%
enlarge'&ig-&-&ig(+ %= &ig I.. DTF !E- multiplyList '!-&-!(+- &ig( 8.. DTF !(E.
multiplyList 'DE-;-DE+.
multiplyList 'D7F,E-&-D0F ME+ %= 0 is 72&-multiplyList ',-&-M+.
ie we first conert &ig to a list- do the multiplication across the members of the list
corresponding to the parameters- and then conert back to a structure. We could then say
enlarge'circle'7+-A-circle'0++ if 7 were already bound- and 0 would be bound to A27- or
enlarge'&red-Scale-&reda+ if &red were known to be a figure of some sort and &reda was to be
the rescaled ersion.
5ni is also useful if we need to create higher leel predicates- or otherwise manipulate
predicates before satisfying them. We may wish to apply positi)e to all members of a list in
one situation and apply negati)e to them in another. We could program these separately by%
allpositi)e 'DE+.
allpositi)e 'D7F,E+ %= positi)e '7+-allpositi)e ',+.
allnegati)e 'DE+.
allnegati)e 'D7F,E+ %= negati)e '7+-allnegati)e ',+.
but these predicate definitions hae the same form. "n each case we are running a single
argument predicate across the list until it fails. "t is possible to define
allpositi)e ',+ %= mapList',-positie+.
allnegati)e ',+ %= mapList',-negatie+.
with appliesTo-ach suitably defined. This can be done as follows%
mapList'DE-!red+.
mapList'D7F,E-!red+ %= Soal 8.. D!red-7E- !oal - mapList',-!red+.
"f we then say mapList'D4-*-AE-positie+- Soal is first set to positi)e '4+ by the uni- this goal is
tested and if true &un is applied to the rest of the list. "n some ersions of !rolog the simple
BSoal-B would hae to be replaced with the built=in call 'Soal+.
3.4.2. -xtracting parts of structures.
Sien a structure f'7-0-...@+ the f is referred to as the functor and the 7-0-...@ as the
arguments. The following two predicates are proided% functor'Term-&-@+ is true if & is the
principal functor of Term and @ is its arity ie number of arguments- arg'@-Term-$+ is true if
$ is the @th argument of Term. Thus%
F G= functor't'f'7+-7-t+-&un-$rity+.
&un I t
$rity I A
4O
F G= arg'4-f'7-t'a+-t'b++-0+.
0 I t'a+
F G= functor'D-date-A+-arg'(-D-4)+-arg'4-D->une+- arg'A-D-():4+.
D I date'4)->une-():4+
&unctor will only work with the following combinations of bound and unbound arguments%
<-5-5 V 5-<-< V <-<-<. This neer causes any problems.
3.. ;ecomposing and creating atoms.
The predicates functor- arg V I.. allow us to manipulate compound terms ie structures.
Similarly seeral modern languages proide facilities to e6plode or implode atomic names =
ie to go between an atomic name and its indiidual characters. "n !rolog only one predicate
is proided but it can be used either way. @ote that rather than dealing with indiidual
characters it deals with their ascii code
F G= name'fred-,+.
, I D(/4-((*-(/(-(//E
F G= name'S-D):-)O-)LE+.
S I baW
3.0. Practical 3
(+ Write a predicate times-m which multiplies a list of numbers.
4+ 5se )ar and non)ar to make the re)erse predicate work both ways- ie with the
arguments bound-unbound V also unbound-bound.
A+ Consider the following program%
%= op'A//-6f6-plays+.
%= op'4//-6fy-and+.
>immy plays football and s1uash.
susan plays s1uash and tennis and basketball.
>o plays tennis.
Define new operators plays2nly so that 7 plays2nly 0 is true when person 7 plays only
one game- plays>ll2f so that 7 plays>ll2f 0 is true when 0 contains more than one game.
Define an operator is2ne2f so that 7 is2ne2f 0 is true is 0 is either a single game of a list
of games separated with ands and 7 is either that single game or one of the listof games.
Define a new operator playsThe!ame so that 7 playsTheSame 0 is true when 0 is one of
the games 'or the only game+ that 7 plays.
*+ Suggest appropriate definitions of the operators ' 5as'- 'of'- 'the'- 'and' to be able to
write clauses like Bpam 5as the secretary and the lifeblood of the departmentB. Test these
with arious sentences and 1ueries.
K+ Define appliesTo-ach2 with three arguments so that the appliesTo-ach2',-&un-M+
is true if ,un'7-0+ is true for 7-0 in the corresponding positions in ,-M for all such positions
eg appliesTo-ach2'D4-L-*-KE-add(-DA-O-K-LE+ is true where add( has the obious meaning.
L+ Define the predicate add1s with two arguments so that add1s'7s-0s+ is true when 0s
is the list of numbers corresponding to the list 7s of numbers but with ( added to each of
them- eg add1s'D(-*E-D4-KE+ is true.
O+ Define the predicate positions with three arguments so that positions '$-7s-"s+ is
true when "s is the list of positions of $ in the list 7s- eg positions 'a-Db-a-a-bE-D4-AE+ is true.
:+ Define the predicate firstPosition with three arguments so that firstPosition'$-7s-"+
is true when " is the first position of $ in the list 7s- eg firstPosition'a-Db-a-a-bE-4+ is true.
4:
)+ Define the predicate ta/es with three arguments so that ta/es'@-7s-0s+ is true when
0s is the list of the first @ elements in the list 7s- eg ta/es*A-Db-a-a-bE-Db-a-aE+ is true.
(/+ Define the predicate drops with three arguments so that drops'@-7s-0s+ is true when
0s is the list of all elements in the list 7s- e6cept the first @- eg drops'A-Db-a-c-dE-DdE+ is true.
((+ Define the predicate ta/esAhile with three arguments so that ta/esAhile '!-7s-0s+
is true when 0s is the list of initial elements from the list 7s for which !'7+ is true- eg
ta/esAhile 'een-D*-L-A-*E-D*-LE+ is true.
(4+ Define the predicate dropsAhile with three arguments so that dropsAhile '!-7s-0s+
is true when 0s is the list of elements from the list 7s omitting the initial elements for which
!'7+ is true- eg dropsAhile 'een-D*-L-A-*E-DA-*E+ is true.
4)
4. Week 4
4.1. Types of e4uality
3arlier in the notes we introduced the matching e1uality operator 8 where 3(I34 was true
when the ariables in 3( and 34 could be matched to unify the two e6pressions eg%
F G= fred'a-7-g'0++8fred'?-b-g'ferd'c+++.
7 I b
0 I ferd'c+
? I a
F G= 784QA.
7 I 4QA
We noted that with arithmetic e6pressions the arithmetic e6pression was not ealuated. To
set 7 e1ual to the alue of 4QA we would hae to do
F G= 7 is 4QA.
7 I K
so this is assignment rather than an e1uality check. To do e1uality checks on the alue of
arithmetic e6pressions we use I%I for e1uality and IPI for ine1uality. Thus%
F G= KQ48B8(/=A.
yes
F G= KQ4898 )=A.
yes
Sometimes we want to test the literal e1uality of compound terms- without doing any
unification. This is done using II for e1uality and PII for ine1uality. Thus%
F G= f'a-b+ 88 f'a-b+.
yes
F G= f'a-7+ 88 f'a-b+.
no
F G= f'a-7+ 88 f'a-0+.
no
F G= 7 88 0.
no
F G= fred'7->o'b-0++ 88 fred'7->o'b-0++.
7 I ;4*
0 I ;K:
yes
F G= 7 9 88 0.
7 I ;(/
0 I ;A*
yes
where in the last two cases- the system is essentially saying = yes " can proe that using
anonymous ariables.
A/
4.2. Input
!rimitie character based input is aailable- but most input is done using read which e6pects
a !rolog term to be entered on the current input channel- and instantiates the single
argument of read to this.
F G= read'7+.
F % no.
7 I no
yes
F G= read'7+- 0 8.. 7.
F % Da-b-c-dE.
7 I Da-b-c-dE
0 I a'b-c-d+
@ote that the input prompt is BF% B. @ote also the period that the user types to indicate the
end of the input. @ote that the binding is lost when the 1uery finishes.
4.3. 2utput
So far we hae relied on the simple output of arible bindings accumulated by the
interpreter to gie us our answers. When we hae a longer program from which we wish to
output information at arious points- or when we want the output in a better layout- we will
use the printing facilities proided in !rolog.
There are primitie input and output predicates for single characters. There are also other
higher leel ones. The predicate 5rite sends to the current output stream its single
argument which must be a !rolog term 'ie a constant- a ariable or a compound term+. The
predicate nl produces a newline. "t is conenient to also hae a writeln predicate defined by
5riteln'DE+ %= nl .
5riteln'D7F,E+ %= 5rite'7+-5riteln',+.
and something to print a list of alues with a space between them.
gapAriteln'DE+ %= nl .
gapAriteln'D7F,E+ %= 5rite'7+-5rite'' '+-gapAriteln',+.
We could use these to neatly print the ancestors of someone in the family knowledge base-
thus%
pancestors'7+ %= setof '0-ancestor'7-0+-,+-
5riteln'D'The ancestors of '-7-' are %'E+- gapAriteln',+.
pancestors'7+ %= 5riteln'D7-' has no ancestors in the database.'E+.
which would be used as follows
F G= pancestors'flo+.
The ancestors of flo are %
harry henrietta >ames >erri peter petra rob rowena
yes
F G= pancestors'>erri+.
>erri has no ancestors in the database.
yes
@ote that nl and 5rite- and hence 5riteln and gapAriteln- will always succeed if their
arguments are bound. Two things should be noted about the pancestors predicate. "t will
always succeed = because either ancestors e6ist in which case the setof succeeds or ancestors
A(
don't e6ist in which case setof fails and the other clause is used. The order of the clauses is
important in that the second is used only when the first has failed.
4.4. +ontrolling 1ac/trac/ing - the cutC D
4.4.1. Introduction
$ programmer may wish to prune the backtracking search tree- for efficiency reasons. This
can be done e6plicitly using the cut- D. $ cut in a clause prunes all the clauses below it. $ cut
also prunes all alternatie solutions to the con>unction of goals which appear to the left of it.
"n this way it gies only one solution- the first to be found. "n>udicious use of the cut can
lead to unsound answers. "t should be used sparingly and only when you understand
precisely what it is doing.
The cut can be usefully used to e6tend definite clause logic to include a weak form of
negation. This is best achieed using the in=built meta= predicates.
4.4.2. Negation as failure
With the family database- if we wished to check whether >ames was @#T the father of fred-
or lucy- we would try
F G= father'fred->ames+.
yes
F G= father'lucy->ames+.
no
To reerse these answers we could define the meta= predicate not by
not ! %= !- X- fail.
not !.
where fail is a built=in 'but doesn't hae to be+ which always fails. Then
F G= not father'fred->ames+.
no
F G= not father'lucy->ames+.
yes
We might think that this seems correct- as the statement Cfather'fred->ames+ is indeed false-
because father'fred->ames+ is true. The second is gien as true. This is because- in our
knowledge base- it is not known whether >ames is the father of lucy. "t may well be that
>ames is the father of lucy- but we simply hae not recorded the fact. @egation in !rolog is
sometimes called negation by failure- ie not p is regarded as true if we fail to satisfy p. This
is sometimes known as the closed world assumption- as the answer is true simply for the
closed world represented by our knowledge base- and does not imply anything about the
world outside. negation is built=in to all !rologs. "n Sicstus !rolog it is represented by E:. "t
was used preiously in 9 : 780 to define deepmem1er'7-M+.
4.43. Negation 5ith )aria1les
9 : p'7+ will be false if p'7+ can be satisfied. Thus if p'7+ is true for some 7- 9 : p'7+ will be
false and the !rolog interpreter will return the answer no. "t is answering the 1uery C p'7+
and not the one you might hae intended C7p'7+. 9 : p'7+ will be true only if p'7+ is true
for no 7. Thus a 1uery 9 : p'7+ will not instantiate 7 to anything useful.
Consider the problem of finding all the ancestors of fred e6cept his parents. $ sufficient
1uery is
F G= ancestor'fred-7+- 9 : parent'fred-7+.
This will operate by finding an 7 satisfying ancestor'fred-7+- $@D TH3@ checking whether
9 : parent'fred-7+ is true for this 7. Thus the system tries to satisfy the predicate 9
:parent'fred-7+ only with 7 already bound to a alue. "t repeats this with eery ancestor of
A4
fred- as long as we keep responding with a semicolon. This will work and gie the correct
answers.
Consider the effect of
F G= 9 : parent'fred-7+ -ancestor'fred-7+.
This will try to satisfy parent'fred-7+ first which succeeds- hence 9 : parent'fred-7+ fails- and
hence the whole 1uery fails. "n this way !rolog does not allow a strictly logical reading = the
order of the predicate e6pressions matters.
$ general rule for including negations in 1ueries is that all their ariables should be
instantiated before they are reached.
4.4.4. 2rder of negations inside a 4uery
"n the Bnegation with ariablesB e6ample we saw that the order or predicate e6pressions in a
1uery had some effect- because the comma separating the predicate e6pressions has the
operational interpretation of se1uencing% Bsatisfy the first and then satisfy the secondB. "n a
pure 1uery with no negation and no sideeffects 'assignment- input and output+ and no other
meta= logical features 'coered later+ the order does @#T matter. Thus- in that case we
achiee the same result no matter what order the predicate e6pressions are in = ie the comma
has a strict logical interpretation same as a logical and.
4.4.. If..then..else
Consider the e6pression if p then (!) else (") where p is ery complicated- and maybe
contains side effects. We get that effect by
4'7+ %= p- X- 7I/.
4'(+.
"f p is not true then 4'(+ succeeds- 4'/+ fails and 4'7+ has the single solution 7I(. "f p is true
then 4'/+ succeeds- 4'(+ fails and 4'7+ has the single solution 7I/. This can be written using
the built=in if..then..else %
4'7+ %= p 7I/(7I(.
This in fact uses the infi6 meta= predicate ' (' which e6ploits the search order to imitate
dis>unction. This built=in could be defined by%
!(Q %= !.
!(Q %= Q.
4.. Fno5ledge .ase manipulation
&acts and rules in earlier e6amples were kept in files- where they remained between program
runs- and were aailable to a program through consulting those files. During a program run
or !rolog session arious ariables were bound to alues during predicate satisfaction- but
the alues were lost after the predicate finished- e6cept when passed through parameters.
#ne way to make alues remain more permanently would be to write them to files.
Howeer- sometimes we wish to retain alues only for all or part of the remainder of the
current session. The way to do this is to use the assert family of predicates. This not only
allows us to store facts such as father'fred->ames+ but also rules. "t is customary to refer to
the things in the files as the static knowledge base- and those kept only during one session as
the dynamic knowledge base. @ote that during a !rolog session the !rolog session
knowledge base contains the knowledge obtained from the files using consult Q the things
asserted during the session = the things BdeletedB during the session. The usual way to
BdeleteB knowledge during a session is using the retract predicate. @ote that this deletes
anything in the !rolog session knowledge base whateer its source- but does not delete
entries in the files themseles.
Consider the following small knowledge base
nice %= sunny- 9 : raining.
funny %= sunny-raining.
AA
horri1le %= raining-fog.
raining.
fog.
and the following !rolog session.
F G= nice.
no
F G= horri1le.
yes
F G= retract'fog+.
yes
F G= horri1le.
no
F G= assert'sunny+.
yes
F G= funny.
yes
F G= retract'raining+.
yes
F G= nice.
yes
Here we only asserted and retracted simple facts. $ fact such as father'tony->ohn+ is asserted
by assert'father'tony->ohn++. $ rule can be asserted as in the following e6ample%
assert''hae;same;child'7-0+ %= father'?-7+-mother'?-0+++. @ote that the rule has to be
wrapped in parentheses. @ote the following
F G= assert'first'D7F,E-7++.
7 I ;/
, I ;(
yes
F G= first'Da-b-c-dE-0+.
0 I a
ie facts with ariables in them can be asserted.
Sien the family knowledge base retract'father'7->ames++ would look for facts matching
father'7->ames+ and progressiely retract them until told to stop- thus%
F G= retract'father'7->ames++.
7 I fred J
7 I flo
yes
F G= retract'father'0-re6++.
0 I >ill
yes
@ote that assert puts the information somewhere in the knowledge base = but we are not
guaranteed anything about where the information actually is. The two predicates asserta-
A*
assertR specifically put the new knowledge at the start and end of the knowledge base
respectiely. Consider the following definition of a predicate to calculate fibonacci numbers
fi1'(-(+.
fi1'4-(+.
fi1'@-&+ %= @( is @=(- @4 is @=4- fi1'@(-&(+- fi1'@4-&4+- & is &(Q&4.
Consider the following partial trace%
'(+ ( Call% fi1'K-;/+ G
'*+ 4 Call% fi1'*-;L+ G
'O+ A Call% fi1'A-;(A+ G
'(/+ * Call% fi1'4-;4/+ G
'(/+ * 36it% fi1'4-(+
'((+ * Call% fi1'(-;4(+ G
'((+ * 36it% fi1'(-(+
'O+ A 36it% fi1'A-4+
'(A+ A Call% fi1'4-;(*+ G
'(A+ A 36it% fi1'4-(+
'*+ 4 36it% fi1'*-A+
'(K+ 4 Call% fi1'A-;O+ G
'(:+ A Call% fi1'4-;A(+ G
'(:+ A 36it% fi1'4-(+
'()+ A Call% fi1'(-;A4+ G
'()+ A 36it% fi1'(-(+
'(K+ 4 36it% fi1'A-4+
'(+ ( 36it% fi1'K-K+
& I K
yes
Thus -it has done all the calculations for fi1'A+ twice. The facts for fi1'4+ and fi1'(+ it only
had to e6tract from the knowledge base. The solution is to assert calculated information into
the knowledge base- by changing the last clause of the definition of fi1 to
fi1'@-&+ %= @(is@=(- @4is @=4-fi1'@(-&(+-fi1'@4-&4+-&is&(Q&4-asserta'fib'@-&++.
@ow once fi1'@-&+ has been calculated- fi1'M-&+ for all M between ( and @ is stored before
the recursie rule in the knowledge base. Hence
F G= fi1'O-H+.
H I (A
yes
F G= trace.
yes
F G= fi1'K-T+.
'(+ ( Call% fi1'K-;/+ G
'(+ ( 36it% fi1'K-K+
T I K
The predicate a1olish retracts all facts and rules for a particular predicate. Thus
a1olish'fib-4+ would remoe not only fi1'(-(+- fi1'4-(+ but also the fi1'@-&+ rule. The second
AK
argument of abolish is the arity of the predicate to be abolished. This is useful when we wish
to run a program seeral times during a !rolog session- as at any stage- we can simply
abolish facts obtained in preious runs.
AL
4..3. -xample 5ith ;isGointness.
Consider the predicate f'7-0+ which has 0I/ for 7MA- 0I4 for AYI7YIL and 0I* for 7NL. We
could define this by
f'7-/+ %= 7MA.
f'7-4+ %= AMI7-7MIL.
f'7-*+ %= 7NL.
Writing it as if 7MA then 0I/ else if 7YIL then 0I4 else 0I*- we could define it using the
as
f'7-0+ %= 7MA 0I/ J 7IML 0I4 J 0I*.
5sing the cut as
f'7-/+ %= 7MA-X.
f'7-4+ %= 7IML-X.
f'7-*+.
which is e1uialent to
f'7-0+ %= '7MA-0I/-X+J'7IML-0I4-X+J0I*.
will work ok when f is used with the first argument bound and the second unbound.
5nfortunately f'A-*+ also succeeds which is presumably @#T what we want. "t would be
safer to use the form with unless we were certain we would only be using it in the
functional mannerJ or to put the cuts in the BcorrectB place by%
f'7-0+ %= '7MA-X-0I/+J'7IML-X-0I4+J0I*.
4..4. +ontrolling num1er of "olutions
Consider the following predicate delete which is true when the third argument is the same
as the second with all occurrences of the first remoed 'it only works if the first two
arguments are bound+%
delete';-DE-DE+.
delete'7-D7F,E-M+ %= delete'7-,-M+.
delete'7-D0F,E-D0F ME+ %= 9 : 7I0- delete'7-,-M+.
Thus
F G= delete'a-Da-b-a-c-a-a-kE-,+.
, I Db-c-kE
Consider the following predicate which deletes only one 7 from the second argument%
deleteone '7-D7F,E-,+.
deleteone '7-D0F,E-D0F ME+ %= deleteone '7-,-M+.
This behaes as follows%
F G= deleteone 'a-Da-b-c-a-a-c-aE-,+.
, I Db-c-a-a-c-aE J
, I Da-b-c-a-c-aE J
, I Da-b-c-a-c-aE J
, I Da-b-c-a-a-cE J
no
Suppose that in a program we only wanted one solution- and if that solution was not suitable
for its use we then wished to stop rather than backtrack to find another. To stop this
backtracking we do the following
AO
oncedeleteone '7-D7F,E-,+ %= X.
oncedeleteone '7-D0F,E-D0F ME+ %= oncedeleteone '7-,-M+.
which behaes like
F G= oncedeleteone 'a-Da-b-c-a-a-c-aE-,+.
, I Db-c-a-a-c-aE J
no
Such cuts are sometimes added for efficiency reasons. This could be written using the as
oncedeleteone '7-D0F,E-@+ %= 780 @8, J oncedeleteone '7-,-M+-@ID0F ME.
" indicated aboe that some proided predicates could be defined using the cut. These often
make use of two special Rero=argument predicates% true V fail. The first of these is always
true and the second always false.
Code which contains cuts is fre1uently bad code. $oid them whereer possible. "f they
must be used for some reason- remember that it is ery easy to write such code incorrectly. "
tend to use the instead- but not ery often. My predicates which contain Xs or s tend to
be ery short with most of the work being done in other predicates without any cuts or
if..then..elses.
A:
4.<. Practical 4
(+ Write a minimum function min'7-0-Min+ without any cuts or if..then..else 8ewrite
it using . 8ewrite it using cuts.
4+ 36tend the weather e6ample as follows. Start with
5eather'7+ %= fact'7-yes+.
fact'nice-yes+ %= fact'sunny-yes+- fact'raining-no+.
fact'funny-yes+ %= fact'sunny-yes+- fact'raining-yes+.
fact'horrible-yes+ %= fact'raining-yes+- fact'fog-no+.
fact'7-no+ %= 9 : fact'7-yes+.
symptoms 'Draining-fog-sunnyE+.
Write a predicate as/a1out '7+ which asks whether 7 is yes or no- and asserts that fact-
retracting preious assertions about that 7 first. Write a predicate as/all ',+ which asks
about all elements in ,. Write a predicate init that does askall on the list of symptoms. Test
your predicates. 36tend its knowledge about weather a bit.
A+ ,oad the wumpus(.pl simulator from the code repository.
"nitialise the simulator with the 1uery%
F G= initiali=e 'DStench-<reeRe-Slitter-no-noE+.
This positions the wumpus and the pits as in &igure L.4 of 8ussel and @orig.
@ow- behae as the agent yourself using ase1uence of 1ueries of the form
F G= execute'$ction-DStench-<reeRe-Slitter-<ump-ScreamE+
where $ction one of%
Z goforward% moe one s1uare along current orientation if possible
Z turnleft% turn left )/ degrees
Z turnright% turn right )/ degrees
Z grab% pickup gold if in s1uare
Z shoot% shoot an arrow along orientation- killing wumpus if in that direction
Z climb% if in s1uare (-(- leae the cae and adds (/// points for each piece of gold.
Write code for a pig=headed agent which ignores the percepts and carries out a prescribed
se1uence of actions.
A)

You might also like