SlideShare a Scribd company logo
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 1/24
COMP9414/9814 Artificial Intelligence
INTRODUCTION TO PROLOG PROGRAMMING
Reference:Bratko, I., Programming in Prolog for Artificial Intelligence, 4th Edition, Addison-Wesley, 2011,
chapters 1-5
Aim: To introduce enough of Prolog to allow students to do the assignment work in this course, thereby
gaining some experience of AI programming.
Plan: What is Prolog? Programming with relations.
Facts
Questions
Variables
Conjunctions of goals, backtracking
Rules
Structures
Recursive programs
Lists
Controlling execution - the cut
What is Prolog?
invented early seventies by Alain Colmerauer in France and Robert
Kowalski in Britain. (There is a recent 2-page article by Kowalski at
http://www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/Kowalski.pdf).
Note that historical information in these lectures is not examinable.
Prolog = Programmation en Logique (Programming in Logic).
Prolog is a declarative programming language
unlike most common programming languages.
In a declarative language
the programmer specifies a goal to be achieved
the Prolog system works out how to achieve it
relational databases owe something to Prolog
Alain
Colmerauer
Robert
Kowalski
What is Prolog? (continued)
traditional programming languages are said to be procedural
procedural programmer must specify in detail how to solve a problem:
mix ingredients;
beat until smooth;
bake for 20 minutes in a moderate oven;
remove tin from oven;
put on bench;
close oven;
turn off oven;
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 2/24
in purely declarative languages, the programmer only states what the problem is and leaves the rest to the
language system
We'll see specific, simple examples of cases where Prolog fits really well shortly
Applications of Prolog
Some applications of Prolog are:
intelligent data base retrieval
natural language understanding
expert systems
specification language
machine learning
robot planning
automated reasoning
problem solving
The Prolog Language
Reference: Bratko, Chapter 1
Ivan Bratko
Relations
Prolog programs specify relationships among objects and properties of objects.
When we say, "John owns the book", we are declaring the ownership relationship between two objects:
John and the book.
When we ask, "Does John own the book?" we are trying to find out about a relationship.
Relationships can also rules such as:
Two people are sisters if
they are both female and
they have the same parents.
A rule allows us to find out about a relationship even if the relationship isn't explicitly stated as a fact.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 3/24
A little more on being sisters
As usual in programming, you need to be a bit careful how you phrase things:
The following would be better:
A and B are sisters if
A and B are both female and
they have the same father and
they have the same mother and
A is not the same as B
Programming in Prolog
declare facts describing explicit relationships between objects and properties objects might have (e.g.
Mary likes pizza, grass has_colour green, Fido is_a_dog, Mizuki taught Paul Japanese )
define rules defining implicit relationships between objects (e.g. the sister rule above) and/or rules
defining implicit object properties (e.g. X is a parent if there is a Y such that Y is a child of X).
One then uses the system by:
asking questions above relationships between objects, and/or about object properties (e.g. does Mary like
pizza? is Joe a parent?)
Facts
Properties of objects, or relationships between objects;
"Dr Turing lectures in course 9020", is written in Prolog as:
lectures(turing, 9020).
Notice that:
names of properties/relationships begin with lower case letters.
the relationship name appears as the first term
objects appear as comma-separated arguments within parentheses.
A period "." must end a fact.
objects also begin with lower case letters. They also can begin with digits (like 9020), and can be
strings of characters enclosed in quotes (as in reads(fred, "War and Peace")).
lectures(turing, 9020). is also called a predicate
Facts about a hypothetical computer science department:
% lectures(X, Y): person X lectures in course Y
lectures(turing, 9020).
lectures(codd, 9311).
lectures(backus, 9021).
lectures(ritchie, 9201).
lectures(minsky, 9414).
lectures(codd, 9314).
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 4/24
% studies(X, Y): person X studies in course Y
studies(fred, 9020).
studies(jack, 9311).
studies(jill, 9314).
studies(jill, 9414).
studies(henry, 9414).
studies(henry, 9314).
%year(X, Y): person X is in year Y
year(fred, 1).
year(jack, 2).
year(jill, 2).
year(henry, 4).
Together, these facts form Prolog's database. Should you wish to experiment with them using Prolog, they are
available at http://www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/facts03.
Queries
Once we have a database of facts (and, soon, rules) we can ask questions about the stored information.
Suppose we want to know if Turing lectures in course 9020. We can ask:
% prolog -s facts03
(multi-line welcome message)
?- lectures(turing, 9020).
true.
?- <control-D>
%
facts03 loaded into Prolog
"?-" is Prolog's prompt
output from Prolog
hold down control & press D
to leave Prolog
Notice that:
In SWI Prolog, queries are terminated by a full stop.
To answer this query, Prolog consults its database to see if this is a known fact.
In example dialogues with Prolog, the text in green italics is what the user types.
Another example query
?- lectures(codd, 9020).
false.
if answer is true., the query succeeded
if answer is false., the query failed. Note: many early versions of Prolog, including early versions of
SWI-Prolog, say No instead of false. See the article on negation in the Prolog dictionary to find out why
No. is a more accurate description of what is happening.
In the latest version of SWI Prolog, it no longer says "No." but says "false." instead.
The use of lower case for codd is critical.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 5/24
Prolog is not being intelligent about this - it would not see a difference between this query and
lectures(fred, 9020). or lectures(xyzzy, 9020).
though a person inspecting the database can see that fred is a student, not a lecturer, and that xyzzy is
neither student nor lecturer.
Variables
Suppose we want to ask, "What course does Turing teach"?
This could be written as:
Is there a course, X, that Turing teaches?
The variable X stands for an object that the questioner does not know about yet.
To answer the question, Prolog has to find out the value of X, if it exists.
As long as we do not know the value of a variable it is said to be unbound.
When a value is found, the variable is said to bound to that value.
The name of a variable must begin with a capital letter or an underscore character, "_".
Variables 2
To ask Prolog to find the course that Turing teaches, enter this:
?- lectures(turing, Course).
Course = 9020 ← output from Prolog
To ask which course(s) Prof. Codd teaches, we may ask,
?- lectures(codd , Course).
Course = 9311 ; ← type ";" to get next solution
Course = 9314
?-
If Prolog can tell that there are no more solutions, it just gives you the ?- prompt for a new query, as
here. If Prolog can't tell, it will let you type ; again, and then if there is no further solution, report false.
Prolog can find all possible ways to answer a query, unless you explicitly tell it not to (see cut, later).
Conjunctions of Goals in Queries
How do we ask, "Does Turing teach Fred"?
This means finding out if Turing lectures in a course that Fred studies.
?- lectures(turing, Course), studies(fred, Course).
i.e. "Turing lectures in course, Course and Fred studies (the same) Course".
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 6/24
The question consists of two goals.
To answer this question, Prolog must find a single value for Course, that satisfies both goals.
Read the comma, ",", as and.
However, note that Prolog will evaluate the two goals left-to-right. In pure logic, P1 ∧ P2 is the same as
P2 ∧ P1. In Prolog, there is the practical consideration of which goal should be evaluated first - the code
might be more efficient one way or the other. In particular, in "P1, P2", if P1 fails, then P2 does not need
to be evaluated at all. This is sometimes referred to as a "conditional-and".
Disjunctions of Goals in Queries
What about or (i.e. disjunction)? It turns out explicit ors aren't needed much in Prolog
There is a way to write or: (";")
The reason ors aren't needed much is that
head :- body1.
head :- body2.
has the same effect as
head :- body1 ; body2.
Avoid using ; if you can, at least until you have learned how to manage without it. While some uses of ;
are harmless, others can make your code hard to follow.
To reinforce this message, you will be penalised if you use the or operator ; in the first (Prolog)
assignment in COMP9414. This prohibition means you can't use the … -> … ; … construct either, in the
first assignment. The … -> … ; … construct is not taught in COMP9414, but in the past, some people
have found out about it.
Backtracking in Prolog
Who does Codd teach?
?- lectures(codd, Course), studies(Student, Course).
Course = 9311
Student = jack ;
Course = 9314
Student = jill ;
Course = 9314
Student = henry ;
Prolog solves this problem by proceeding left to right and then backtracking.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 7/24
When given the initial query, Prolog starts by trying to solve
lectures(codd, Course)
There are six lectures clauses, but only two have codd as their first argument.
Prolog uses the first clause that refers to codd: lectures(codd, 9311).
With Course = 9311, it tries to satisfy the next goal, studies(Student, 9311).
It finds the fact studies(jack, 9311). and hence the first solution: (Course = 9311, Student =
jack)
Backtracking in Prolog 2
After the first solution is found, Prolog retraces its steps up the tree and looks for alternative solutions.
First it looks for other students studying 9311 (but finds none).
Then it
backs up
rebinds Course to 9314,
goes down the lectures(codd, 9314) branch
tries studies(Student, 9314),
finds the other two solutions:
(Course = 9314, Student = jill)
and (Course = 9314, Student = henry).
Backtracking in Prolog 3
To picture what happens when Prolog tries to find a solution and backtracks, we draw a "proof tree":
Rules
The previous question can be restated as a general rule:
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 8/24
One person, Teacher, teaches another person, Student if
Teacher lectures in a course, Course and
Student studies Course.
In Prolog this is written as:
teaches(Teacher, Student) :-
lectures(Teacher, Course),
studies(Student, Course).
?- teaches(codd, Student).
Facts are unit clauses and rules are non-unit clauses.
Clause Syntax
":-" means "if" or "is implied by". Also called the neck symbol.
The left hand side of the neck is called the head.
The right hand side of the neck is called the body.
The comma, ",", separating the goals, stands for and.
Another rule, using the predefined predicate ">".
more_advanced(S1, S2) :-
year(S1, Year1),
year(S2, Year2),
Year1 > Year2.
Tracing Execution
more_advanced(S1, S2) :-
year(S1, Year1),
year(S2, Year2),
Year1 > Year2.
?- trace.
true.
[trace] ?- more_advanced(henry, fred).
Call: more_advanced(henry, fred) ? *
Call: year(henry, _L205) ?
Exit: year(henry, 4) ?
Call: year(fred, _L206) ?
Exit: year(fred, 1) ?
^ Call: 4>1 ?
^ Exit: 4>1 ?
Exit: more_advanced(henry, fred) ?
true.
[debug] ?- notrace.
bind S1 to henry, S2 to fred
test 1st goal in body of rule
succeeds, binds Year1 to 4
test 2nd goal in body of rule
succeeds, binds Year2 to 1
test 3rd goal: Year1 > Year2
succeeds
succeeds
* The ? is a prompt. Press the return key at end of each line of tracing. Prolog will echo the <return> as creep,
and then print the next line of tracing. The "creep"s have been removed in the table above, to reduce clutter.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 9/24
true., false., or true
Sometimes, Prolog says true instead of true. (i.e. no full-stop after true).
Prolog does this when it believes it may be able to prove that the query is true in more than one way (and
there are no variables in the query, that it can report bindings for).
Example: suppose we have the following facts and rule:
bad_dog(fido).
bad_dog(Dog) :-
bites(Dog, Person),
is_person(Person),
is_dog(Dog).
bites(fido, postman).
is_person(postman).
is_dog(fido).
There are two ways to prove bad_dog(fido): (a) it's there as a fact; and (b) it can be proven using the
bad_dog rule:
?- bad_dog(fido).
true ;
true.
The missing full-stop prompts us to type ; if we want to check for another proof. The true. that follows
means that a second proof was found. Alternatively, we can just press the "return" key if we are not
interested in whether there is another proof.
You can find more details by looking up true. vs true in the Prolog dictionary.
Structures
Reference: Bratko chapter 2
Functional terms can be used to construct complex data structures.
If we want to say that John owns the novel Tehanu, we can write: owns(john, 'Tehanu').
Often objects have a number of attributes: owns(john, book('Tehanu', leguin)).
The author LeGuin has attributes too: owns(john, book('Tehanu', author (leguin, ursula))).
The arity of a term is the number of arguments it takes.
all versions of owns have arity 2, but the detailed structure of the arguments changes.
gives(john, book, mary). is a term with arity 3.
Asking Questions with Structures
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 10/24
How do we ask, "What books does John own that were written by someone called LeGuin"?
?- owns(john, book(Title, author(leguin, GivenName))).
Title = 'Tehanu'
GivenName = ursula
What books does John own?
?- owns(john, Book).
Book = book('Tehanu', author(leguin, ursula))
What books does John own?
?- owns(john, book(Title, Author)).
Title = 'Tehanu'
Author = author(leguin, ursula)
Prolog performs a complex matching operation between the structures in the query and those in the clause
head.
Library Database Example
A database of books in a library contains facts of the form
book(CatalogNo, Title, author(Family, Given)).
libmember(MemberNo, name(Family, Given), Address).
loan(CatalogNo, MemberNo, BorrowDate, DueDate).
A member of the library may borrow a book.
A "loan" records:
the catalogue number of the book
the number of the member
the date on which the book was borrowed
the due date
Library Database Example 2
Dates are stored as structures:
date(Year, Month, Day)
e.g. date(2012, 6, 16) represents 16 June 2012.
which books has a member borrowed?
borrowed(MemFamily, Title, CatalogNo) :-
libmember(MemberNo, name(MemFamily, _), _),
loan(CatalogNo, MemberNo, _, _),
book(CatalogNo, Title, _).
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 11/24
The underscore or "don't care" variables (_) are used because for the purpose of this query we don't care
about the values in some parts of these structures.
Comparing Two Terms
we would like to know which books are overdue; how do we compare dates?
%later(Date1, Date2) if Date1 is after Date2:
later(date(Y, M, Day1), date(Y, M, Day2)) :-
Day1 > Day2.
later(date(Y, Month1, _), date(Y, Month2, _)) :-
Month1 > Month2.
later(date(Year1, _, _), date(Year2, _, _)) :-
Year1 > Year2.
This rule has three clauses: in any given case, only one clause is appropriate. They are tried in the given
order.
This is how disjunction (or) is often achieved in Prolog. In effect, we are saying that the first date is later
than the second date if Day1 > Day2 and the Y and M are the same, or if the Y is the same and Month1 >
Month2, or if Year1 > Year2.
Footnote: if the year and month are the same, then the heads of all three rules match, and so, while the
first rule is the appropriate one, all three will be tried in the course of backtracking. However, the
condition "Month1 > Month2" in the second rule means that it will fail in this case, and similarly for the
third rule.
More on Comparisons
In the code for later, again we are using the comparison operator ">"
More complex arithmetic expressions can be arguments of comparison operators
- e.g. X + Y >= Z * W * 2.
The available numeric comparison operators are:
Operator Meaning Syntax
> greater than Expression1 > Expression2
< less than Expression1 < Expression2
>= greater than or equal to Expression1 >= Expression2
=< less than or equal to Expression1 =< Expression2
=:= equal to Expression1 =:= Expression2
== not equal to Expression1 == Expression2
All these numerical comparison operators evaluate both their arguments. That is, they evaluate
Expression1 and Expression2.
Overdue Books
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 12/24
% overdue(Today, Title, CatalogNo, MemFamily):
% given the date Today, produces the Title, CatalogNo,
% and MemFamily of all overdue books.
overdue(Today, Title, CatalogNo, MemFamily) :-
loan(CatalogNo, MemberNo, _, DueDate),
later(Today, DueDate),
book(CatalogNo, Title, _),
libmember(MemberNo, name(MemFamily, _), _).
Due Date
Assume the loan period is one month:
due_date(date(Y, Month1, D),
date(Y, Month2, D)) :-
Month1 < 12,
Month2 is Month1 + 1.
due_date(date(Year1, 12, D),
date(Year2, 1, D)) :-
Year2 is Year1 + 1.
You can find a copy of the code for all the library stuff, and a sample (toy) library database, at
http://www.cse.unsw.edu.au/~billw/cs9414/code/library.pro
The is operator
The right hand argument of is must be an arithmetic expression that can be evaluated right now (no
unbound variables).
This expression is evaluated and bound to the left hand argument.
is is not a C-style assignment statement:
X is X + 1 won't work!
except via backtracking, variables can only be bound once, using is or any other way
= does not cause evaluation of its arguments:
?- X = 2, Y = X + 1.
X = 2
Y = 2+1
?- X = 2, Y is X + 1.
X = 2
Y = 3
Use is if and only if you need to evaluate something:
X is 1 BAD! - nothing to evaluate
X = 1 GOOD!
To reinforce the point about the meaning of is, you will be penalised in the first Prolog assignment if you
use it where it is not needed.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 13/24
Order of goals with is
Order of goals matters with is.
Variables on the RHS of is must be instantiated at the time the is goal is tried by Prolog. This is why the
following example fails:
?- X is Y + 1, Y = 3.
ERROR: is/2: Arguments are not sufficiently instantiated
vs
?- Y = 3, X is Y + 1.
Y = 3,
X = 4.
is, = and =:=
You can see the differences between these three Prolog constructs from the following example Prolog
queries:
?- X =:= 3+2.
ERROR: =:=/2: Arguments are
not sufficiently instantiated
X is not currently bound, so can't be evaluated.
?- X = 3+2.
X = 3+2.
= doesn't evaluate, so X is bound to 3+2.
?- X is 3+2.
X = 5.
is does evaluate its right-hand side.
?- 4+1 is 3+2.
false.
3+2 is evaluated to 5.
4+1 is not evaluated. So 4+1 is different from 5.
?- 4+1=3+2.
false.
Neither side is evaluated by =.
The two expressions are different.
?- 4+1 =:= 3+2.
true.
Both sides are evaluated by =:=
= is used for matching, so a more appropriate use would be:
?- likes(mary, X) = likes(Y, pizza).
X = pizza,
Y = mary.
Recursive Programs
Reference: Bratko section 1.3 (doesn't cover trees, though)
Binary Trees
In the library database example, some complex terms contained other terms, for example, book contained
name.
The following term also contains another term, this time one similar to itself:
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 14/24
tree(tree(L1, jack, R1), fred, tree(L2, jill, R2))
The variables L1, L2, R1, and R2 should be bound to sub-trees (this will be clarified shortly).
A structure like this could be used to represent a "binary tree" that looks like:
Binary because each "node" has two branches (our backtrack tree before had many branches at some
nodes)
Recursive Structures
A term that contains another term that has the same principal functor (in this case tree) is said to be
recursive.
Biological trees have leaves. For us, a leaf is a node with two empty branches:
empty is an arbitrary symbol to represent the empty tree. In full, the tree above would be:
tree(tree(empty, jack, empty), fred, tree(empty, jill, empty))
Usually, we wouldn't bother to draw the empty nodes:
Another Tree Example
tree(tree(empty, 7, empty),
'+',
tree(tree(empty, 5, empty),
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 15/24
'-',
tree(empty, 3, empty)))
Recursive Programs for Recursive Structures
A binary tree is either empty or contains some data and a left and right subtree that are also binary trees.
In Prolog we express this as:
is_tree(empty). trivial branch
is_tree(tree(Left, Data, Right)) :-
is_tree(Left),
some_data(Data),
is_tree(Right).
recursive branch
A non-empty tree is represented by a 3-arity term.
Any recursive predicate must have:
(at least) one recursive branch/rule (or it isn't recursive :-) ) and
(at least) one non-recursive or trivial branch (to stop the recursion going on for ever).
The example at the heading "An Application of Lists", below, will show how the recursive branch and the trivial branch work
together. However, you probably shouldn't try to look at it until we have studied lists.
Recursive Programs for Recursive Structures 2
Let us define (or measure) the size of tree (i.e. number of nodes):
tree_size(empty, 0).
tree_size(tree(L, _, R), Total_Size) :-
tree_size(L, Left_Size),
tree_size(R, Right_Size),
Total_Size is
Left_Size + Right_Size + 1.
The size of an empty tree is zero.
The size of a non-empty tree is the size of the left sub-tree plus the size of the
right sub-tree plus one for the current tree node.
The data does not contribute to the total size of the tree.
Recursive data structures need recursive programs. A recursive program is one that refers to itself, thus,
tree_size contains goals that call for the tree_size of smaller trees.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 16/24
Lists
Reference: Bratko chapter 3
A list may be nil (i.e. empty) or it may be a term that has a head and a tail
The head may be any term or atom.
The tail is another list.
We could define lists as follows:
is_list(nil).
is_list(list(Head, Tail)) :-
is_list(Tail).
A list of numbers [1, 2, 3] would look like:
list(1, list(2, list(3, nil)))
This notation is understandable but clumsy. Prolog doesn't actually recognise it, and in fact uses . instead
of list and [] instead of nil. So Prolog would recognise .(1, .(2, .(3, []))) as a list of three
numbers. This is briefer but still looks strange, and is hard to work with.
Since lists are used so often, Prolog in fact has a special notation that encloses the list members in square
brackets:
[1, 2, 3] = .(1, .(2, .(3, [])))
?- X = .(1, .(2, .(3, []))).
X = [1, 2, 3]
List Constructor |
Within the square brackets [ ], the symbol | acts as an operator to construct a list from an item and
another list.
?- X = [1 | [2, 3]].
X = [1, 2, 3].
?- Head = 1 , Tail = [2, 3], List = [Head | Tail].
List = [1, 2, 3].
Examples of Lists and Pattern Matching
?- [X, Y, Z] = [1, 2, 3]. Match the terms on either side of =
X = 1
Y = 2
Z = 3
?- [X | Y] = [1, 2, 3]. | separates head from tail of list.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 17/24
X = 1 So [First | Rest] is the usual way
Y = [2, 3] of writing .(First, Rest) in Prolog
?- [X | Y] = [1].
X = 1
Y = []
The empty list is written as []
Lists "end" in an empty list!
Note that [1] is a list with one element.
The first several elements of the list can be selected before matching the tail:
?- [X, Y | Z] = [fred, jim, jill, mary].
X = fred
Y = jim
Z = [jill, mary]
Must be at least two elements
in the list on the right.
More Complex List Matching
?- [X | Y] = [[a, f(e)], [n, m, [2]]].
X = [a, f(e)]
Y = [[n, m, [2]]]
Notice that Y is shown with an extra pair of brackets: Y is the tail of the entire list: [n, m, [2]] is the sole
element of Y.
List Membership
A term is a member of a list if
the term is the same as the head of the list, or
the term is a member of the tail of the list.
In Prolog:
member(X, [X | _]).
trivial branch:
a rule with a head but no body
member(X, [_ | Y]) :-
member(X, Y).
recursive branch
The first rule has the same effect as: member(X, [Y|_]) :- X = Y.
The form member(X, [X|_]). is preferred, as it avoids the extra calculation.
member is actually predefined in Prolog. It is a built-in predicate. There are quite a few built-in predicates
in Prolog. We do not have the time to find out about most of them in COMP9414. Look at the COMP9814
Prolog Extension notes if you want to get an idea about some of the built-in predicates. "Pre-defined"
means that you do not need to put the rules for member into your code - Prolog already knows the
definition of member. Do not re-define predefined predicates.
= in goals
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 18/24
Earlier, we said:
X = 1 GOOD!
Actually, goals with = in them are mostly avoidable and should be avoided. Beginnner Prolog programmers are
tempted to use = frequently, to tie together variables that they now realise should be the same:
% length(List, LengthOfList)
% binds LengthOfList to the number of elements in List.
length([OnlyMember], Length) :-
Length = 1.
length([First | Rest], Length) :-
length(Rest, LengthOfRest),
Length is LengthOfRest + 1.
This works, but involves an unnecessary unification. It is better for the base case to be
length([OnlyMember], 1).
In effect, we take the original version of the base case, and replace Length, in the head of the rule, with the
thing that Length is = to. Programmers who fail to do this are usually still thinking procedurally.
Programming Principles for Recursive Structures
Only deal with one element at a time.
Believe that the recursive program you are writing has already been written.
In the definition of member, we are already assuming that we know how to find a member in the tail.
Write definitions, not programs!
If you are used to writing programs for conventional languages, then you are used to giving
instructions on how to perform certain operations.
In Prolog, you define relationships between objects and let the system do its best to construct
objects that satisfy the given relationship.
Concatenating Two Lists
Suppose we want to take two lists, like [1, 3] and [5, 2] and concatenate them to make [1, 3, 5,
2]
The header comment is:
% concat(List1, List2, Concat_List1_List2)
% Concat_List1_List2 is the concatenation of List1 & List2
There are two rules:
First, the trivial branch:
concat([], List2, List2).
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 19/24
Next, the recursive branch:
concat([Item | Tail1], List2, [Item | Concat_Tail1_List2]) :-
concat(Tail1, List2, Concat_Tail1_List2).
For example, consider
?- concat([1], [2], [1, 2]).
By the recursive branch:
concat([1 | []], [2], [1 | [2]]) :-
concat([], [2], [2]).
and concat([], [2], [2]) holds because of the trivial branch.
The entire program is:
% concat(List1, List2, Concat_List1_List2):
% Concat_List1_List2 is the concatenation of List1 & List2
concat([], List2, List2).
concat([Item | Tail1], List2, [Item | Concat_Tail1_List2]) :-
concat(Tail1, List2, Concat_Tail1_List2).
An Application of Lists
Find the total cost of a list of items:
Cost data:
cost(cornflakes, 230).
cost(cocacola, 210).
cost(chocolate, 250).
cost(crisps, 190).
Rules:
total_cost([], 0). % trivial branch
total_cost([Item|Rest], Cost) :- % recursive branch
cost(Item, ItemCost),
total_cost(Rest, CostOfRest),
Cost is ItemCost + CostOfRest.
Sample query:
?- total_cost([cornflakes, crisps], X).
X = 420
Tracing total_cost
?- trace.
true.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 20/24
[trace] ?- total_cost([cornflakes, crisps], X).
Call: (7) total_cost([cornflakes, crisps], _G290) ? creep
Call: (8) cost(cornflakes, _L207) ? creep
Exit: (8) cost(cornflakes, 230) ? creep
Call: (8) total_cost([crisps], _L208) ? creep
Call: (9) cost(crisps, _L228) ? creep
Exit: (9) cost(crisps, 190) ? creep
Call: (9) total_cost([], _L229) ? creep
Exit: (9) total_cost([], 0) ? creep
^ Call: (9) _L208 is 190+0 ? creep
^ Exit: (9) 190 is 190+0 ? creep
Exit: (8) total_cost([crisps], 190) ? creep
^ Call: (8) _G290 is 230+190 ? creep
^ Exit: (8) 420 is 230+190 ? creep
Exit: (7) total_cost([cornflakes, crisps], 420) ? creep
X = 420
[debug] ?- notrace.
Modifying total_cost
This is an optional homework exercise.
What happens if we change the recursive branch rule for total_cost as shown below?
total_cost([Item|Rest], Cost) :-
total_cost(Rest, CostOfRest),
cost(Item, ItemCost),
Cost is ItemCost + CostOfRest.
The second and third lines have been swapped around.
You'll find that the rule still works. Try tracing the new version of this rule, work out what happens differently.
Which version do you find easier to understand? Why do think this is the case?
Another list-processing procedure
The next procedure removes duplicates from a list.
It has three rules. This is an example of a common list-processing template.
Algorithm:
If the list is empty, there's nothing to do.
If the first item of the list is a member of the rest of the list, then discard it, and remove duplicates
from the rest of the list.
Otherwise, keep the first item, and again, remove any duplicates from the rest of the list.
% remove_dups(+List, -NewList):
% New List isbound to List, but with duplicate items removed.
remove_dups([], []).
remove_dups([First | Rest], NewRest) :-
member(First, Rest),
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 21/24
remove_dups(Rest, NewRest).
remove_dups([First | Rest], [First | NewRest]) :-
not(member(First, Rest)),
remove_dups(Rest, NewRest).
?- remove_dups([1,2,3,1,3,4], X).
X = [2, 1, 3, 4] ;
false.
Note the use of not to negate a condition. An alternative to not is +. See the article on negation in the
Prolog dictionary to find out why there are two names for not.
Singleton Variables
If Prolog finds a variable name that you only use once in a rule, it assumes that it may be a spelling
mistake, and issues a Warning about a "singleton variable" when you load the code:
% prolog -q -s mycode.pl
Warning: .../mycode.pl:4:
Singleton variables: [Item]
The -q means "quiet" - i.e. don't print the SWI Prolog welcome message. This way, any warnings are
easier to notice.
Here is the code that produced this (with line numbers added):
1 % count(Item, List, Count) counts the number of times the
2 % Item occurs in the List, and binds Count to that number.
3
4 count(Item, [], 0).
5 count(Item, [Item | Rest], Count) :-
6 count(Item, Rest, RestCount),
7 Count is RestCount + 1.
8 count(Item, [Other | Rest], Count) :-
9 not(Item = Other),
10 count(Item, Rest, Count).
To suppress the warning, put an _ in front of the word Item on line 4 (only). This makes it "don't care"
variable. Check for the possible spelling error, first!
4 count(_Item, [], 0).
See also the entry on singleton variables in the Prolog dictionary.
Controlling Execution
Reference: Bratko chapter 5
The Cut Operator (!)
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 22/24
Sometimes we need a way to prevent Prolog finding all solutions, i.e. a way to stop backtracking.
The cut operator, written !, is a built-in goal that prevents backtracking.
It turns Prolog from a nice declarative language into a hybrid monster.
Use cuts sparingly and with a sense of having sinned.
Cut Operator 2
Recall this example:
Cut Prunes the Search Tree
If the goal(s) to the right of the cut fail then the entire clause fails and the the goal that caused this clause
to be invoked fails.
In particular, alternatives for Course are not explored.
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 23/24
Cut Prunes the Search Tree 2
Another example: using the facts03 database, try
?- lectures(codd, X).
X = 9311 ;
X = 9314.
?- lectures(codd, X), ! .
X = 9311.
The cut in the second version of the query prevents Prolog from backtracking to find the second solution.
Using cuts in later to improve efficiency
Recall the code for later:
later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2.
later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2.
later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2.
We note that if year and month are the same, all three rules are tried while backtracking. This could be prevented
by adding cuts:
later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2, !.
later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2, !.
later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2.
This would increase efficiency by eliminating unnecessary backtracking, though it is doubtful if it would be
worth bothering about, unless you actually have code that is running too slowly. In that case you should first do
an analysis of where the time is being spent, before putting in cuts everywhere!
In other cases, adding cuts of this sort to multi-rule procedures might be a useful (if lazy) way of ensuring that
only one rule is used in a particular case. Unless it makes the code very clumsy, it is better to use and rely on
"condition" goals in each rule (like M1 > M2 in the second rule for later) to specify the case in which it is
appropriate. More examples of this are below.
Another cut example
max, without cut:
% max(A, B, C) binds C to the larger of A and B.
max(A, B, A) :-
A > B.
max(A, B, B) :-
A =< B.
max, with cut:
max(A, B, A) :-
A > B,
11/18/2019 Introduction to Prolog
www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 24/24
!.
max(A, B, B).
The first version has a negated test in the second rule (=< vs >). The second version substitutes a cut in the
first rule for the negated test.
Remember, no cuts in the first assignment unless they are essential! Hint: the first assignment can be done
without cuts.
Another cut example 2
remove_dups, without cut:
remove_dups([], []).
remove_dups([First | Rest], NewRest) :-
member(First, Rest),
remove_dups(Rest, NewRest).
remove_dups([First | Rest], [First | NewRest]) :-
not(member(First, Rest)),
remove_dups(Rest, NewRest).
remove_dups, with cut:
remove_dups([], []).
remove_dups([First | Rest], NewRest) :-
member(First, Rest),
!,
remove_dups(Rest, NewRest).
remove_dups([First | Rest], [First | NewRest]) :-
remove_dups(Rest, NewRest).
The first version has a negated test in the third rule (not(member(First, Rest))). The second version
substitutes a cut in the second rule for the negated test in the third rule.
Summary: Introduction to Prolog
We have introduced facts, queries, variables, conjunctions of goals, rules, structures, recursion, trees and lists,
and controlling execution by means of the "cut".
CRICOS Provider Code No. 00098G
Last updated on: 27 February 2012
Copyright © Bill Wilson, 1996-2012, except where another source is acknowledged: much of the material in
these notes is based on an earlier edition by Claude Sammut. Certain improvements are due to Maurice
Pagnucco. Images of Bratko, Kowalski, and Colmerauer were obtained from Google Images.

More Related Content

PPTX
ProLog (Artificial Intelligence) Introduction
PPTX
Database , 4 Data Integration
PPTX
Lec 8 (distributed database)
PPTX
Predicate logic
PPTX
Distributed DBMS - Unit 1 - Introduction
PPTX
Knowledge based agents
PPTX
First order logic
PPT
First order logic
ProLog (Artificial Intelligence) Introduction
Database , 4 Data Integration
Lec 8 (distributed database)
Predicate logic
Distributed DBMS - Unit 1 - Introduction
Knowledge based agents
First order logic
First order logic

What's hot (20)

PPT
Knowledge Representation in Artificial intelligence
PPTX
Temporal databases
PPTX
blackboard architecture
PPTX
Multimedia Database
PDF
Object oriented databases
PPT
predicate logic example
PPT
10. XML in DBMS
PPT
MySQL Transactions
PPT
Distributed Database Management System
PPTX
Kr using rules
PDF
Dbms 2: Data Model
PPTX
Distributed dbms
PPTX
Serialization
PDF
The CAP Theorem
PPT
Distributed Database System
PPT
Cloud service management
PPTX
Distributed DBMS - Unit 8 - Distributed Transaction Management & Concurrency ...
PPTX
Cloud federation.pptx
PDF
Apache Kafka and the Data Mesh | Michael Noll, Confluent
PPTX
PROLOG: Introduction To Prolog
Knowledge Representation in Artificial intelligence
Temporal databases
blackboard architecture
Multimedia Database
Object oriented databases
predicate logic example
10. XML in DBMS
MySQL Transactions
Distributed Database Management System
Kr using rules
Dbms 2: Data Model
Distributed dbms
Serialization
The CAP Theorem
Distributed Database System
Cloud service management
Distributed DBMS - Unit 8 - Distributed Transaction Management & Concurrency ...
Cloud federation.pptx
Apache Kafka and the Data Mesh | Michael Noll, Confluent
PROLOG: Introduction To Prolog
Ad

Similar to Introduction to prolog (20)

PDF
Prolog,Prolog Programming IN AI.pdf
PDF
ICS1019.pdf
PPTX
Ics1019 ics5003
PDF
Logic Progamming in Perl
PPTX
Ics1019 ics5003
PPTX
Prolog Programming : Basics
PDF
1066_multitask_prompted_training_en.pdf
PPT
NLP Natural Language Processing 8th Chapter.ppt
PPT
2 Prolog L 1 V2.ppt
PPTX
MACHINE LEARNING-LEARNING RULE
PPT
Introduction to logic and prolog - Part 1
PPT
Tarek Almiski Scientists In The Schools
PDF
Introduction To Objectoriented Programming An 3rd Edition Timothy Budd
PDF
Course Design Best Practices
PPTX
Publishability workshop: Writing readable academic text
DOCX
FIX-IT (REVISE THIS DRAFT) Revise this paragraph. The rev
PPTX
COMP1409-lesson01.pptx
DOCX
Java OOPs Concepts.docx
PPTX
artificial intelligence.pptx
Prolog,Prolog Programming IN AI.pdf
ICS1019.pdf
Ics1019 ics5003
Logic Progamming in Perl
Ics1019 ics5003
Prolog Programming : Basics
1066_multitask_prompted_training_en.pdf
NLP Natural Language Processing 8th Chapter.ppt
2 Prolog L 1 V2.ppt
MACHINE LEARNING-LEARNING RULE
Introduction to logic and prolog - Part 1
Tarek Almiski Scientists In The Schools
Introduction To Objectoriented Programming An 3rd Edition Timothy Budd
Course Design Best Practices
Publishability workshop: Writing readable academic text
FIX-IT (REVISE THIS DRAFT) Revise this paragraph. The rev
COMP1409-lesson01.pptx
Java OOPs Concepts.docx
artificial intelligence.pptx
Ad

Recently uploaded (20)

PDF
August Patch Tuesday
PDF
Empathic Computing: Creating Shared Understanding
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Encapsulation theory and applications.pdf
PDF
Heart disease approach using modified random forest and particle swarm optimi...
PPTX
A Presentation on Artificial Intelligence
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
1. Introduction to Computer Programming.pptx
PPTX
OMC Textile Division Presentation 2021.pptx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
Tartificialntelligence_presentation.pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
August Patch Tuesday
Empathic Computing: Creating Shared Understanding
Univ-Connecticut-ChatGPT-Presentaion.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Group 1 Presentation -Planning and Decision Making .pptx
A comparative analysis of optical character recognition models for extracting...
MIND Revenue Release Quarter 2 2025 Press Release
Encapsulation theory and applications.pdf
Heart disease approach using modified random forest and particle swarm optimi...
A Presentation on Artificial Intelligence
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Agricultural_Statistics_at_a_Glance_2022_0.pdf
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
Unlocking AI with Model Context Protocol (MCP)
Spectral efficient network and resource selection model in 5G networks
1. Introduction to Computer Programming.pptx
OMC Textile Division Presentation 2021.pptx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Tartificialntelligence_presentation.pptx
Network Security Unit 5.pdf for BCA BBA.

Introduction to prolog

  • 1. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 1/24 COMP9414/9814 Artificial Intelligence INTRODUCTION TO PROLOG PROGRAMMING Reference:Bratko, I., Programming in Prolog for Artificial Intelligence, 4th Edition, Addison-Wesley, 2011, chapters 1-5 Aim: To introduce enough of Prolog to allow students to do the assignment work in this course, thereby gaining some experience of AI programming. Plan: What is Prolog? Programming with relations. Facts Questions Variables Conjunctions of goals, backtracking Rules Structures Recursive programs Lists Controlling execution - the cut What is Prolog? invented early seventies by Alain Colmerauer in France and Robert Kowalski in Britain. (There is a recent 2-page article by Kowalski at http://www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/Kowalski.pdf). Note that historical information in these lectures is not examinable. Prolog = Programmation en Logique (Programming in Logic). Prolog is a declarative programming language unlike most common programming languages. In a declarative language the programmer specifies a goal to be achieved the Prolog system works out how to achieve it relational databases owe something to Prolog Alain Colmerauer Robert Kowalski What is Prolog? (continued) traditional programming languages are said to be procedural procedural programmer must specify in detail how to solve a problem: mix ingredients; beat until smooth; bake for 20 minutes in a moderate oven; remove tin from oven; put on bench; close oven; turn off oven;
  • 2. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 2/24 in purely declarative languages, the programmer only states what the problem is and leaves the rest to the language system We'll see specific, simple examples of cases where Prolog fits really well shortly Applications of Prolog Some applications of Prolog are: intelligent data base retrieval natural language understanding expert systems specification language machine learning robot planning automated reasoning problem solving The Prolog Language Reference: Bratko, Chapter 1 Ivan Bratko Relations Prolog programs specify relationships among objects and properties of objects. When we say, "John owns the book", we are declaring the ownership relationship between two objects: John and the book. When we ask, "Does John own the book?" we are trying to find out about a relationship. Relationships can also rules such as: Two people are sisters if they are both female and they have the same parents. A rule allows us to find out about a relationship even if the relationship isn't explicitly stated as a fact.
  • 3. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 3/24 A little more on being sisters As usual in programming, you need to be a bit careful how you phrase things: The following would be better: A and B are sisters if A and B are both female and they have the same father and they have the same mother and A is not the same as B Programming in Prolog declare facts describing explicit relationships between objects and properties objects might have (e.g. Mary likes pizza, grass has_colour green, Fido is_a_dog, Mizuki taught Paul Japanese ) define rules defining implicit relationships between objects (e.g. the sister rule above) and/or rules defining implicit object properties (e.g. X is a parent if there is a Y such that Y is a child of X). One then uses the system by: asking questions above relationships between objects, and/or about object properties (e.g. does Mary like pizza? is Joe a parent?) Facts Properties of objects, or relationships between objects; "Dr Turing lectures in course 9020", is written in Prolog as: lectures(turing, 9020). Notice that: names of properties/relationships begin with lower case letters. the relationship name appears as the first term objects appear as comma-separated arguments within parentheses. A period "." must end a fact. objects also begin with lower case letters. They also can begin with digits (like 9020), and can be strings of characters enclosed in quotes (as in reads(fred, "War and Peace")). lectures(turing, 9020). is also called a predicate Facts about a hypothetical computer science department: % lectures(X, Y): person X lectures in course Y lectures(turing, 9020). lectures(codd, 9311). lectures(backus, 9021). lectures(ritchie, 9201). lectures(minsky, 9414). lectures(codd, 9314).
  • 4. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 4/24 % studies(X, Y): person X studies in course Y studies(fred, 9020). studies(jack, 9311). studies(jill, 9314). studies(jill, 9414). studies(henry, 9414). studies(henry, 9314). %year(X, Y): person X is in year Y year(fred, 1). year(jack, 2). year(jill, 2). year(henry, 4). Together, these facts form Prolog's database. Should you wish to experiment with them using Prolog, they are available at http://www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/facts03. Queries Once we have a database of facts (and, soon, rules) we can ask questions about the stored information. Suppose we want to know if Turing lectures in course 9020. We can ask: % prolog -s facts03 (multi-line welcome message) ?- lectures(turing, 9020). true. ?- <control-D> % facts03 loaded into Prolog "?-" is Prolog's prompt output from Prolog hold down control & press D to leave Prolog Notice that: In SWI Prolog, queries are terminated by a full stop. To answer this query, Prolog consults its database to see if this is a known fact. In example dialogues with Prolog, the text in green italics is what the user types. Another example query ?- lectures(codd, 9020). false. if answer is true., the query succeeded if answer is false., the query failed. Note: many early versions of Prolog, including early versions of SWI-Prolog, say No instead of false. See the article on negation in the Prolog dictionary to find out why No. is a more accurate description of what is happening. In the latest version of SWI Prolog, it no longer says "No." but says "false." instead. The use of lower case for codd is critical.
  • 5. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 5/24 Prolog is not being intelligent about this - it would not see a difference between this query and lectures(fred, 9020). or lectures(xyzzy, 9020). though a person inspecting the database can see that fred is a student, not a lecturer, and that xyzzy is neither student nor lecturer. Variables Suppose we want to ask, "What course does Turing teach"? This could be written as: Is there a course, X, that Turing teaches? The variable X stands for an object that the questioner does not know about yet. To answer the question, Prolog has to find out the value of X, if it exists. As long as we do not know the value of a variable it is said to be unbound. When a value is found, the variable is said to bound to that value. The name of a variable must begin with a capital letter or an underscore character, "_". Variables 2 To ask Prolog to find the course that Turing teaches, enter this: ?- lectures(turing, Course). Course = 9020 ← output from Prolog To ask which course(s) Prof. Codd teaches, we may ask, ?- lectures(codd , Course). Course = 9311 ; ← type ";" to get next solution Course = 9314 ?- If Prolog can tell that there are no more solutions, it just gives you the ?- prompt for a new query, as here. If Prolog can't tell, it will let you type ; again, and then if there is no further solution, report false. Prolog can find all possible ways to answer a query, unless you explicitly tell it not to (see cut, later). Conjunctions of Goals in Queries How do we ask, "Does Turing teach Fred"? This means finding out if Turing lectures in a course that Fred studies. ?- lectures(turing, Course), studies(fred, Course). i.e. "Turing lectures in course, Course and Fred studies (the same) Course".
  • 6. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 6/24 The question consists of two goals. To answer this question, Prolog must find a single value for Course, that satisfies both goals. Read the comma, ",", as and. However, note that Prolog will evaluate the two goals left-to-right. In pure logic, P1 ∧ P2 is the same as P2 ∧ P1. In Prolog, there is the practical consideration of which goal should be evaluated first - the code might be more efficient one way or the other. In particular, in "P1, P2", if P1 fails, then P2 does not need to be evaluated at all. This is sometimes referred to as a "conditional-and". Disjunctions of Goals in Queries What about or (i.e. disjunction)? It turns out explicit ors aren't needed much in Prolog There is a way to write or: (";") The reason ors aren't needed much is that head :- body1. head :- body2. has the same effect as head :- body1 ; body2. Avoid using ; if you can, at least until you have learned how to manage without it. While some uses of ; are harmless, others can make your code hard to follow. To reinforce this message, you will be penalised if you use the or operator ; in the first (Prolog) assignment in COMP9414. This prohibition means you can't use the … -> … ; … construct either, in the first assignment. The … -> … ; … construct is not taught in COMP9414, but in the past, some people have found out about it. Backtracking in Prolog Who does Codd teach? ?- lectures(codd, Course), studies(Student, Course). Course = 9311 Student = jack ; Course = 9314 Student = jill ; Course = 9314 Student = henry ; Prolog solves this problem by proceeding left to right and then backtracking.
  • 7. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 7/24 When given the initial query, Prolog starts by trying to solve lectures(codd, Course) There are six lectures clauses, but only two have codd as their first argument. Prolog uses the first clause that refers to codd: lectures(codd, 9311). With Course = 9311, it tries to satisfy the next goal, studies(Student, 9311). It finds the fact studies(jack, 9311). and hence the first solution: (Course = 9311, Student = jack) Backtracking in Prolog 2 After the first solution is found, Prolog retraces its steps up the tree and looks for alternative solutions. First it looks for other students studying 9311 (but finds none). Then it backs up rebinds Course to 9314, goes down the lectures(codd, 9314) branch tries studies(Student, 9314), finds the other two solutions: (Course = 9314, Student = jill) and (Course = 9314, Student = henry). Backtracking in Prolog 3 To picture what happens when Prolog tries to find a solution and backtracks, we draw a "proof tree": Rules The previous question can be restated as a general rule:
  • 8. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 8/24 One person, Teacher, teaches another person, Student if Teacher lectures in a course, Course and Student studies Course. In Prolog this is written as: teaches(Teacher, Student) :- lectures(Teacher, Course), studies(Student, Course). ?- teaches(codd, Student). Facts are unit clauses and rules are non-unit clauses. Clause Syntax ":-" means "if" or "is implied by". Also called the neck symbol. The left hand side of the neck is called the head. The right hand side of the neck is called the body. The comma, ",", separating the goals, stands for and. Another rule, using the predefined predicate ">". more_advanced(S1, S2) :- year(S1, Year1), year(S2, Year2), Year1 > Year2. Tracing Execution more_advanced(S1, S2) :- year(S1, Year1), year(S2, Year2), Year1 > Year2. ?- trace. true. [trace] ?- more_advanced(henry, fred). Call: more_advanced(henry, fred) ? * Call: year(henry, _L205) ? Exit: year(henry, 4) ? Call: year(fred, _L206) ? Exit: year(fred, 1) ? ^ Call: 4>1 ? ^ Exit: 4>1 ? Exit: more_advanced(henry, fred) ? true. [debug] ?- notrace. bind S1 to henry, S2 to fred test 1st goal in body of rule succeeds, binds Year1 to 4 test 2nd goal in body of rule succeeds, binds Year2 to 1 test 3rd goal: Year1 > Year2 succeeds succeeds * The ? is a prompt. Press the return key at end of each line of tracing. Prolog will echo the <return> as creep, and then print the next line of tracing. The "creep"s have been removed in the table above, to reduce clutter.
  • 9. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 9/24 true., false., or true Sometimes, Prolog says true instead of true. (i.e. no full-stop after true). Prolog does this when it believes it may be able to prove that the query is true in more than one way (and there are no variables in the query, that it can report bindings for). Example: suppose we have the following facts and rule: bad_dog(fido). bad_dog(Dog) :- bites(Dog, Person), is_person(Person), is_dog(Dog). bites(fido, postman). is_person(postman). is_dog(fido). There are two ways to prove bad_dog(fido): (a) it's there as a fact; and (b) it can be proven using the bad_dog rule: ?- bad_dog(fido). true ; true. The missing full-stop prompts us to type ; if we want to check for another proof. The true. that follows means that a second proof was found. Alternatively, we can just press the "return" key if we are not interested in whether there is another proof. You can find more details by looking up true. vs true in the Prolog dictionary. Structures Reference: Bratko chapter 2 Functional terms can be used to construct complex data structures. If we want to say that John owns the novel Tehanu, we can write: owns(john, 'Tehanu'). Often objects have a number of attributes: owns(john, book('Tehanu', leguin)). The author LeGuin has attributes too: owns(john, book('Tehanu', author (leguin, ursula))). The arity of a term is the number of arguments it takes. all versions of owns have arity 2, but the detailed structure of the arguments changes. gives(john, book, mary). is a term with arity 3. Asking Questions with Structures
  • 10. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 10/24 How do we ask, "What books does John own that were written by someone called LeGuin"? ?- owns(john, book(Title, author(leguin, GivenName))). Title = 'Tehanu' GivenName = ursula What books does John own? ?- owns(john, Book). Book = book('Tehanu', author(leguin, ursula)) What books does John own? ?- owns(john, book(Title, Author)). Title = 'Tehanu' Author = author(leguin, ursula) Prolog performs a complex matching operation between the structures in the query and those in the clause head. Library Database Example A database of books in a library contains facts of the form book(CatalogNo, Title, author(Family, Given)). libmember(MemberNo, name(Family, Given), Address). loan(CatalogNo, MemberNo, BorrowDate, DueDate). A member of the library may borrow a book. A "loan" records: the catalogue number of the book the number of the member the date on which the book was borrowed the due date Library Database Example 2 Dates are stored as structures: date(Year, Month, Day) e.g. date(2012, 6, 16) represents 16 June 2012. which books has a member borrowed? borrowed(MemFamily, Title, CatalogNo) :- libmember(MemberNo, name(MemFamily, _), _), loan(CatalogNo, MemberNo, _, _), book(CatalogNo, Title, _).
  • 11. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 11/24 The underscore or "don't care" variables (_) are used because for the purpose of this query we don't care about the values in some parts of these structures. Comparing Two Terms we would like to know which books are overdue; how do we compare dates? %later(Date1, Date2) if Date1 is after Date2: later(date(Y, M, Day1), date(Y, M, Day2)) :- Day1 > Day2. later(date(Y, Month1, _), date(Y, Month2, _)) :- Month1 > Month2. later(date(Year1, _, _), date(Year2, _, _)) :- Year1 > Year2. This rule has three clauses: in any given case, only one clause is appropriate. They are tried in the given order. This is how disjunction (or) is often achieved in Prolog. In effect, we are saying that the first date is later than the second date if Day1 > Day2 and the Y and M are the same, or if the Y is the same and Month1 > Month2, or if Year1 > Year2. Footnote: if the year and month are the same, then the heads of all three rules match, and so, while the first rule is the appropriate one, all three will be tried in the course of backtracking. However, the condition "Month1 > Month2" in the second rule means that it will fail in this case, and similarly for the third rule. More on Comparisons In the code for later, again we are using the comparison operator ">" More complex arithmetic expressions can be arguments of comparison operators - e.g. X + Y >= Z * W * 2. The available numeric comparison operators are: Operator Meaning Syntax > greater than Expression1 > Expression2 < less than Expression1 < Expression2 >= greater than or equal to Expression1 >= Expression2 =< less than or equal to Expression1 =< Expression2 =:= equal to Expression1 =:= Expression2 == not equal to Expression1 == Expression2 All these numerical comparison operators evaluate both their arguments. That is, they evaluate Expression1 and Expression2. Overdue Books
  • 12. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 12/24 % overdue(Today, Title, CatalogNo, MemFamily): % given the date Today, produces the Title, CatalogNo, % and MemFamily of all overdue books. overdue(Today, Title, CatalogNo, MemFamily) :- loan(CatalogNo, MemberNo, _, DueDate), later(Today, DueDate), book(CatalogNo, Title, _), libmember(MemberNo, name(MemFamily, _), _). Due Date Assume the loan period is one month: due_date(date(Y, Month1, D), date(Y, Month2, D)) :- Month1 < 12, Month2 is Month1 + 1. due_date(date(Year1, 12, D), date(Year2, 1, D)) :- Year2 is Year1 + 1. You can find a copy of the code for all the library stuff, and a sample (toy) library database, at http://www.cse.unsw.edu.au/~billw/cs9414/code/library.pro The is operator The right hand argument of is must be an arithmetic expression that can be evaluated right now (no unbound variables). This expression is evaluated and bound to the left hand argument. is is not a C-style assignment statement: X is X + 1 won't work! except via backtracking, variables can only be bound once, using is or any other way = does not cause evaluation of its arguments: ?- X = 2, Y = X + 1. X = 2 Y = 2+1 ?- X = 2, Y is X + 1. X = 2 Y = 3 Use is if and only if you need to evaluate something: X is 1 BAD! - nothing to evaluate X = 1 GOOD! To reinforce the point about the meaning of is, you will be penalised in the first Prolog assignment if you use it where it is not needed.
  • 13. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 13/24 Order of goals with is Order of goals matters with is. Variables on the RHS of is must be instantiated at the time the is goal is tried by Prolog. This is why the following example fails: ?- X is Y + 1, Y = 3. ERROR: is/2: Arguments are not sufficiently instantiated vs ?- Y = 3, X is Y + 1. Y = 3, X = 4. is, = and =:= You can see the differences between these three Prolog constructs from the following example Prolog queries: ?- X =:= 3+2. ERROR: =:=/2: Arguments are not sufficiently instantiated X is not currently bound, so can't be evaluated. ?- X = 3+2. X = 3+2. = doesn't evaluate, so X is bound to 3+2. ?- X is 3+2. X = 5. is does evaluate its right-hand side. ?- 4+1 is 3+2. false. 3+2 is evaluated to 5. 4+1 is not evaluated. So 4+1 is different from 5. ?- 4+1=3+2. false. Neither side is evaluated by =. The two expressions are different. ?- 4+1 =:= 3+2. true. Both sides are evaluated by =:= = is used for matching, so a more appropriate use would be: ?- likes(mary, X) = likes(Y, pizza). X = pizza, Y = mary. Recursive Programs Reference: Bratko section 1.3 (doesn't cover trees, though) Binary Trees In the library database example, some complex terms contained other terms, for example, book contained name. The following term also contains another term, this time one similar to itself:
  • 14. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 14/24 tree(tree(L1, jack, R1), fred, tree(L2, jill, R2)) The variables L1, L2, R1, and R2 should be bound to sub-trees (this will be clarified shortly). A structure like this could be used to represent a "binary tree" that looks like: Binary because each "node" has two branches (our backtrack tree before had many branches at some nodes) Recursive Structures A term that contains another term that has the same principal functor (in this case tree) is said to be recursive. Biological trees have leaves. For us, a leaf is a node with two empty branches: empty is an arbitrary symbol to represent the empty tree. In full, the tree above would be: tree(tree(empty, jack, empty), fred, tree(empty, jill, empty)) Usually, we wouldn't bother to draw the empty nodes: Another Tree Example tree(tree(empty, 7, empty), '+', tree(tree(empty, 5, empty),
  • 15. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 15/24 '-', tree(empty, 3, empty))) Recursive Programs for Recursive Structures A binary tree is either empty or contains some data and a left and right subtree that are also binary trees. In Prolog we express this as: is_tree(empty). trivial branch is_tree(tree(Left, Data, Right)) :- is_tree(Left), some_data(Data), is_tree(Right). recursive branch A non-empty tree is represented by a 3-arity term. Any recursive predicate must have: (at least) one recursive branch/rule (or it isn't recursive :-) ) and (at least) one non-recursive or trivial branch (to stop the recursion going on for ever). The example at the heading "An Application of Lists", below, will show how the recursive branch and the trivial branch work together. However, you probably shouldn't try to look at it until we have studied lists. Recursive Programs for Recursive Structures 2 Let us define (or measure) the size of tree (i.e. number of nodes): tree_size(empty, 0). tree_size(tree(L, _, R), Total_Size) :- tree_size(L, Left_Size), tree_size(R, Right_Size), Total_Size is Left_Size + Right_Size + 1. The size of an empty tree is zero. The size of a non-empty tree is the size of the left sub-tree plus the size of the right sub-tree plus one for the current tree node. The data does not contribute to the total size of the tree. Recursive data structures need recursive programs. A recursive program is one that refers to itself, thus, tree_size contains goals that call for the tree_size of smaller trees.
  • 16. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 16/24 Lists Reference: Bratko chapter 3 A list may be nil (i.e. empty) or it may be a term that has a head and a tail The head may be any term or atom. The tail is another list. We could define lists as follows: is_list(nil). is_list(list(Head, Tail)) :- is_list(Tail). A list of numbers [1, 2, 3] would look like: list(1, list(2, list(3, nil))) This notation is understandable but clumsy. Prolog doesn't actually recognise it, and in fact uses . instead of list and [] instead of nil. So Prolog would recognise .(1, .(2, .(3, []))) as a list of three numbers. This is briefer but still looks strange, and is hard to work with. Since lists are used so often, Prolog in fact has a special notation that encloses the list members in square brackets: [1, 2, 3] = .(1, .(2, .(3, []))) ?- X = .(1, .(2, .(3, []))). X = [1, 2, 3] List Constructor | Within the square brackets [ ], the symbol | acts as an operator to construct a list from an item and another list. ?- X = [1 | [2, 3]]. X = [1, 2, 3]. ?- Head = 1 , Tail = [2, 3], List = [Head | Tail]. List = [1, 2, 3]. Examples of Lists and Pattern Matching ?- [X, Y, Z] = [1, 2, 3]. Match the terms on either side of = X = 1 Y = 2 Z = 3 ?- [X | Y] = [1, 2, 3]. | separates head from tail of list.
  • 17. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 17/24 X = 1 So [First | Rest] is the usual way Y = [2, 3] of writing .(First, Rest) in Prolog ?- [X | Y] = [1]. X = 1 Y = [] The empty list is written as [] Lists "end" in an empty list! Note that [1] is a list with one element. The first several elements of the list can be selected before matching the tail: ?- [X, Y | Z] = [fred, jim, jill, mary]. X = fred Y = jim Z = [jill, mary] Must be at least two elements in the list on the right. More Complex List Matching ?- [X | Y] = [[a, f(e)], [n, m, [2]]]. X = [a, f(e)] Y = [[n, m, [2]]] Notice that Y is shown with an extra pair of brackets: Y is the tail of the entire list: [n, m, [2]] is the sole element of Y. List Membership A term is a member of a list if the term is the same as the head of the list, or the term is a member of the tail of the list. In Prolog: member(X, [X | _]). trivial branch: a rule with a head but no body member(X, [_ | Y]) :- member(X, Y). recursive branch The first rule has the same effect as: member(X, [Y|_]) :- X = Y. The form member(X, [X|_]). is preferred, as it avoids the extra calculation. member is actually predefined in Prolog. It is a built-in predicate. There are quite a few built-in predicates in Prolog. We do not have the time to find out about most of them in COMP9414. Look at the COMP9814 Prolog Extension notes if you want to get an idea about some of the built-in predicates. "Pre-defined" means that you do not need to put the rules for member into your code - Prolog already knows the definition of member. Do not re-define predefined predicates. = in goals
  • 18. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 18/24 Earlier, we said: X = 1 GOOD! Actually, goals with = in them are mostly avoidable and should be avoided. Beginnner Prolog programmers are tempted to use = frequently, to tie together variables that they now realise should be the same: % length(List, LengthOfList) % binds LengthOfList to the number of elements in List. length([OnlyMember], Length) :- Length = 1. length([First | Rest], Length) :- length(Rest, LengthOfRest), Length is LengthOfRest + 1. This works, but involves an unnecessary unification. It is better for the base case to be length([OnlyMember], 1). In effect, we take the original version of the base case, and replace Length, in the head of the rule, with the thing that Length is = to. Programmers who fail to do this are usually still thinking procedurally. Programming Principles for Recursive Structures Only deal with one element at a time. Believe that the recursive program you are writing has already been written. In the definition of member, we are already assuming that we know how to find a member in the tail. Write definitions, not programs! If you are used to writing programs for conventional languages, then you are used to giving instructions on how to perform certain operations. In Prolog, you define relationships between objects and let the system do its best to construct objects that satisfy the given relationship. Concatenating Two Lists Suppose we want to take two lists, like [1, 3] and [5, 2] and concatenate them to make [1, 3, 5, 2] The header comment is: % concat(List1, List2, Concat_List1_List2) % Concat_List1_List2 is the concatenation of List1 & List2 There are two rules: First, the trivial branch: concat([], List2, List2).
  • 19. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 19/24 Next, the recursive branch: concat([Item | Tail1], List2, [Item | Concat_Tail1_List2]) :- concat(Tail1, List2, Concat_Tail1_List2). For example, consider ?- concat([1], [2], [1, 2]). By the recursive branch: concat([1 | []], [2], [1 | [2]]) :- concat([], [2], [2]). and concat([], [2], [2]) holds because of the trivial branch. The entire program is: % concat(List1, List2, Concat_List1_List2): % Concat_List1_List2 is the concatenation of List1 & List2 concat([], List2, List2). concat([Item | Tail1], List2, [Item | Concat_Tail1_List2]) :- concat(Tail1, List2, Concat_Tail1_List2). An Application of Lists Find the total cost of a list of items: Cost data: cost(cornflakes, 230). cost(cocacola, 210). cost(chocolate, 250). cost(crisps, 190). Rules: total_cost([], 0). % trivial branch total_cost([Item|Rest], Cost) :- % recursive branch cost(Item, ItemCost), total_cost(Rest, CostOfRest), Cost is ItemCost + CostOfRest. Sample query: ?- total_cost([cornflakes, crisps], X). X = 420 Tracing total_cost ?- trace. true.
  • 20. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 20/24 [trace] ?- total_cost([cornflakes, crisps], X). Call: (7) total_cost([cornflakes, crisps], _G290) ? creep Call: (8) cost(cornflakes, _L207) ? creep Exit: (8) cost(cornflakes, 230) ? creep Call: (8) total_cost([crisps], _L208) ? creep Call: (9) cost(crisps, _L228) ? creep Exit: (9) cost(crisps, 190) ? creep Call: (9) total_cost([], _L229) ? creep Exit: (9) total_cost([], 0) ? creep ^ Call: (9) _L208 is 190+0 ? creep ^ Exit: (9) 190 is 190+0 ? creep Exit: (8) total_cost([crisps], 190) ? creep ^ Call: (8) _G290 is 230+190 ? creep ^ Exit: (8) 420 is 230+190 ? creep Exit: (7) total_cost([cornflakes, crisps], 420) ? creep X = 420 [debug] ?- notrace. Modifying total_cost This is an optional homework exercise. What happens if we change the recursive branch rule for total_cost as shown below? total_cost([Item|Rest], Cost) :- total_cost(Rest, CostOfRest), cost(Item, ItemCost), Cost is ItemCost + CostOfRest. The second and third lines have been swapped around. You'll find that the rule still works. Try tracing the new version of this rule, work out what happens differently. Which version do you find easier to understand? Why do think this is the case? Another list-processing procedure The next procedure removes duplicates from a list. It has three rules. This is an example of a common list-processing template. Algorithm: If the list is empty, there's nothing to do. If the first item of the list is a member of the rest of the list, then discard it, and remove duplicates from the rest of the list. Otherwise, keep the first item, and again, remove any duplicates from the rest of the list. % remove_dups(+List, -NewList): % New List isbound to List, but with duplicate items removed. remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest),
  • 21. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 21/24 remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- not(member(First, Rest)), remove_dups(Rest, NewRest). ?- remove_dups([1,2,3,1,3,4], X). X = [2, 1, 3, 4] ; false. Note the use of not to negate a condition. An alternative to not is +. See the article on negation in the Prolog dictionary to find out why there are two names for not. Singleton Variables If Prolog finds a variable name that you only use once in a rule, it assumes that it may be a spelling mistake, and issues a Warning about a "singleton variable" when you load the code: % prolog -q -s mycode.pl Warning: .../mycode.pl:4: Singleton variables: [Item] The -q means "quiet" - i.e. don't print the SWI Prolog welcome message. This way, any warnings are easier to notice. Here is the code that produced this (with line numbers added): 1 % count(Item, List, Count) counts the number of times the 2 % Item occurs in the List, and binds Count to that number. 3 4 count(Item, [], 0). 5 count(Item, [Item | Rest], Count) :- 6 count(Item, Rest, RestCount), 7 Count is RestCount + 1. 8 count(Item, [Other | Rest], Count) :- 9 not(Item = Other), 10 count(Item, Rest, Count). To suppress the warning, put an _ in front of the word Item on line 4 (only). This makes it "don't care" variable. Check for the possible spelling error, first! 4 count(_Item, [], 0). See also the entry on singleton variables in the Prolog dictionary. Controlling Execution Reference: Bratko chapter 5 The Cut Operator (!)
  • 22. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 22/24 Sometimes we need a way to prevent Prolog finding all solutions, i.e. a way to stop backtracking. The cut operator, written !, is a built-in goal that prevents backtracking. It turns Prolog from a nice declarative language into a hybrid monster. Use cuts sparingly and with a sense of having sinned. Cut Operator 2 Recall this example: Cut Prunes the Search Tree If the goal(s) to the right of the cut fail then the entire clause fails and the the goal that caused this clause to be invoked fails. In particular, alternatives for Course are not explored.
  • 23. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 23/24 Cut Prunes the Search Tree 2 Another example: using the facts03 database, try ?- lectures(codd, X). X = 9311 ; X = 9314. ?- lectures(codd, X), ! . X = 9311. The cut in the second version of the query prevents Prolog from backtracking to find the second solution. Using cuts in later to improve efficiency Recall the code for later: later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2. later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2. later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2. We note that if year and month are the same, all three rules are tried while backtracking. This could be prevented by adding cuts: later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2, !. later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2, !. later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2. This would increase efficiency by eliminating unnecessary backtracking, though it is doubtful if it would be worth bothering about, unless you actually have code that is running too slowly. In that case you should first do an analysis of where the time is being spent, before putting in cuts everywhere! In other cases, adding cuts of this sort to multi-rule procedures might be a useful (if lazy) way of ensuring that only one rule is used in a particular case. Unless it makes the code very clumsy, it is better to use and rely on "condition" goals in each rule (like M1 > M2 in the second rule for later) to specify the case in which it is appropriate. More examples of this are below. Another cut example max, without cut: % max(A, B, C) binds C to the larger of A and B. max(A, B, A) :- A > B. max(A, B, B) :- A =< B. max, with cut: max(A, B, A) :- A > B,
  • 24. 11/18/2019 Introduction to Prolog www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/intro.html 24/24 !. max(A, B, B). The first version has a negated test in the second rule (=< vs >). The second version substitutes a cut in the first rule for the negated test. Remember, no cuts in the first assignment unless they are essential! Hint: the first assignment can be done without cuts. Another cut example 2 remove_dups, without cut: remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- not(member(First, Rest)), remove_dups(Rest, NewRest). remove_dups, with cut: remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), !, remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- remove_dups(Rest, NewRest). The first version has a negated test in the third rule (not(member(First, Rest))). The second version substitutes a cut in the second rule for the negated test in the third rule. Summary: Introduction to Prolog We have introduced facts, queries, variables, conjunctions of goals, rules, structures, recursion, trees and lists, and controlling execution by means of the "cut". CRICOS Provider Code No. 00098G Last updated on: 27 February 2012 Copyright © Bill Wilson, 1996-2012, except where another source is acknowledged: much of the material in these notes is based on an earlier edition by Claude Sammut. Certain improvements are due to Maurice Pagnucco. Images of Bratko, Kowalski, and Colmerauer were obtained from Google Images.