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

2-csc407 prolog lab 2

This document is a Prolog laboratory sheet focused on operators, arithmetic, and defining relations in Prolog. It covers key concepts such as arity, comments, built-in predicates, arithmetic operators, and recursion, providing examples and exercises for practice. Additionally, it includes tasks for creating knowledge bases and implementing recursive solutions for various problems.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

2-csc407 prolog lab 2

This document is a Prolog laboratory sheet focused on operators, arithmetic, and defining relations in Prolog. It covers key concepts such as arity, comments, built-in predicates, arithmetic operators, and recursion, providing examples and exercises for practice. Additionally, it includes tasks for creating knowledge bases and implementing recursive solutions for various problems.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

University of Buea

Faculty of Science
CSC 405 – Artificial Intelligence
Prolog Laboratory Sheet II

Operators and Arithmetic


Some Prolog Details
Arity
The arity of a predicate is simply the number of arguments it takes. You may have noticed that Prolog's error messages always
refer to a predicate name along with a number which corresponds to the arity of the predicate; for example parent/2 for predicate
parent we saw earlier. The reason Prolog always refers to the arity is that Prolog allows you to have different predicates with the
same name, but different arity.
Spaces
Prolog does not care how much spacing you use in your code with one main exception: a space should not be put between a
predicate name and the opening bracket - "(" - which follows it.
Comments
Prolog supports two forms of comment:
 The character "%" followed by any sequence of characters up to end of line.
 The symbols "/*" followed by any sequence of characters (including new lines) up to "*/"
Simple I/O in Prolog
 nl moves to a new line on screen
 write(X) writes X on screen
Arithmetic in Prolog
In this section we want to look at how Prolog deals with numbers; an important point here is the difference between functions
(as in C) and Prolog's relations.
Built-In Predicates
Built-in predicates are written between their arguments (i.e., using infix notation) instead of having to write them before their
arguments (i.e., using prefix notation).
Examples of built-in arithmetical predicates are: <, >, >=, =<, = etc. (Note inconsistency: >= and =<). Examples:
positive(N) :- N>0.
non_zero(N) :- N<0 ; N>0.
Note that Prolog's "=" relation is equality (not assignment); it is the same as the "==" relation in C.
Arithmetic Operators
Prolog also has arithmetic operators like +, -, *, / and also the usual collection of functions like sqrt, exp, cos. However these do
not work exactly as expected!
The important point here is to realise that writing "2+3" in Prolog is not an instruction to carry out the addition (remember,
Prolog is not an imperative language). Rather it represents "the addition of 2 and 3". It is thus a completely different term to
"1+4", or "3+2", and certainly different from "5*1" etc.
Thus if we have the knowledge base:
prime(2).
prime(3).
prime(5).
...
The queries "prime(1+1)" or "prime(5*1)" will both fail, because the terms they contain cannot be unified with any of those in
the knowledge base.
The value of an arithmetic expression is only actually computed when we ask Prolog to compute it - the standard way of doing
is to use Prolog's assignment predicate is.

Denis L. Nkweteyim Artificial Intelligence


The predicate N is E will succeed whenever N is an unbound variable, and E is some arithmetic expression (like 2+3). After it
succeeds, N will be assigned the computed value of E.
Thus, in the above example, the query X is 1+1, prime(X). would succeed, since the is will cause the term 1+1 to be
evaluated to 2.
It's worth emphasising this point: in general, the variable used before the is should be unbound; any variables occurring in the
arithmetical expression should have a value.
So, to use one of the built-in arithmetic functions, you'd need something like:
| ?- X is sqrt(9), Y is 2 ** 4, Z is floor(3.14). %** stands for exponent
X = 3.0
Y = 16.0
Z = 3
Some queries
Each of the following can be entered as a query to Prolog. Try entering them, and make sure you understand Prolog's response
in each case:
 N is 1+1.
 N is 1+1, P is N*2, Q is P+Q.
 N is X+1.
 I is I+1.
 I is 6, I is I+1.
 I is 6, J is I+1.
Defining your own relations
The relations positive and non_zero that we defined above represent things which would be regarded as relations in most
languages. However, it's important to remember that in Prolog all "operations" must be represented as relations - this can seem a
little strange at first.
Suppose we wanted to define a predicate to calculate the minimum value of two numbers. In C, we might write a function of the
form:
int minimum(int x, int y) {
if (x < y)
return x;
else
return y;
}
This function takes two arguments and returns one value. In Prolog we don't' have functions, so this has to be represented as a
relation. The first two arguments to the relation will be the input values, the third argument will be the result. Thus we note that:
In general, a function that takes k arguments will be represented in Prolog as a relation that takes k+1 arguments (the last one
being used to hold the result)
Thus in Prolog we write:
% minimum(X,Y,Z) is true if Z is the minimum of X and Y
minimum(X,Y,X) :- X<Y.
minimum(X,Y,Y) :- X>=Y.
We should read a statement of the form "minimum(X,Y,X) :- ..." as saying"the minimum of X and Y is X if ...". Note the way
that the two alternatives are expressed as separate clauses in Prolog.
It's a bit like if we insisted that all our functions in C were to be of type void, and return their result by reference; thus we might
write:
void minimum(int x, int y, int *z)
{
if (x<y)
*z = x;
else
*z = y;
}

Denis L. Nkweteyim Artificial Intelligence


Remember also that these predicates cannot be used in expressions like functions; in C we might write something like
"(minimum(x,y) > 0)" to test if the minimum of two numbers is positive, since we know that minimum(x,y) represents a value.
You should be very careful not to do this in Prolog, since applying the predicate minimum to something will not give a value.
The corresponding Prolog expression is: minimum(X,Y,Z), Z>0.

Exercises
Define predicates to calculate the following:
• the result of adding 1 to a number
• the function signum(x) which is x-1 if x>0, and 0 otherwise
• the absolute value of a number
• the product of two numbers
• the sum of two numbers
• division of two numbers
• integer division of two integers (div)
• remainder of division of two integers (mod)
• the maximum of two numbers
• the maximum of three numbers (without using recursion)

Using Recursion
Recursion is extremely important in Prolog. Iteration constructs like while, do, for, etc. that are provided in imperative
programming languages like C, C++, Java, are not available in Prolog. If we want to iterate in Prolog, we use recursion.
Recursion involves defining something in terms of itself. The key to ensuring that this makes sense is that you always define
something in terms of a smaller copy of itself. Recursion is the algorithmic equivalent of “proof by induction” in mathematics.
When you do recursion you must have three things:
1. Some set (or "data structure") over which you are doing the recursion: common examples include numbers, arrays,
trees etc.
2. A base case definition, usually dealing with an empty structure
3. A recursive case definition, explaining how to work out a non-trivial case in terms of some smaller version of itself.
Some Examples
Factorial:
By definition, the factorial of some positive integer n, written n! is n*n-1*n-2* ... *1. We can express this in terms of recursion
as follows:
 Data Structure: natural numbers
 Base Case: fact(0) = 1
 Recursive Case: For any n>0, we have fact(n) = n * fact(n-1)
Test for Even Numbers:
 Data Structure: natural numbers
 Base Case: 0 is even
 Recursive Case: For any n>0 we know that n is even only if n-2 is even.
A similar definition can be used to test if a number is odd; here the base case will be 1.
Maximum of three numbers: X, Y, Z
 Base case: Maximum of 2 numbers
 Recursive case: Determine maximum of X,Y = W, then determine maximum of W, Z.

Denis L. Nkweteyim Artificial Intelligence


Exercises
 Create a KB (recursion.pl) with rules for the following computations. Use appropriate queries to test the rules in each
case.
o Compute the maximum of three numbers
o Compute the factorial of a number
o Determine if a number is even
o Determine if a number is odd
 Go back to the family tree example (family.pl), and write a predicate which gives all the direct ancestors of a person
i.e. their parents, grandparents, great-grandparents etc. Query your KB to ensure that the predicate gives the desired
results.
 Try the following versions, and try to understand why the first one is not good enough, and why the last one runs into
problems
o %ancestor(A,B) :- parent(A,B).
o %ancestor(A,B) :- parent(A,X),parent(X,B).
o %ancestor(A,B) :- parent(A,B).
o %ancestor(A,B) :- parent(A,X),ancestor(X,B).
o %ancestor(A,B) :- parent(A,B).
o %ancestor(A,B) :- ancestor(A,X),ancestor(X,B). //does not involve base case

The Towers of Hanoi


Recursion lends itself naturally to the solution of this problem.
1. Data Structure: The number of discs to be moved
2. Base Case: One disc - To transfer a stack consisting of 1 disc from peg A to peg B, simply move that disc from A to B
3. Recursive Case: To transfer a stack of n discs from A to B, do the following:
a. Transfer the first n-1 discs to some other peg C
b. Move the last disc on A to B
c. Transfer the n-1 discs from C to peg B
Thus, when we wish to transfer n discs we assume that we already know how to transfer n-1 discs.
Each time we move a disk from one peg to another, we shall print a message on the screen using the predicate move.
% move(X,Y) is true if we move the topmost disc from peg X to peg Y
move(X,Y) :-
nl, write('Move topmost disc from '), %recall nl stands for new line
write(X), write(' to '), write(Y). %write writes something on screen
To do the main work, we define a recursive predicate which will have the form transfer(N,A,I,B) where:
1. N is the number of discs to be transferred
2. A is the peg on which the discs are stacked
3. B is the peg we are to move the discs to
4. I is the (empty) intermediate peg to be used for storage

Basically, transfer(N,A,I,B) will be satisfied if we can find an algorithm to transfer N discs from A to B using I. The
following code can be used.
% transfer(N,A,I,B) is true if we can transfer N discs from A to B
% using I as an intermediate peg.
% Base case - 1 disc
transfer(1,A,I,B) :- move(A,B).
% Recursive case - N discs
transfer(N,A,I,B) :-
M is N-1,
transfer(M,A,B,I), %Transfer top N-1 discs from A to I, using B
move(A,B), %Move biggest disc from A to B
transfer(M,I,A,B). %Xfer remaining N-1 discs from I to B using A
 Create a KB with the code given above, and name it hanol.pl.
 Test your KB with a queries of the form:
transfer(3,a,b,c).

Denis L. Nkweteyim Artificial Intelligence


Grid Example
Imagine a grid consisting of (evenly spaced) horizontal and vertical lines; assume that it is possible to place an object at the
intersection of any two lines. Suppose also that the lines are potentially infinite in length.
A possible configuration of objects on the grid might be:
| | | | | |
| | | | | |
----+------[A]-----[B]------+------[C]------+----
| | | | | |
| | | | | |
| | | | | |
----+------[D]-----[E]-----[F]-----[G]------+----
| | | | | |
| | | | | |
| | | | | |
----+-------+------[H]------+-------+-------+----
| | | | | |
| | | | | |
| | | | | |
----+-------+------[I]------+-------+-------+----
| | | | | |
| | | | | |
 Create a knowledge base to represent the points on the grid. Use only predicates point to indicate the point exists,
above to indicate that one point is directly above another, and right to indicate that a point is directly to the right of
another.
Note: Rather than use absolute co-ordinates (remember the grid is infinitely large in theory), describe the position of
the objects relative to each other (after all, Prolog is a relational language...)
 Now write some rules which will check the following:
1. an object is immediately to the left of another
2. an object is immediately below another
3. an object is exactly between two others, either in a horizontal or vertical direction
4. an object is directly beside another in a diagonal direction
 Finally, generalise the above so that they return all objects (a) to the right/lef,t or (b) above/below another, or (c) along
the same diagonal (using recursion!).

Denis L. Nkweteyim Artificial Intelligence

You might also like