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

Introduction To Prolog For Artificial Intelligence

This document introduces the logic programming language Prolog. It discusses that Prolog is a declarative language where programs describe problems through facts and rules, rather than procedurally specifying how to solve problems. It provides examples of simple Prolog programs containing facts, rules, and queries. Facts state unconditional truths, rules represent conditional truths using an "if-then" format, and queries are questions posed to the program. The Prolog engine uses logical deduction over the facts and rules to answer queries.

Uploaded by

psd_prasad
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
532 views

Introduction To Prolog For Artificial Intelligence

This document introduces the logic programming language Prolog. It discusses that Prolog is a declarative language where programs describe problems through facts and rules, rather than procedurally specifying how to solve problems. It provides examples of simple Prolog programs containing facts, rules, and queries. Facts state unconditional truths, rules represent conditional truths using an "if-then" format, and queries are questions posed to the program. The Prolog engine uses logical deduction over the facts and rules to answer queries.

Uploaded by

psd_prasad
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

Introduction To Prolog For Artificial Intelligence

Table of Contents

ƒ Introduction to Prolog (Programming by Logic)


ƒ Programming Languages Types: Descriptive Language, Procedural
1
Language.
ƒ Why Prolog is suitable for AI and Expert System Application?
ƒ Prolog Program Structure: Predicates ,Clauses and Goal

ƒ Prolog Engine Architecture


ƒ Facts ,Rules and Goals
2
ƒ Installation of SWI-Prolog
ƒ Atoms , Variables and Complex Terms

ƒ Compound Goals
3
ƒ Comments
ƒ Matching and Proof Search

ƒ Recursion
4

ƒ Arithmetic Operators
5
ƒ Arity

ƒ Lists 6
ƒ Case studies 7

1
INTRODUCTION TO PROLOG (PROGRAMMING BY LOGIC)
Prolog was invented in the early seventies at the University of Marseille. Prolog stands for
PROgramming in LOGic. It is a logic language that is particularly used by programs that use non-
numeric objects. For this reason it is a frequently used language in Artificial Intelligence where
manipulation of symbols is a common task. Prolog differs from the most common programmings
languages because it is declarative language. Traditional programming languages are said to be
procedural. This means that the programmer specify how to solve a problem. In declarative
languages the programmers only give the problem and the language find himself how to solve the
problem.
Although it can be, and often is, used by itself, Prolog complements traditional languages when used
together in the same application.

Programming Languages Types:

Procedural language:-in which wrote the complete program depending on an appropriate algorithm
that must be programmed, specifies what the program should do and how? Like High Level
programming: Java, C++,Visual Basic

Descriptive language (Declarative):-like Prolog in Which program describe the problem as FACTS
and RULES, and then specify what the program should do? But didn't say How the program will
work and the results will be obtains, the Prolog Inference Engine is responsible for finding the
results

Why Prolog Is Suitable For AI Problems And Expert Systems?


Prolog is a Descriptive Programming Language as the Programmer should only describe the problem
properly in a knowledge base of FACTS and RULES, then the Prolog Inference Engine deduce new
Information through these Facts and RULES and display it as the answer for user query .
Also Many of AI Problem and Expert Systems are non-numeric Problems so it's easy to be describe
in prolog rather than any programming languages

PROLOG PROGRAM STRUCTURE: Facts, Rules, Queries


The Prolog Program contains Facts and Rules in a file (*.PL) called Knowledge base which has the
description of the problem and the Query is asked by the user to the Prolog Engine as Shown in

Figure 1: Prolog Structure


(3) Display (1) Load
Inference
Engine

Solutions
(2) Ask
Knowledge
Base
(Facts, Rules)
Queries (Goals)
2
Facts, Rules, and Queries
This introductory lecture has two main goals:
- To give some simple examples of Prolog programs. This will introduce us to the three basic constructs
in Prolog: facts, rules, and queries. It will also introduce us to a number of other themes, like the role of
logic in Prolog,
- To begin the systematic study of Prolog by defining terms, atoms, variables and other syntactic
concepts.

Some Simple Examples


There are only three basic constructs in Prolog: facts, rules, and queries. A collection of facts and rules
is called a knowledge base (or a database) and Prolog programming is all about writing knowledge
bases. That is, Prolog programs simply are knowledge bases, collections of facts and rules which
describe some collection of relationships that we find interesting. So how do we use a Prolog
program? By asking queries. That is, by asking questions about the information stored in the
knowledge base. Now this probably sounds rather strange. It's certainly not obvious that it has much to
do with programming at all -- after all, isn't programming all about telling the computer what to do?
But as we shall see, the Prolog way of programming makes a lot of sense, at least for certain kinds of
applications (computational linguistics being one of the most important examples). But instead of
saying more about Prolog in general terms, let's jump right in and start writing some simple
knowledge bases; this is not just the best way of learning Prolog, it's the only way ...

Knowledge Base 1
Knowledge Base 1 (KB1) is simply a collection of facts. Facts are used to state things that are
unconditionally true of the domain of interest. For example, we can state that Mia, Jody, and
Yolanda are women, and that Jody plays air guitar, using the following four facts:
woman(mia).
woman(jody).
woman(yolanda).
playsAirGuitar(jody).

This collection of facts is KB1. It is our first example of a Prolog program. Note that the names
mia, jody, and yolanda, and the properties woman and playsAirGuitar, have been written so that
the first letter is in lower-case. This is important; we will see why a little later. How can we use
KB1? By posing queries. That is, by asking questions about the information KB1 contains. Here
are some examples. We can ask Prolog whether Mia is a woman by posing the query:
?- woman(mia).
Prolog will answer
yes
for the obvious reason that this is one of the facts explicitly recorded in KB1. Incidentally, we
don't type in the ?-. This symbol (or something like it, depending on the implementation of Prolog
you are using) is the prompt symbol that the Prolog interpreter displays when it is waiting to
evaluate a query. We just type in the actual query (for example woman(mia)) followed by . (a full
stop).

Similarly, we can ask whether Jody plays air guitar by posing the following query:
?- playsAirGuitar(jody).
Prolog will again answer ``yes'', because this is one of the facts in KB1. However, suppose we ask
whether Mia plays air guitar:

3
?- playsAirGuitar(mia).
We will get the answer
no

Why ? Well, first of all, this is not a fact in KB1. Moreover, KB1 is extremely simple, and contains
no other information (such as the rules we will learn about shortly) which might help Prolog try to
infer (that is, deduce whether Mia plays air guitar. So Prolog correctly concludes that
playsAirGuitar(mia) does not follow from KB1.
Here are two important examples. Suppose we pose the query:
?- playsAirGuitar(vincent).
Again Prolog answers ``no''. Why? Well, this query is about a person (Vincent) that it has no
information about, so it concludes that playsAirGuitar(vincent) cannot be deduced from the
information in KB1.Similarly, suppose we pose the query:
?- tatooed(jody).
Again Prolog will answer ``no''. Why? Well, this query is about a property (being tatooed) that it
has no information about, so once again it concludes that the query cannot be deduced from the
information in KB1.

Knowledge Base 2

Here is KB2, our second knowledge base:

listensToMusic(mia).
happy(yolanda).
playsAirGuitar(mia) :- listensToMusic(mia).
playsAirGuitar(yolanda) :- listensToMusic(yolanda).
listensToMusic(yolanda):- happy(yolanda).

KB2 contains two facts, listensToMusic(mia) and happy(yolanda). The last three
items are rules.Rules state information that is conditionally true of the domain of interest. For
example, the first rule says that Mia plays air guitar if she listens to music, and the last rule says
that Yolanda listens to music if she if happy. More generally, the :- should be read as ``if'', or ``is
implied by''. The part on the left hand side of the :- is called the head of the rule, the part on the
right hand side is called the body. So in general rules say: if the body of the rule is true, then the
head of the rule is true too. And now for the key point: if a knowledge base contains a rule head :-
body, and Prolog knows that body follows from the information in the knowledge base, then
Prolog can infer head. This fundamental deduction step is what logicians call modus
ponens..Let's consider an example. We will ask Prolog whether Mia plays air guitar:

?- playsAirGuitar(mia).

Prolog will respond ``yes''. Why? Well, although playsAirGuitar(mia) is not a fact explicitly
recorded in KB2, KB2 does contain the rule

playsAirGuitar(mia) :- listensToMusic(mia).

Moreover, KB2 also contains the fact listensToMusic(mia). Hence Prolog can use modus ponens
to deduce that playsAirGuitar(mia). Our next example shows that Prolog can chain together uses of
modus ponens. Suppose we ask:

4
?- playsAirGuitar(yolanda).

Prolog would respond ``yes''. Why? Well, using the fact happy(yolanda) and the rule
listensToMusic(yolanda):- happy(yolanda), Prolog can deduce the new fact
listensToMusic(yolanda). This new fact is not explicitly recorded in the knowledge base --- it is
only implicitly present (it is inferred knowledge). Nonetheless, Prolog can then use it just like an
explicitly recorded fact. Thus, together with the rule

playsAirGuitar(yolanda) :- listensToMusic(yolanda)

it can deduce that playsAirGuitar(yolanda), which is what we asked it. Summing up:
any fact produced by an application of modus ponens can be used as input to further rules. By
chaining together applications of modus ponens in this way, Prolog is able to retrieve information
that logically follows from the rules and facts recorded in the knowledge base.The facts and rules
contained in a knowledge base are called clauses. Thus KB2 contains five clauses, namely three
rules and two facts. Another way of looking at KB2 is to say that it consists of three predicates (or
procedures). The three predicates are:

listensToMusic
happy
playsAirGuitar

The happy predicate is defined using a single clause (a fact). The listensToMusic and
playsAirGuitar predicates are each defined using two clauses (in both cases, two rules). It is a good
idea to think about Prolog programs in terms of the predicates they contain. In essence, the
predicates are the concepts we find important, and the various clauses we write down concerning
them are our attempts to pin down what they mean and how they are interrelated.One final remark.
We can view a fact as a rule with an empty body. That is, we can think of facts as ``conditionals
that do not have any antecedent conditions'', or ``degenerate rules''.

Knowledge Base 3

KB3, our third knowledge base, consists of five clauses:

happy(vincent).
listensToMusic(butch).
playsAirGuitar(vincent):-listensToMusic(vincent),happy(vincent).
playsAirGuitar(butch):-happy(butch).
playsAirGuitar(butch):-listensToMusic(butch).

There are two facts, namely happy(vincent) and listensToMusic(butch), and three rules.
KB3 defines the same three predicates as KB2 (namely happy, listensToMusic, and
playsAirGuitar) but it defines them differently. In particular, the three rules that define the
playsAirGuitar predicate introduce some new ideas. First, note that the rule

playsAirGuitar(vincent):-
listensToMusic(vincent),
happy(vincent).

5
has two items in its body, or (to use the standard terminology) two goals. What does this rule
mean? The important thing to note is the comma, that separates the goal listensToMusic (vincent)
and the goal happy (vincent) in the rule's body. This is the way logical conjunction is expressed in
Prolog (that is, the comma means and). So this rule says: ``Vincent plays air guitar if he listens to
music and he is happy''.
Thus, if we posed the query

?- playsAirGuitar(vincent).

Prolog would answer ``no''. This is because while KB3 contains happy(vincent), it does not
explicitly contain the information listensToMusic(vincent), and this fact cannot be deduced either.
So KB3 only fulfils one of the two preconditions needed to establish playsAirGuitar(vincent), and
our query fails.Incidentally, the spacing used in this rule is irrelevant. For example, we could have
written it as

playsAirGuitar(vincent):- happy(vincent),listensToMusic(vincent).

and it would have meant exactly the same thing. Prolog offers us a lot of freedom in the way we
set out knowledge bases, and we can take advantage of this to keep our code readable.
Next, note that KB3 contains two rules with exactly the same head, namely:

playsAirGuitar(butch):-happy(butch).
playsAirGuitar(butch):-listensToMusic(butch).

This is a way of stating that Butch plays air guitar if either he listens to music, or if he is happy.
That is, listing multiple rules with the same head is a way of expressing logical disjunction (that is,
it is a way of saying or). So if we posed the query

?- playsAirGuitar(butch).

Prolog would answer ``yes''. For although the first of these rules will not help (KB3 does not allow
Prolog to conclude that happy(butch)), KB3 does contain listensToMusic(butch) and this means
Prolog can apply modus ponens using the rule

playsAirGuitar(butch):-listensToMusic(butch).

to conclude that playsAirGuitar(butch). There is another way of expressing disjunction in Prolog.


We could replace the pair of rules given above by the single rule playsAirGuitar(butch):-
happy(butch); listensToMusic(butch).
The semicolon ; is the Prolog symbol for OR, so this single rule means exactly the same thing as
the previous pair of rules. But Prolog programmers usually write multiple rules, as extensive use of
semicolon can make Prolog code hard to read.
It should now be clear that Prolog has something do with logic: after all, the :- means implication(
when ), the , means conjunction, and the ; means disjunction. (What about negation? That is a
whole other story. We'll be discussing it later in the course.) Moreover, we have seen that a
standard logical proof rule (modus ponens) plays an important role in Prolog programming. And in
fact ``Prolog'' is short for ``Programming in logic''.

6
Knowledge Base 4
Here is KB4, our fourth knowledge base:

woman(mia).
woman(jody).
woman(yolanda).
loves(vincent,mia).
loves(marcellus,mia).
loves(pumpkin,honey_bunny).
loves(honey_bunny,pumpkin).

Now, this is a pretty boring knowledge base. There are no rules, only a collection of facts. Ok, we
are seeing a relation that has two names as arguments for the first time (namely the loves relation),
but, let's face it, that's a rather predictable idea.
No, the novelty this time lies not in the knowledge base, it lies in the queries we are going to pose.
In particular, for the first time we're going to make use of variables. Here's an example:

?- woman(X).

The X is a variable (in fact, any word beginning with an upper-case letter is a Prolog variable,
which is why we had to be careful to use lower-case initial letters in our earlier examples).
Now a variable isn't a name, rather it's a ``placeholder'' for information. That is, this query
essentially asks Prolog: tell me which of the individuals you know about is a woman. Prolog
answers this query by working its way through KB4, from top to bottom, trying to match (or unify)
the expression woman(X) with the information KB4 contains. Now the first item in the knowledge
base is woman(mia). So, Prolog matches X to mia, thus making the query agree perfectly with this
first item. (Incidentally, there's a lot of different terminology for this process: we can also say that
Prolog instantiates X to mia, or that it binds X to mia.)
Prolog then reports back to us as follows:

X = mia

That is, it not only says that there is information about at least one woman in KB4, it actually tells
us who she is. It didn't just say ``yes'', it actually gave us the variable binding, or instantiation that
led to success. But that's not the end of the story. The whole point of variables --- and not just in
Prolog either --- is that they can ``stand for'' or ``match with'' different things. And there is
information about other women in the knowledge base. We can access this information by typing
the following simple query
?- ;
Remember that ; means or, so this query means: are there any more women? So Prolog begins
working through the knowledge base again (it remembers where it got up to last time and starts
from there) and sees that if it matches X with Jody, then the query agrees perfectly with the second
entry in the knowledge base. So it responds:

X = jody
It's telling us that there is information about a second woman in KB4, and (once again) it actually
gives us the value that led to success. And of course, if we press ; a second time,Prolog returns the
answer

X = yolanda

7
But what happens if we press ; a third time? Prolog responds ``no''. No other matches are possible.
There are no other facts starting with the symbol woman. The last four entries in the knowledge
base concern the love relation, and there is no way that such entries can match a query of the form
of the form woman(x).Let's try a more complicated query, namely
loves(marcellus,X),woman(X).Now, remember that , means and, so this query says: is there any
individual X such that Marcellus loves X and X is a woman? If you look at the knowledge base
you'll see that there is: Mia is a woman (fact 1) and Marcellus loves Mia (fact 5). And in fact,
Prolog is capable of working this out. That is, it can search through the knowledge base and work
out that if it matches X with Mia, then both conjuncts of the query are satisfied (we'll learn in later
lectures exactly how Prolog does this). So Prolog returns the answer

X = mia

This business of matching variables to information in the knowledge base is the heart of Prolog.
For sure, Prolog has many other interesting aspects --- but when you get right down to it, it's
Prolog's ability to perform matching and return the values of the variable binding to us that is
crucial.

Prolog Syntax
Now that we've got some idea of what Prolog does, it's time to go back to the beginning and work
through the details more carefully. Let's start by asking a very basic question: we've seen all kinds
of expressions (for example jody, playsAirGuitar(mia), and X) in our Prolog programs, but these
have just been examples. Exactly what are facts, rules, and queries built out of? The answer is
terms, and there are four kinds of terms in Prolog: atoms, numbers, variables, and complex terms
(or structures). Atoms and numbers are lumped together under the heading constants, and constants
and variables together make up the simple terms of Prolog.
Let's take a closer look. To make things crystal clear, let's first get clear about the basic characters
(or symbols) at our disposal. The upper-case letters are A, B, ..., Z; the lower-case letters are a, b,
..., z; the digits are 1, 2, ..., 9; and the special characters are +, -, *, /, <, >, =, :, ., &, ~, and _. The _
character is called underscore. The blank space is also a character, but a rather unusual one, being
invisible. A string is an unbroken sequence of
characters.

Atoms
An atom is either:
1. A string of characters made up of upper-case letters, lower-case letters, digits, and the
underscore character, that begins with a lower-case letter. For example: butch,big_kahuna_burger,
and m_monroe2. 2. An arbitrary sequence of character enclosed in single quotes. For example
'Vincent', 'The Gimp', 'Five_Dollar_Shake', '&^%&#@$ &*', and ' '. The character between the
single quotes is called the atom name. Note that we are allowed to use spaces in such atoms --- in
fact, a common reason for using single quotes is so we can do precisely that.3. A string of special
characters. For example: @= and ====> and ; and :- are all atoms.As we have seen, some of these
atoms, such as ; and :- have a pre-defined meaning.

Numbers

8
Real numbers aren't particularly important in typical Prolog applications. So although most Prolog
implementations do support floating point numbers or floats (that is, representations of real
numbers such as 1657.3087 or ) we are not going to discuss them in this course. But integers (that
is: ... -2, -1, 0, 1, 2, 3, ...) are useful for such tasks as counting the elements of a list, and we'll
discuss how to manipulate them in a later lecture. Their Prolog syntax is the obvious one: 23,
1001, 0, -365, and so on.

Variables

A variable is a string of upper-case letters, lower-case letters, digits and underscore characters that
starts either with an upper-case letter or with underscore. For example, X, Y, Variable, _tag,
X_526, and List, List24, _head, Tail, _input and Output are all Prolog variables.
The variable _ (that is, a single underscore character) is rather special. It's called the anonymous
variable, and we discuss it in a later lecture.

Complex terms
Constants, numbers, and variables are the building blocks: now we need to know how to fit them
together to make complex terms. Recall that complex terms are often called structures.
Complex terms are build out of a functor followed by a sequence of arguments. The arguments are
put in ordinary brackets, separated by commas, and placed after the functor.
The functor must be an atom. That is, variables cannot be used as functors. On the other hand,
arguments can be any kind of term.
Now, we've already seen lots of examples of complex terms when we looked at KB1 -- KB5.
For example, playsAirGuitar(jody) is a complex term: its functor is playsAirGuitar and its
argument is jody. Other examples are loves(vincent,mia) and, to give an example containing a
variable, jealous(marcellus,W).
But note that the definition allows far more complex terms than this. In fact, it allows us to to keep
nesting complex terms inside complex terms indefinitely (that is, it is a recursive definition). For
example hide(X,father(father(father(butch)))) is a perfectly ok complex term. Its functor is hide,
and it has two arguments: the variable X, and the complex term father(father(father(butch))). This
complex term has father as its functor, and another complex term, namely father(father(butch)), as
its
sole argument. And the argument of this complex term, namely father(butch), is also complex. But
then the nesting ``bottoms out'', for the argument here is the constant butch.

As we shall see, such nested (or recursively structured) terms enable us to represent many
problems naturally. In fact the interplay between recursive term structure and variable matching is
the source of much of Prolog's power.The number of arguments that a complex term has is called
its arity. For instance, woman (mia) is a complex term with arity 1, while loves(vincent,mia) is a
complex term with arity 2.

Arity is important to Prolog. Prolog would be quite happy for us to define two predicates with the
same functor but with a different number of arguments. For example, we are free to define a
knowledge base that defines a two place predicate love (this might contain such facts as
love(vincent,mia)), and also a three place love predicate (which might contain such facts as
love(vincent,marcellus,mia)). However, if we did this, Prolog would treat the two place love and
the three place love as completely different predicates.

9
When we need to talk about predicates and how we intend to use them (for example, in
documentation) it is usual to use a suffix / followed by a number to indicate the pre dicate's arity.
To return to KB2, instead of saying that it defines predicates

listensToMusic
happy
playsAirGuitar

we should really say that it defines predicates listensToMusic/1 happy/1,playsAirGuitar/1 ,and


Prolog can't get confused about a knowledge base containing the two different love predicates, for
it regards the love/2 predicate and the love/3 predicate as completely distinct.

10
Exercise (1):
Q1

Which of the following sequences of characters are atoms, which are variables,
and which are neither?
1. vINCENT
2. Footmassage
3. variable23
4. Variable2000
5. big_kahuna_burger
6. 'big kahuna burger'
7. big kahuna burger
8. 'Jules'
9. _Jules
10. '_Jules'

Q2

Which of the following sequences of characters are atoms, which are variables, which are complex
terms, and which are not terms at all? Give the functor and arity of each complex term.
1. loves(Vincent,mia)
2. 'loves(Vincent,mia)'
3. Butch(boxer)
4. boxer(Butch)
5. and(big(burger),kahuna(burger))
6. and(big(X),kahuna(X))
7. _and(big(X),kahuna(X))
8. (Butch kills Vincent)
9. kills(Butch Vincent)
10. kills(Butch,Vincent

Q3

How many facts, rules, clauses, and predicates are there in the following
knowledge base? What are the heads of the rules, and what are the goals they
contain?
woman(vincent).
woman(mia).
man(jules).
person(X) :- man(X); woman(X).
loves(X,Y) :- knows(Y,X).
father(Y,Z) :- man(Y), son(Z,Y).
father(Y,Z) :- man(Y), daughter(Z,Y).

Q4

Represent the following in Prolog:


1. Butch is a killer.
2. Mia and Marcellus are married.
3. Zed is dead.

11
4. Marcellus kills everyone who gives Mia a footmassage.
5. Mia loves everyone who is a good dancer.
6. Jules eats anything that is nutritious or tasty.

Q5

Suppose we are working with the following knowledge base:


wizard(ron).
hasWand(harry).
quidditchPlayer(harry).
wizard(X) :- hasBroom(X),hasWand(X).
hasBroom(X) :- quidditchPlayer(X).

How does Prolog respond to the following queries?


1. wizard(ron).
2. witch(ron).
3. wizard(hermione).
4. witch(hermione).
5. wizard(harry).
6. wizard(Y).
7. witch(Y).

12
Matching And Proof Search
1. To discuss the idea of matching in Prolog, and to explain how Prolog matching differs from
standard unification. Along the way, we'll introduce =, the built-in Prolog predicate for matching.
2. To explain the search strategy Prolog uses when it tries to prove something.

Matching

When working with knowledge base KB4 in the previous chapter, we introduced the term
matching. We said, e.g. that Prolog matches woman(X) with woman(mia), thereby instantiating the
variable X to mia. We will now have a close look at what matching means.
Recall that there are three types of term:
1. Constants. These can either be atoms (such as vincent) or numbers (such as 24).
2. Variables.
3. Complex terms. These have the form: functor(term_1,...,term_n).

Proof Search

Now that we know about matching, we are in a position to learn how Prolog actually searches a
knowledge base to see if a query is satisfied. That is, we are now able to learn about proof search.
We will introduce the basic ideas involved by working through a simple example. Suppose we are
working with the following knowledge base

f(a).
f(b).
g(a).
g(b).
h(b).
k(X) :- f(X),g(X),h(X).

Suppose we then pose the query


k(Y).

13
K(Y)

X=Y
K(X)

f(X),g(X),h(X) X=b
X=a

F(b),g(b),h(b)
f(a),g(a),h(a)

T,g(a),h(a)
T,g(b),h(b)

T,T,h(a)

T,T,(b)

T,T,T
T,T,F

Figure2: Proof Search Tree

You will probably see that there is only one answer to this query, namely k(b), but how exactly
does Prolog work this out? Let's see.
Prolog reads the knowledge base, and tries to match k(X) with either a fact, or the head of a rule. It
searches the knowledge base top to bottom, and carries out the matching, if it can, at the first place
possible. Here there is only one possibility: it must match k(X) to the head of the rule k(X) :-
f(X),g(X),h(X).

Let's have a look at another example. Suppose that we are working with the following
knowledge base:

loves(vincent,mia).
loves(marcellus,mia).
jealous(X,Y) :- loves(X,Z),loves(Y,Z).

14
Now, we ask the query
jealous(X,Y).

Exercise 2

Q1
Which of the following pairs of terms match? Where relevant, give the variable Instantiations that
lead to successful matching.

1. bread = bread
2. 'Bread' = bread
3. 'bread' = bread
4. Bread = bread
5. bread = sausage
6. food(bread) = bread
7. food(bread) = X
8. food(X) = food(bread)
9. food(bread,X) = food(Y,sausage)
10. food(bread,X,beer) = food(Y,sausage,X)
11. food(bread,X,beer) = food(Y,kahuna_burger)
12. food(X) = X
13. meal(food(bread),drink(beer)) = meal(X,Y)
14. meal(food(bread),X) = meal(X,drink(beer))

Q2
We are working with the following knowledge base:
house_elf(dobby).
witch(hermione).
witch('McGonagall').
witch(rita_skeeter).
magic(X):-house_elf(X).
magic(X):-wizard(X).
magic(X):-witch(X).
Which of the following queries are satisfied? Where relevant, give all the variable instantiations
that lead to success.

1. ?- magic(house_elf).
2. ?- wizard(harry).
3. ?- magic(wizard).
4. ?- magic('McGonagall').
5. ?- magic(Hermione).

Draw the search tree for the fifth query magic(Hermione).

Q4
Here is a tiny lexicon and mini grammar with only one rule which defines a
sentence as consisting of five words: an article, a noun, a verb, and again an
article and a noun.

15
word(article,a).
word(article,every).
word(noun,criminal).
word(noun,'big kahuna burger').
word(verb,eats).
word(verb,likes).
sentence(Word1,Word2,Word3,Word4,Word5) :-
word(article,Word1),
word(noun,Word2),
word(verb,Word3),
word(article,Word4),
word(noun,Word5).

What query do you have to pose in order to find out which sentences the
grammar can generate? List all sentences that this grammar can generate in the order Prolog will
generate them. Make sure that you understand why Prolog generates them in this order.

16
Recursion
1. To introduce recursive definitions in Prolog.
2. To show that there can be mismatches between the declarative meaning of a Prolog program,
and its procedural meaning.

Recursive definitions
Predicates can be defined recursively. Roughly speaking, a predicate is recursively defined if one
or more rules in its definition refers to itself.

Example 1: Eating
Consider the following knowledge base:

is_digesting(X,Y) :- just_ate(X,Y).
is_digesting(X,Y) :-
just_ate(X,Z),
is_digesting(Z,Y).
just_ate(mosquito,blood(john)).
just_ate(frog,mosquito).
just_ate(stork,frog).

At first glance this seems pretty ordinary: it's just a knowledge base containing two facts and two
rules. But the definition of the is_digesting/2 predicate is recursive. Note that is_digesting is (at
least partially) defined in terms of itself, for the is_digesting functor occurs on both the left and
right hand sides of the second rule. Crucially, however, there is an `escape' from this circularity.
This is provided by the just_ate predicate, which occurs in both the first and second rules.
(Significantly, the right hand side of the first rule makes no mention of is_digesting.) Let's now
consider both the declarative and procedural meanings of this rule.

The word declarative is used to talk about the logical meaning of Prolog knowledge bases.That is,
the declarative meaning of a Prolog knowledge base is simply `what it says', or `what it means, if
we read it as a collection of logical statements'. And the declarative meaning of this recursive
definition is fairly straightforward. The first clause (the `escape' clause, the one that is not
recursive, or as we shall usually call it, the base clause), simply says that: if X has just eaten Y,
then X is now digesting Y. This is obviously a sensible definition.

So what about the second clause, the recursive clause? This says that: if X has just eaten Z and Z is
digesting Y, then X is digesting Y, too. Again, this is obviously a sensible definition.
So now we know what this recursive definition says, but what happens when we pose a query that
actually needs to use this definition? That is, what does this definition actually do? To use the
normal Prolog terminology, what is its procedural meaning?

This is also reasonably straightforward. The base rule is like all the earlier rules we've seen..That
is, if we ask whether X is digesting Y, Prolog can use this rule to ask instead the question: has X
just eaten Y?
What about the recursive clause? This gives Prolog another strategy for determining whether X is
digesting Y: it can try to find some Z such that X has just eaten Z, and Z is digesting Y.
That is, this rule lets Prolog break the task apart into two subtasks. Hopefully, doing so will
eventually lead to simple problems which can be solved by simply looking up the answers in the
knowledge base. The following picture sums up the situation:

17
Let's see how this works. If we pose the query:

?- is_digesting(stork,mosquito).

then Prolog goes to work as follows. First, it tries to make use of the first rule listed concerning
is_digesting; that is, the base rule. This tells it that X is digesting Y if X just ate Y, By unifying X
with stork and Y with mosquito it obtains the following goal:

just_ate(stork,mosquito).

But the knowledge base doesn't contain the information that the stork just ate the mosquito,so this
attempt fails. So Prolog next tries to make use of the second rule. By unifying X with stork and Y
with mosquito it obtains the following goals:

just_ate(stork,Z),
is_digesting(Z,mosquito).

That is, to show is_digesting(stork,mosquitp)}, Prolog needs to find a value for Z such that, firstly,

just_ate(stork,Z).
and secondly,
is_digesting(Z,mosquito).

And there is such a value for Z, namely frog. It is immediate that

Example : Descendant
Now that we know something about what recursion in Prolog involves, it is time to ask why it is so
important. Actually, this is a question that can be answered on a number of levels, but for now,
let's keep things fairly practical. So: when it comes to writing useful Prolog programs,are recursive
definitions really so important? And if so, why? Let's consider an example. Suppose we have a
knowledge base recording facts about the child relation:

child(charlotte,caroline).
child(caroline,laura).

That is, Caroline is a child of Charlotte, and Laura is a child of Caroline. Now suppose we wished
to define the descendant relation; that is, the relation of being a child of, or a child of a child of, or
a child of a child of a child of, or.... Here's a first attempt to do this. We could add the following
two non-recursive rules to the knowledge base:

descend(X,Y) :- child(X,Y).
descend(X,Y) :- child(X,Z),child(Z,Y).

Now, fairly obviously these definitions work up to a point, but they are clearly extremely limited:
they only define the concept of descendant-of for two generations or less. That's ok for the above
knowledge base, but suppose we get some more information about the child-of relation and we
expand our list of child-of facts to this:

child(martha,charlotte).
child(charlotte,caroline).

18
child(caroline,laura).
child(laura,rose).

Now our two rules are inadequate. For example, if we pose the queries

?- descend(martha,laura).
?- descend(charlotte,rose).

we get the answer `No!', which is not what we want. Sure, we could `fix' this by adding the
following two rules:

descend(X,Y) :- child(X,Z_1),
child(Z_1,Z_2),
child(Z_2,Y).
descend(X,Y) :- child(X,Z_1),
child(Z_1,Z_2),
child(Z_2,Z_3),
child(Z_3,Y).

But, let's face it, this is clumsy and hard to read. Moreover, if we add further child-of facts, we
could easily find ourselves having to add more and more rules as our list of child-of facts grow,
rules like:

descend(X,Y) :- child(X,Z_1),
child(Z_1,Z_2),
child(Z_2,Z_3),
.
.
.
child(Z_17,Z_18).
child(Z_18,Z_19).
child(Z_19,Y).
This is not a particularly pleasant (or sensible) way to go! But we don't need to do this at all. We
can avoid having to use ever longer rules entirely. The following recursive rule fixes everything
exactly the way we want:

descend(X,Y) :- child(X,Y).
descend(X,Y) :- child(X,Z),descend(Z,Y).

What does this say? The declarative meaning of the base clause is: if Y is a child of X, then Y is a
descendant of X. Obviously sensible.
So what about the recursive clause? It's declarative meaning is: if Z is a child of X, and Y is a
descendant of Z, then Y is a descendant of X. Again, this is obviously true.
So let's now look at the procedural meaning of this recursive predicate, by stepping through an
example. What happens when we pose the query?

descend(martha,laura)

Prolog first tries the first rule. The variable X in the head of the rule is unified with Martha and Y
with laura and the next goal Prolog tries to prove is

19
child(martha,laura) This attempt fails, however, since the knowledge base neither contains the fact
child (martha,laura) nor any rules that would allow to infer it. So Prolog backtracks and looks for
an alternative way of proving descend(martha,laura). It finds the second rule in the knowledge
base and now has the following subgoals:

child(martha,_633),
descend(_633,laura).

Prolog takes the first subgoal and tries to match it onto something in the knowledge base. It finds
the fact child(martha,charlotte) and the Variable _633 gets instantiated to charlotte. Now that the
first subgoal is satisfied, Prolog moves to the second subgoal. It has to prove
descend(charlotte,laura)
This is the recursive call of the predicate descend/2. As before, Prolog starts with the first rule, but
fails, because the goal child(charlotte,laura) cannot be proved. Backtracking, Prolog finds that
there is a second possibility to be checked for descend(charlotte,laura), viz. the second rule, which
again gives Prolog two new
subgoals:

child(charlotte,_1785),
descend(_1785,laura).

The first subgoal can be unified with the fact child(charlotte,caroline) of the knowledge base, so
that the variable _1785 is instantiated with caroline. Next Prolog tries to prove
descend(caroline,laura).
This is the second recursive call of predicate descend/2. As before, it tries the first rule
first,obtaining the following new goal:

child(caroline,laura)

This time Prolog succeeds, since child(caroline,laura) is a fact in the database. Prolog
has found a proof for the goal descend(caroline,laura) (the second recursive call). But
this means that child(charlotte,laura) (the first recursive call) is also true, which means that our
original query descend(martha,laura) is true as well. Here is the search tree for the query
descend(martha,laura). Make sure that you understand how it relates to the discussion in the text;
i.e. how Prolog traverses this search tree when trying to prove this query.

20
Exercise
Q1
We have the following knowledge base:
directTrain(forbach,saarbruecken).
directTrain(freyming,forbach).
directTrain(fahlquemont,stAvold).
directTrain(stAvold,forbach).
directTrain(saarbruecken,dudweiler).
directTrain(metz,fahlquemont).
directTrain(nancy,metz).

That is, this knowledge base holds facts about towns it is possible to travel between by taking a
direct train. But of course, we can travel further by `chaining together' direct train journeys. Write
a recursive predicate travelBetween/2 that tells us when we can travel by train between two towns.
For example, when given the query
travelBetween(nancy,saarbruecken)
it should reply `yes'.

It is, furthermore, plausible to assume that whenever it is possible to take a direct train from A to
B, it is also possible to take a direct train from B to A. Can you encode this in Prolog? You
program should e.g. answer `yes' to the following query:

travelBetween(saarbruecken,nancy).

Do you see any problems you program may run into?

21
Arithmetic in Prolog

Prolog provides a number of basic arithmetic tools for manipulating integers (that is, numbers
of the form ...-3, -2, -1, 0, 1, 2, 3, 4...). Most Prolog implementation also provide tools for
handling real numbers (or floating point numbers) such as 1.53 or , but we're not
going to discuss these, for they are not particularly useful for the symbolic processing tasks
discussed in this course. Integers, on the other hand, are useful for various tasks (such as
finding the length of a list), so it is important to understand how to work with them. We'll start
by looking at how Prolog handles the four basic operations of addition, multiplication,
subtraction, and division.

Arithmetic examples Prolog Notation

6+2=8 8 is 6+2.
682=12 12 is 6*2.
6-2=4 4 is 6-2.
6-8=-2 -2 is 6-8.
6/2=3 3 is 6/2.
7/3=2 3 is 7/2.
1 is the remainder when 7 is divided by 2 1 is mod(7,2).

(Note that as we are working with integers, division gives us back an integer answer. Thus 7%2
gives 3 as an answer, leaving a reminder of 1.) Posing the following queries yields the following
responses:

?- 8 is 6+2.
yes
?- 12 is 6*2.
yes
?- -2 is 6-8.
yes
?- 3 is 6/2.
yes
?- 1 is mod(7,2).
yes
More importantly, we can work out the answers to arithmetic questions by using variables. For
example:
?- X is 6+2.
X=8
?- X is 6*2.
X = 12
?- R is mod(7,2).
R=1

Moreover, we can use arithmetic operations when we define predicates. Here's a simple example.
Let's define a predicate add_3_and_double2/ whose arguments are both integers.This predicate
takes its first argument, adds three to it, doubles the result, and returns the number obtained as the
second argument. We define this predicate as follows:

22
add_3_and_double(X,Y) :- Y is (X+3)*2.
And indeed, this works:
?- add_3_and_double(1,X).
X=8
?- add_3_and_double(2,X).
X = 10
One other thing. Prolog understands the usual conventions we use for disambiguating arithmetical
expressions. For example, when we write 3+2*4 we mean 3+(2*4) and not (3+2)*4, and Prolog
knows this convention:
?- X is 3+2*4.
X = 11

Comparing Integers

Some Prolog arithmetic predicates actually do carry out arithmetic all by themselves (that is,
without the assistance of is). These are the operators that compare integers.

X < Y.
X =< Y.
X =:= Y. means x equal y
X =\= Y. means not equal y
X >= Y
X>Y
These operators have the obvious meaning:
2 < 4.
yes
2 =< 4.
yes
4 =< 4.
yes
4=:=4.
yes
4=\=5.
yes
4=\=4.
no
4 >= 4.
yes

4 > 2.
yes

Moreover, they force both their right-hand and left-hand arguments to be evaluated:
2 < 4+1.
yes
2+1 < 4.
yes
2+1 < 3+2.
yes

23
Note that =:= really is different from =, as the following examples show:
4=4.
yes
2+2 =4.
no
2+2 =:= 4.
yes
That is, = tries to unify its arguments; it does not force arithmetic evaluation. That's =:='s job.
Whenever we use these operators, we have to take care that any variables are instantiated. For
example, all the following queries lead to instantiation errors.
X < 3.
3 < Y.
X =:= X.
Moreover, variables have to be instantiated to integers. The query
X = 3, X < 4.
succeeds. But the query

X = b, X < 4.
fails.
OK, let's now look at an example which puts Prolog's abilities to compare numbers to work.We're
going to define a predicate which takes takes a list of non-negative integers as its first argument,
and returns the maximum integer in the list as its last argument. Again, we'll use an accumulator.
As we work our way down the list, the accumulator will keep track of the highest integer found so
far. If we find a higher value, the accumulator will be updated to this new value. When we call the
program, we set accumulator to an initial value of 0. Here's the code. Note that there are two
recursive clauses:
accMax([H|T],A,Max) :-
H > A,
accMax(T,H,Max).
accMax([H|T],A,Max) :-
H =< A,
accMax(T,A,Max).
accMax([],A,A).

The first clause tests if the head of the list is larger than the largest value found so far. If it is,we set
the accumulator to this new value, and then recursively work through the tail of the list. The
second clause applies when the head is less than or equal to the accumulator; in this case we
recursively work through the tail of the list using the old accumulator value. Finally,the base clause
unifies the second and third arguments; it gives the highest value we found while going through
the list to the last argument. Here's how it works:
accMax([1,0,5,4],0,_5810)
accMax([0,5,4],1,_5810)
accMax([5,4],1,_5810)
accMax([4],5,_5810)
accMax([],5,_5810)
accMax([],5,5)

Again, it's nice to define a predicate which calls this, and initializes the accumulator. But wait:
what should we initialize the accumulator too? If you say 0, this means you are assuming that
all the numbers in the list are positive. But suppose we give a list of negative integers as

24
input. Then we would have
accMax([-11,-2,-7,-4,-12],0,Max).
Max = 0
yes
This is not what we want: the biggest number on the list is -2. Our use of 0 as the initial value
of the accumulator has ruined everything, because it's bigger than any number on the list.There's
an easy way around this: since our input list will always be a list of integers, simply initialize the
accumulator to the head of the list. That way we guarantee that the accumulator is initialized to a
number on the list. The following predicate does this for us:
max(List,Max) :-
List = [H|_],
accMax(List,H,Max).
So we can simply say:
max([1,2,46,53,0],X).
X = 53
yes
And furthermore we have:
max([-11,-2,-7,-4,-12],X).
X = -2
Yes

25
Exercises

Q1
How does Prolog respond to the following queries?
1. X = 3*4.
2. X is 3*4.
3. 4 is X.
4. X = Y.
5. 3 is 1+2.
6. 3 is +(1,2).
7. 3 is X+2.
8. X is 1+2.
9. 1+2 is 1+2.
10. is(X,+(1,2)).
11. 3+2 = +(3,2).
12. *(7,5) = 7*5.
13. *(7,+(3,2)) = 7*(3+2).
14. *(7,(3+2)) = 7*(3+2).
15. *(7,(3+2)) = 7*(+(3,2)).

Q2

1. Define a 2-place predicate increment that holds only when its second argument is an integer one
larger than its first argument. For example, increment(4,5) should hold, but increment(4,6) should
not.
2. Define a 3-place predicate sum that holds only when its third argument is the sum of the first
two arguments. For example, sum(4,5,9) should hold, but sum(4,6,12)should not.

Q3

Write a predicate addone2/ whose first argument is a list of integers, and whose second argument
is the list of integers obtained by adding 1 to each integer in the first list. For example, the query
addone([1,2,7,2],X). should give X = [2,3,8,3].

26
Lists
1. To introduce lists, an important recursive data structure widely used in computational
linguistics.
2. To define member, a fundamental Prolog tool for manipulating lists, and to introduce the idea of
recursing down lists.

Lists
As its name suggests, a list is just a plain old list of items. Slightly more precisely, it is a finite
sequence of elements. Here are some examples of lists in Prolog:

[mia, vincent, jules, yolanda]


[mia, robber(honey_bunny), X, 2, mia]
[]
[mia, [vincent, jules], [butch, girlfriend(butch)]]
[[], dead(zed), [2, [b, chopper]], [], Z, [2, [b, chopper]]]

We can learn some important things from these examples.


1. We can specify lists in Prolog by enclosing the elements of the list in square brackets (that is,
the symbols [ and ]). The elements are separated by commas. For example,our first example [mia,
vincent, jules, yolanda] is a list with four elements,namely mia, vincent, jules, and yolanda. The
length of a list is the number of elements it has, so our first example is a list of length four.

2. From our second example, [mia,robber(honey_bunny),X,2,mia], we learn that all sorts of Prolog
objects can be elements of a list. The first element of this list is mia,an atom; the second element is
robber(honey_bunny), a complex term; the third element is X, a variable; the fourth element is 2, a
number. Moreover, we also learn that the same item may occur more than once in the same list: for
example, the fifth element of this list is mia, which is same as the first element.

3. The third example shows that there is a very special list, the empty list. The empty list (as its
name suggests) is the list that contains no elements. What is the length of the empty list? Zero, of
course (for the length of a list is the number of members it contains, and the empty list contains
nothing).
4. The fourth example teaches us something extremely important: lists can contain other
lists as elements. For example, the second element of [mia, [vincent, jules],
[butch,girlfriend(butch)] is the list [vincent,jules], and the third element is [butch,girlfriend
(butch)]]. In short, lists are examples of recursive data structures: lists can be made out of lists.
What is the length of the fourth list? The answer is: three. If you thought it was five (or indeed,
anything else) you're not thinking about lists in the right way. The elements of the list are the
things between the outermost square brackets separated by commas. So this list contains three
elements: the first element is mia, the second element is [vincent, jules], and the third element is
[butch, girlfriend (butch)].
The last example mixes all these ideas together. We have here a list which contains the empty list
(in fact, it contains it twice), the complex term dead(zed), two copies of the list [2, [b, chopper]],
and the variable Z. Note that the third (and the last) elements are lists which themselves contain
lists (namely [b, chopper]).
Now for a very important point. Any non-empty list can be thought of as consisting of two parts:
the head and the tail. The head is simply the first item in the list; the tail is everything else. Or
more precisely, the tail is the list that remains when we take the first element away, i.e. the tail of a
list is always a list again.

27
For example, the head of [mia, vincent, jules, yolanda] is mia and the tail is [vincent, jules,
yolanda]. Similarly, the head of [[], dead(zed), [2, [b, chopper]], [], Z, [2, [b, chopper]]]
is [], and the tail is [dead(zed), [2,[b,chopper]],[],Z,[2,[b, chopper]]]. And what are the head and
the tail of the list [dead(zed)]? Well, the head is the first element of the list, which is dead(zed),
and the tail is the list that remains if we take the head away,which, in this case, is the empty list [].
Note that only non-empty lists have heads and tails. That is, the empty list contains no internal
structure. For Prolog, the empty list [] is a special, particularly simple, list.Prolog has a special
inbuilt operator | which can be used to decompose a list into its head and tail. It is very important
to get to know how to use |, for it is a key tool for writing Prolog list manipulation programs.
The most obvious use of | is to extract information from lists. We do this by using | together
with matching. For example, to get hold of the head and tail of [mia,vincent, jules, yolanda] we
can pose the following query:
?- [Head| Tail] = [mia, vincent, jules, yolanda].
Head = mia
Tail = [vincent,jules,yolanda]
yes
That is, the head of the list has become bound to Head and the tail of the list has become bound to
Tail. Note that there is nothing special about Head and Tail, they are simply variables. We could
just as well have posed the query:
?- [X|Y] = [mia, vincent, jules, yolanda].
X = mia
Y = [vincent,jules,yolanda]
yes
As we mentioned above, only non-empty lists have heads and tails. If we try to use | to pull
[] apart, Prolog will fail:
?- [X|Y] = [].
no
That is, Prolog treats [] as a special list. This observation is very important. We'll see why
later.
Let's look at some other examples. We can extract the head and tail of the following list just
as we saw above:
?- [X|Y] = [[], dead(zed), [2, [b, chopper]], [], Z].
X = []
Y = [dead(zed),[2,[b,chopper]],[],_7800]
Z = _7800
yes
That is: the head of the list is bound to X, the tail is bound to Y. (We also get the information
that Prolog has bound Z to the internal variable _7800.)
But we can can do a lot more with |; it really is a very flexible tool. For example, suppose we
wanted to know what the first two elements of the list were, and also the remainder of the list
after the second element. Then we'd pose the following query:
?- [X,Y | W] = [[], dead(zed), [2, [b, chopper]], [], Z].
X = []
Y = dead(zed)
W = [[2,[b,chopper]],[],_8327]
Z = _8327
yes
That is: the head of the list is bound to X, the second element is bound to Y, and the remainder of
the list after the second element is bound to W. W is the list that remains when we take away the

28
first two elements. So, | can not only be used to split a list into its head and its tail, but we can in
fact use it to split a list at any point. Left of the |, we just have to
enumerate how many elements we want to take away from the beginning of the list, and right
of the | we will then get what remains of the list. In this example, we also get the information
that Prolog has bound Z to the internal variable _8327.
This is a good time to introduce the anonymous variable. Suppose we were interested in
getting hold of the second and fourth elements of the list:
[[], dead(zed), [2, [b, chopper]], [], Z].
Now, we could find out like this:
?- [X1,X2,X3,X4 | Tail] = [[], dead
(zed), [2, [b, chopper]], [], Z].
X1 = []
X2 = dead(zed)
X3 = [2,[b,chopper]]
X4 = []
Tail = [_8910]
Z = _8910
yes
OK, we have got the information we wanted: the values we are interested in are bound to the
variables X2 and X4. But we've got a lot of other information too (namely the values bound to
X1, X3 and Tail). And perhaps we're not interested in all this other stuff. If so, it's a bit silly having
to explicitly introduce variables X1, X3 and Tail to deal with it. And in fact, there is a simpler way
to obtain only the information we want: we can pose the following query instead:
?- [_,X,_,Y|_] = [[], dead(zed), [2, [b, chopper]], [], Z].
X = dead(zed)
Y = []
Z = _9593
yes
The _ symbol (that is, underscore) is the anonymous variable. We use it when we need to use
a variable, but we're not interested in what Prolog instantiates it to. As you can see in the above
example, Prolog didn't bother telling us what _ was bound to. Moreover, note that each occurrence
of _ is independent: each is bound to something different. This couldn't happen with an ordinary
variable of course, but then the anonymous variable isn't meant to be ordinary. It's simply a way of
telling Prolog to bind something to a given position, completely independently of any other
bindings.
Let's look at one last example. The third element of our working example is a list (namely
[2, [b, chopper]]). Suppose we wanted to extract the tail of this internal list, and that we are not
interested in any other information. How could we do this? As follows:
?- [_,_,[_|X]|_] =
[[], dead
(zed), [2, [b, chopper]], [], Z, [2, [b, chopper]]].
X = [[b,chopper]]
Z = _10087
Yes

Member

It's time to look at our first example of a Prolog program for manipulating lists. One of the most
basic things we would like to know is whether something is an element of a list or not.So let's
write a program that, when given as inputs an arbitrary object X and a list L, tells us whether or not

29
X belongs to L. The program that does this is usually called member, and it is the simplest
example of a Prolog program that exploits the recursive structure of lists. Here it is:
member(X,[X|T]).
member(X,[H|T]) :- member(X,T).
That's all there is to it: one fact (namely member(X,[X|T])) and one rule (namely member
(X,[H|T]) :- member(X,T)). But note that the rule is recursive (after all, the functor member occurs
in both the rule's head and tail) and it is this that explains why such a short program is all that is
required. Let's take a closer look.
We'll start by reading the program declaratively. And read this way, it is obviously sensible.The
first clause (the fact) simply says: an object X is a member of a list if it is the head of that list. Note
that we used the inbuilt | operator to state this (simple but important) principle about lists.What
about the second clause, the recursive rule? This says: an object X is member of a list if it is a
member of the tail of the list. Again, note that we used the | operator to state this principle.Now,
clearly this definition makes good declarative sense. But does this program actually do what it is
supposed to do? That is, will it really tell us whether an object X belongs to a list L?
And if so, how exactly does it do this? To answer such questions, we need to think about its
procedural meaning. Let's work our way through a few examples.
Suppose we posed the following query:
?- member(yolanda,[yolanda,trudy,vincent,jules]).
Prolog will immediately answer `Yes'. Why? Because it can unify yolanda with both occurrences
of X in the first clause (the fact) in the definition of member/2, so it succeeds immediately.
Now consider the following query:
?- member(vincent,[yolanda,trudy,vincent,jules]).
Now the first rule won't help (vincent and yolanda are distinct atoms) so Prolog goes to the second
clause, the recursive rule. This gives Prolog a new goal: it now has to see if
member(vincent,[trudy,vincent,jules]).
Now, once again the first clause won't help, so Prolog goes (again) to the recursive rule. This gives
it a new goal, namelymember(vincent,[vincent,jules]).
This time, the first clause does help, and the query succeeds.So far so good, but we need to ask an
important question. What happens when we pose a query that fails? For example, what happens if
we pose the query member(zed,[yolanda,trudy,vincent,jules]).
Now, this should obviously fail (after all, zed is not on the list). So how does Prolog handle this?
In particular, how can we be sure that Prolog really will stop, and say no, instead going into an
endless recursive loop? Let's think this through systematically. Once again, the first clause cannot
help, so Prolog uses the recursive rule,which gives it a new goal ember(zed,[trudy,vincent,jules]).
Now, this should obviously fail (after all, zed is not on the list). So how does Prolog handle this?
In particular, how can we be sure that Prolog really will stop, and say no, instead going into an
endless recursive loop? Let's think this through systematically. Once again, the first clause cannot
help,so Prolog uses the recursive rule,which gives it a new goal member(zed,[trudy,vincent,jules]).
Again, the first clause doesn't help, so Prolog reuses the recursive rule and tries to show that
member(zed,[vincent,jules]).Similarly, the first rule doesn't help, so Prolog reuses the second rule
yet again and tries the Goal member(zed,[jules]).Again the first clause doesn't help, so Prolog uses
the second rule, which gives it the goal

30
Member
member(zed,[]) And this is where things get interesting. Obviously the first clause can't help here.
But note:the recursive rule can't do anything more either. Why not? Simple: the recursive rule elies
on splitting the list into a head and a tail, but as we have already seen, the empty list can't be split
up in this way. So the recursive rule cannot be applied either, and Prolog stops searching for more
solutions and announces `No'. That is, it tells us that zed does not belong to the list,which is, of
course, what it ought to do.We could summarize the member/2 predicate as follows. It is a ecursive
predicate, which systematically searches down the length of the list for the required item. It does
this by stepwise breaking down the list into smaller lists, and looking at the first item of each
smaller list. This mechanism that drives this search is recursion, and the reason that this recursion
is safe (that is, the reason it does not go on forever) is that at the end of the line Prolog has to ask a
question about the empty list. The empty list cannot be broken down into smaller parts,and this
allows a way out of the recursion.Well, we've now seen why member/2 works, but in fact it's far
more useful than the previous example might suggest. Up till now we've only been using it to
answer yes/no questions. But we can also pose questions containing variables. For example, we
can have the following dialog with Prolog:
member(X,[yolanda,trudy,vincent,jules]).
X = yolanda ;
X = trudy ;
X = vincent ;
X = jules ;
no
That is, Prolog has told us what every member of a list is. This is a very common use of
member/2. In effect, by using the variable we are saying to Prolog: `Quick! Give me some
element of the list!'. In many applications we need to be able to extract members of a list, and
this is the way it is typically done.One final remark. The way we defined member/2 above is
certainly correct, but in one respect it is a little messy.Think about it. The first clause is there to
deal with the head of the list. But although the tail is irrelevant to the first clause, we named the tail
using the variable T. Similarly, the recursive rule is there to deal with the tail of the list. But
although the head is irrelevant here, we named it using the variable H. These unnecessary variable
names are distracting: it's better to write predicates in a way that focuses attention on what is really
important in each clause, and the anonymous variable gives us a nice way of doing this. That is, we
can rewrite member/2 as follows:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
This version is exactly the same, both declaratively and procedurally. But it's just that little bit
clearer: when you read it, you are forced to concentrate on what is essential.

31
Exercises
Q1
How does Prolog respond to the following queries?
1. [a,b,c,d] = [a,[b,c,d]].
2. [a,b,c,d] = [a|[b,c,d]].
3. [a,b,c,d] = [a,b,[c,d]].
4. [a,b,c,d] = [a,b|[c,d]].
5. [a,b,c,d] = [a,b,c,[d]].
6. [a,b,c,d] = [a,b,c|[d]].
7. [a,b,c,d] = [a,b,c,d,[]].
8. [a,b,c,d] = [a,b,c,d|[]].
9. [] = _.
10. [] = [_].
11. [] = [_|[]].

Q2

Suppose we are given a knowledge base with the following facts:


tran(eins,one).
tran(zwei,two).
tran(drei,three).
tran(vier,four).
tran(fuenf,five).
tran(sechs,six).
tran(sieben,seven).
tran(acht,eight).
tran(neun,nine).
Write a predicate listtran(G,E) which translates a list of German number words to the crresponding
list of English number words. For example:
listtran([eins,neun,zwei],X).
should give:X = [one,nine,two].
Your program should also work in the other direction. For example, if you give it
the query listtran(X,[one,seven,six,two]).
it should return: X = [eins,sieben,sechs,zwei].
Hint: to answer this question, first ask yourself `How do I translate the empty list of number
words?'. That's the base case. For non-empty lists, first translate the head of the list, then use
recursion to translate the tail.

Q3

Write a predicate twice(In,Out) whose left argument is a list, and whose right argument is a list
consisting of every element in the left list written twice. For example, the query
twice([a,4,buggle],X).
should return
X = [a,a,4,4,buggle,buggle]).
And the query
twice([1,2,1,1],X).
should return
X = [1,1,2,2,1,1,1,1].

32
Hint: to answer this question, first ask yourself `What should happen when the first argument is the
empty list?'. That's the base case. For non-empty lists, think about what you should do with the
head, and use recursion to handle the tail.
Q4
Draw the search trees for the following three queries:
?- member(a,[c,b,a,y]).
?- member(x,[a,b,c]).
?- member(X,[a,b,c]).

33

You might also like