0% found this document useful (0 votes)
12 views36 pages

Prolog Tutorial

PROLOG TUTORIAL(1)

Uploaded by

Kelvin Bakespear
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views36 pages

Prolog Tutorial

PROLOG TUTORIAL(1)

Uploaded by

Kelvin Bakespear
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 36

PROLOG TUTORIAL

In the previous section, we have seen how to install GNU Prolog. Now,
we will see how to write a simple Hello World program in our Prolog
environment.

Hello World Program


After running the GNU prolog, we can write hello world program directly
from the console. To do so, we have to write the command as follows −
write('Hello World').
Note − After each line, you have to use one period (.) symbol to show
that the line has ended.
n the following sections, we will see what are the different types of
operators in Prolog. Types of the comparison operators and Arithmetic
operators.
We will also see how these are different from any other high level
language operators, how they are syntactically different, and how they
are different in their work. Also we will see some practical
demonstration to understand the usage of different operators.

Comparison Operators
Comparison operators are used to compare two equations or states.
Following are different comparison operators −

Operator Meaning

X>Y X is greater than Y

X<Y X is less than Y

X >= Y X is greater than or equal to Y

X =< Y X is less than or equal to Y

X =:= Y the X and Y values are equal

X =\= Y the X and Y values are not equal


You can see that the ‘=<’ operator, ‘=:=’ operator and ‘=\=’ operators
are syntactically different from other languages. Let us see some
practical demonstration to this.
Example
| ?- 1+2=:=2+1.

yes
| ?- 1+2=2+1.

no
| ?- 1+A=B+2.

A=2
B=1

yes
| ?- 5<10.

yes
| ?- 5>10.

no
| ?- 10=\=100.

yes
Here we can see 1+2=:=2+1 is returning true, but 1+2=2+1 is returning
false. This is because, in the first case it is checking whether the value
of 1 + 2 is same as 2 + 1 or not, and the other one is checking whether
two patterns ‘1+2’ and ‘2+1’ are same or not. As they are not same, it
returns no (false). In the case of 1+A=B+2, A and B are two variables,
and they are automatically assigned to some values that will match the
pattern.

Arithmetic Operators in Prolog


Arithmetic operators are used to perform arithmetic operations. There
are few different types of arithmetic operators as follows −

Arithmetic Operators in Prolog


Arithmetic operators are used to perform arithmetic operations. There
are few different types of arithmetic operators as follows −

Operator Meaning
+ Addition

- Subtraction

* Multiplication

/ Division

** Power

// Integer Division

mod Modulus

Let us see one practical code to understand the usage of these


operators.
Program
calc :- X is 100 + 200,write('100 + 200 is '),write(X),nl,
Y is 400 - 150,write('400 - 150 is '),write(Y),nl,
Z is 10 * 300,write('10 * 300 is '),write(Z),nl,
A is 100 / 30,write('100 / 30 is '),write(A),nl,
B is 100 // 30,write('100 // 30 is '),write(B),nl,
C is 100 ** 2,write('100 ** 2 is '),write(C),nl,
D is 100 mod 30,write('100 mod 30 is '),write(D),nl.
Note − The nl is used to create new line.
Output
| ?- change_directory('D:/TP Prolog/Sample_Codes').

yes
| ?- [op_arith].
compiling D:/TP Prolog/Sample_Codes/op_arith.pl for byte code...
D:/TP Prolog/Sample_Codes/op_arith.pl compiled, 6 lines read -
2390 bytes written, 11 ms

yes
| ?- calc.
100 + 200 is 300
400 - 150 is 250
10 * 300 is 3000
100 / 30 is 3.3333333333333335
100 // 30 is 3
100 ** 2 is 10000.0
100 mod 30 is 10

yes
| ?-

In this chapter, we will discuss loops and decision making in Prolog.

Loops
Loop statements are used to execute the code block multiple times. In
general, for, while, do-while are loop constructs in programming
languages (like Java, C, C++).
Code block is executed multiple times using recursive predicate logic.
There are no direct loops in some other languages, but we can
simulate loops with few different techniques.
Program
count_to_10(10) :- write(10),nl.
count_to_10(X) :-
write(X),nl,
Y is X + 1,
count_to_10(Y).

Output
| ?- [loop].
compiling D:/TP Prolog/Sample_Codes/loop.pl for byte code...
D:/TP Prolog/Sample_Codes/loop.pl compiled, 4 lines read - 751
bytes written, 16 ms

(16 ms) yes


| ?- count_to_10(3).
3
4
5
6
7
8
9
10

true ?
yes
| ?-

Now create a loop that takes lowest and highest values. So, we can
use the between() to simulate loops.
Program
Let us see an example program −
count_down(L, H) :-
between(L, H, Y),
Z is H - Y,
write(Z), nl.

count_up(L, H) :-
between(L, H, Y),
Z is L + Y,
write(Z), nl.

Decision Making
The decision statements are If-Then-Else statements. So when we try
to match some condition, and perform some task, then we use the
decision making statements. The basic usage is as follows −
If <condition> is true, Then <do this>, Else
In some different programming languages, there are If-Else
statements, but in Prolog we have to define our statements in some
other manner. Following is an example of decision making in Prolog.
Program
% If-Then-Else statement

gt(X,Y) :- X >= Y,write('X is greater or equal').


gt(X,Y) :- X < Y,write('X is smaller').
% If-Elif-Else statement

gte(X,Y) :- X > Y,write('X is greater').


gte(X,Y) :- X =:= Y,write('X and Y are same').
gte(X,Y) :- X < Y,write('X is smaller').

Output
| ?- [test].
compiling D:/TP Prolog/Sample_Codes/test.pl for byte code...
D:/TP Prolog/Sample_Codes/test.pl compiled, 3 lines read - 529
bytes written, 15 ms

yes
| ?- gt(10,100).
X is smaller
yes
| ?- gt(150,100).
X is greater or equal

true ?

yes
| ?- gte(10,20).
X is smaller

(15 ms) yes


| ?- gte(100,20).
X is greater

true ?

yes
| ?- gte(100,100).
X and Y are same

true ?

yes
| ?-

In this chapter, we will discuss one of the important concepts in Prolog,


The Lists. It is a data structure that can be used in different cases for
non-numeric programming. Lists are used to store the atoms as a
collection.
In the subsequent sections, we will discuss the following topics −
 Representation of lists in Prolog
 Basic operations on prolog such as Insert, delete, update,
append.
 Repositioning operators such as permutation, combination, etc.
 Set operations like set union, set intersection, etc.

Representation of Lists
The list is a simple data structure that is widely used in non-numeric
programming. List consists of any number of items, for example, red,
green, blue, white, dark. It will be represented as, [red, green, blue,
white, dark]. The list of elements will be enclosed with square
brackets.
A list can be either empty or non-empty. In the first case, the list is
simply written as a Prolog atom, []. In the second case, the list consists
of two things as given below −
 The first item, called the head of the list;
 The remaining part of the list, called the tail.
Suppose we have a list like: [red, green, blue, white, dark]. Here the
head is red and tail is [green, blue, white, dark]. So the tail is another
list.
Now, let us consider we have a list, L = [a, b, c]. If we write Tail = [b, c]
then we can also write the list L as L = [ a | Tail]. Here the vertical bar
(|) separates the head and tail parts.
So the following list representations are also valid −
 [a, b, c] = [x | [b, c] ]
 [a, b, c] = [a, b | [c] ]
 [a, b, c] = [a, b, c | [ ] ]
 For these properties we can define the list as −
 A data structure that is either empty or consists of two parts − a
head and a tail. The tail itself has to be a list.

 Basic Operations on Lists


 Following table contains various operations on prolog lists −

Operations Definition

Membership During this operation, we can verify whether a given element is


Checking member of specified list or not?

Length Calculation With this operation, we can find the length of a list.

Concatenation Concatenation is an operation which is used to join/add two lists.

Delete Items This operation removes the specified element from a list.

Append Items Append operation adds one list into another (as an item).

Insert Items This operation inserts a given item into a list.

Membership Operation
During this operation, we can check whether a member X is present in
list L or not? So how to check this? Well, we have to define one
predicate to do so. Suppose the predicate name is list_member(X,L).
The goal of this predicate is to check whether X is present in L or not.
To design this predicate, we can follow these observations. X is a
member of L if either −
 X is head of L, or
 X is a member of the tail of L
Program
list_member(X,[X|_]).
list_member(X,[_|TAIL]) :- list_member(X,TAIL).
Output
| ?- [list_basics].
compiling D:/TP Prolog/Sample_Codes/list_basics.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_basics.pl compiled, 1 lines read -
467 bytes written, 13 ms

yes
| ?- list_member(b,[a,b,c]).

true ?

yes
| ?- list_member(b,[a,[b,c]]).

no
| ?- list_member([b,c],[a,[b,c]]).

true ?

Length Calculation
This is used to find the length of list L. We will define one predicate to
do this task. Suppose the predicate name is list_length(L,N). This
takes L and N as input argument. This will count the elements in a list L
and instantiate N to their number. As was the case with our previous
relations involving lists, it is useful to consider two cases −
 If list is empty, then length is 0.
 If the list is not empty, then L = [Head|Tail], then its length is 1 +
length of Tail.
Program
list_length([],0).
list_length([_|TAIL],N) :- list_length(TAIL,N1), N is N1 + 1.
Output
| ?- [list_basics].
compiling D:/TP Prolog/Sample_Codes/list_basics.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_basics.pl compiled, 4 lines read -
985 bytes written, 23 ms

yes
| ?- list_length([a,b,c,d,e,f,g,h,i,j],Len).

Len = 10

yes
| ?- list_length([],Len).

Len = 0

yes
| ?- list_length([[a,b],[c,d],[e,f]],Len).

Len = 3

Concatenation
Concatenation of two lists means adding the list items of the second list
after the first one. So if two lists are [a,b,c] and [1,2], then the final list
will be [a,b,c,1,2]. So to do this task we will create one predicate called
list_concat(), that will take first list L1, second list L2, and the L3 as
resultant list. There are two observations here.
 If the first list is empty, and second list is L, then the resultant list
will be L.
 If the first list is not empty, then write this as [Head|Tail],
concatenate Tail with L2 recursively, and store into new list in the
form, [Head|New List].
Program
list_concat([],L,L).
list_concat([X1|L1],L2,[X1|L3]) :- list_concat(L1,L2,L3).
Output
| ?- [list_basics].
compiling D:/TP Prolog/Sample_Codes/list_basics.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_basics.pl compiled, 7 lines read -
1367 bytes written, 19 ms

yes
| ?- list_concat([1,2],[a,b,c],NewList).
NewList = [1,2,a,b,c]

yes
| ?- list_concat([],[a,b,c],NewList).

NewList = [a,b,c]

yes
| ?- list_concat([[1,2,3],[p,q,r]],[a,b,c],NewList).

NewList = [[1,2,3],[p,q,r],a,b,c]

yes

Delete from List


Suppose we have a list L and an element X, we have to delete X from
L. So there are three cases −
 If X is the only element, then after deleting it, it will return empty
list.
 If X is head of L, the resultant list will be the Tail part.
 If X is present in the Tail part, then delete from there recursively.
Program
list_delete(X, [X], []).
list_delete(X,[X|L1], L1).
list_delete(X, [Y|L2], [Y|L1]) :- list_delete(X,L2,L1).
Output
| ?- [list_basics].
compiling D:/TP Prolog/Sample_Codes/list_basics.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_basics.pl compiled, 11 lines read
- 1923 bytes written, 25 ms

yes
| ?- list_delete(a,[a,e,i,o,u],NewList).

NewList = [e,i,o,u] ?

yes
| ?- list_delete(a,[a],NewList).

NewList = [] ?

yes
| ?- list_delete(X,[a,e,i,o,u],[a,e,o,u]).
X=i?;

no
| ?-

Append into List


Appending two lists means adding two lists together, or adding one list
as an item. Now if the item is present in the list, then the append
function will not work. So we will create one predicate namely,
list_append(L1, L2, L3). The following are some observations −
 Let A is an element, L1 is a list, the output will be L1 also, when
L1 has A already.
 Otherwise new list will be L2 = [A|L1].
Program
list_member(X,[X|_]).
list_member(X,[_|TAIL]) :- list_member(X,TAIL).

list_append(A,T,T) :- list_member(A,T),!.
list_append(A,T,[A|T]).
In this case, we have used (!) symbol, that is known as cut. So when
the first line is executed successfully, then we cut it, so it will not
execute the next operation.
Output
| ?- [list_basics].
compiling D:/TP Prolog/Sample_Codes/list_basics.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_basics.pl compiled, 14 lines read
- 2334 bytes written, 25 ms

(16 ms) yes


| ?- list_append(a,[e,i,o,u],NewList).

NewList = [a,e,i,o,u]

yes
| ?- list_append(e,[e,i,o,u],NewList).

NewList = [e,i,o,u]

yes
| ?- list_append([a,b],[e,i,o,u],NewList).

NewList = [[a,b],e,i,o,u]
yes
| ?-

Insert into List


This method is used to insert an item X into list L, and the resultant list
will be R. So the predicate will be in this form list_insert(X, L, R). So
this can insert X into L in all possible positions. If we see closer, then
there are some observations.
 If we perform list_insert(X,L,R), we can use list_delete(X,R,L), so
delete X from R and make new list L
Program
list_delete(X, [X], []).
list_delete(X,[X|L1], L1).
list_delete(X, [Y|L2], [Y|L1]) :- list_delete(X,L2,L1).

list_insert(X,L,R) :- list_delete(X,R,L).
Output
| ?- [list_basics].
compiling D:/TP Prolog/Sample_Codes/list_basics.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_basics.pl compiled, 16 lines read
- 2558 bytes written, 22 ms

(16 ms) yes


| ?- list_insert(a,[e,i,o,u],NewList).

NewList = [a,e,i,o,u] ? a

NewList = [e,a,i,o,u]

NewList = [e,i,a,o,u]

NewList = [e,i,o,a,u]

NewList = [e,i,o,u,a]
NewList = [e,i,o,u,a]

(15 ms) no
| ?-

Repositioning operations of list items


Following are repositioning operations −

Repositioning Definition
Operations

Permutation This operation will change the list item positions and generate all
possible outcomes.

Reverse Items This operation arranges the items of a list in reverse order.

Shift Items This operation will shift one element of a list to the left
rotationally.

Order Items This operation verifies whether the given list is ordered or not.

Permutation Operation
This operation will change the list item positions and generate all
possible outcomes. So we will create one predicate as
list_perm(L1,L2), This will generate all permutation of L1, and store
them into L2. To do this we need list_delete() clause to help.
To design this predicate, we can follow few observations as given
below −
X is member of L if either −
 If the first list is empty, then the second list must also be empty.
 If the first list is not empty then it has the form [X | L], and a
permutation of such a list can be constructed as, first permute L
obtaining L1 and then insert X at any position into L1.
Program
list_delete(X,[X|L1], L1).
list_delete(X, [Y|L2], [Y|L1]) :- list_delete(X,L2,L1).

list_perm([],[]).
list_perm(L,[X|P]) :- list_delete(X,L,L1),list_perm(L1,P).
Output
| ?- [list_repos].
compiling D:/TP Prolog/Sample_Codes/list_repos.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_repos.pl compiled, 4 lines read -
1060 bytes written, 17 ms

(15 ms) yes


| ?- list_perm([a,b,c,d],X).
X = [a,b,c,d] ? a

X = [a,b,d,c]

X = [a,c,b,d]

X = [a,c,d,b]

X = [a,d,b,c]
X = [a,d,c,b]

X = [b,a,c,d]

X = [b,a,d,c]

X = [b,c,a,d]

X = [b,c,d,a]

X = [b,d,a,c]

X = [b,d,c,a]

X = [c,a,b,d]

X = [c,a,d,b]
X = [c,b,a,d]

X = [c,b,d,a]

X = [c,d,a,b]

X = [c,d,b,a]

X = [d,a,b,c]

X = [d,a,c,b]

X = [d,b,a,c]
X = [d,b,c,a]

X = [d,c,a,b]

X = [d,c,b,a]

(31 ms) no
| ?-
Reverse Operation
Suppose we have a list L = [a,b,c,d,e], and we want to reverse the
elements, so the output will be [e,d,c,b,a]. To do this, we will create a
clause, list_reverse(List, ReversedList). Following are some
observations −
 If the list is empty, then the resultant list will also be empty.
 Otherwise put the list items namely, [Head|Tail], and reverse the
Tail items recursively, and concatenate with the Head.
 Otherwise put the list items namely, [Head|Tail], and reverse the
Tail items recursively, and concatenate with the Head.
Program
list_concat([],L,L).
list_concat([X1|L1],L2,[X1|L3]) :- list_concat(L1,L2,L3).

list_rev([],[]).
list_rev([Head|Tail],Reversed) :-
list_rev(Tail, RevTail),list_concat(RevTail, [Head],Reversed).
Output
| ?- [list_repos].
compiling D:/TP Prolog/Sample_Codes/list_repos.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_repos.pl compiled, 10 lines read -
1977 bytes written, 19 ms

yes
| ?- list_rev([a,b,c,d,e],NewList).

NewList = [e,d,c,b,a]

yes
| ?- list_rev([a,b,c,d,e],[e,d,c,b,a]).

yes
| ?-

Shift Operation
Using Shift operation, we can shift one element of a list to the left
rotationally. So if the list items are [a,b,c,d], then after shifting, it will be
[b,c,d,a]. So we will make a clause list_shift(L1, L2).
 We will express the list as [Head|Tail], then recursively
concatenate Head after the Tail, so as a result we can feel that
the elements are shifted.
 This can also be used to check whether the two lists are shifted
at one position or not.
Program
list_concat([],L,L).
list_concat([X1|L1],L2,[X1|L3]) :- list_concat(L1,L2,L3).

list_shift([Head|Tail],Shifted) :- list_concat(Tail, [Head],Shifted).

Output
| ?- [list_repos].
compiling D:/TP Prolog/Sample_Codes/list_repos.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_repos.pl compiled, 12 lines read -
2287 bytes written, 10 ms

yes
| ?- list_shift([a,b,c,d,e],L2).

L2 = [b,c,d,e,a]

(16 ms) yes


| ?- list_shift([a,b,c,d,e],[b,c,d,e,a]).

yes
| ?-

Order Operation
Here we will define a predicate list_order(L) which checks whether L is
ordered or not. So if L = [1,2,3,4,5,6], then the result will be true.
 If there is only one element, that is already ordered.
 Otherwise take first two elements X and Y as Head, and rest as
Tail. If X =< Y, then call the clause again with the parameter [Y|
Tail], so this will recursively check from the next element.
Program
list_order([X, Y | Tail]) :- X =< Y, list_order([Y|Tail]).
list_order([X]).
Output
| ?- [list_repos].
compiling D:/TP Prolog/Sample_Codes/list_repos.pl for byte
code...
D:/TP Prolog/Sample_Codes/list_repos.pl:15: warning: singleton
variables [X] for list_order/1
D:/TP Prolog/Sample_Codes/list_repos.pl compiled, 15 lines read -
2805 bytes written, 18 ms

yes
| ?- list_order([1,2,3,4,5,6,6,7,7,8]).

true ?

yes
| ?- list_order([1,4,2,3,6,5]).

no
| ?-

Set operations on lists


We will try to write a clause that will get all possible subsets of a given
set. So if the set is [a,b], then the result will be [], [a], [b], [a,b]. To do
so, we will create one clause, list_subset(L, X). It will take L and return
each subsets into X. So we will proceed in the following way −
 If list is empty, the subset is also empty.
 Find the subset recursively by retaining the Head, and
 Make another recursive call where we will remove Head
Program
list_subset([],[]).
list_subset([Head|Tail],[Head|Subset]) :- list_subset(Tail,Subset).
list_subset([Head|Tail],Subset) :- list_subset(Tail,Subset).
Output
| ?- [list_set].
compiling D:/TP Prolog/Sample_Codes/list_set.pl for byte code...
D:/TP Prolog/Sample_Codes/list_set.pl:3: warning: singleton
variables [Head] for list_subset/2
D:/TP Prolog/Sample_Codes/list_set.pl compiled, 2 lines read -
653 bytes written, 7 ms

yes
| ?- list_subset([a,b],X).

X = [a,b] ? ;

X = [a] ? ;

X = [b] ? ;

X = []
(15 ms) yes
| ?- list_subset([x,y,z],X).
X = [x,y,z] ? a

X = [x,y]

X = [x,z]

X = [x]

X = [y,z]

X = [y]

X = [z]

X = []
yes
| ?-

Union Operation
Let us define a clause called list_union(L1,L2,L3), So this will take L1
and L2, and perform Union on them, and store the result into L3. As
you know if two lists have the same element twice, then after union,
there will be only one. So we need another helper clause to check the
membership.
Program
list_member(X,[X|_]).
list_member(X,[_|TAIL]) :- list_member(X,TAIL).

list_union([X|Y],Z,W) :- list_member(X,Z),list_union(Y,Z,W).
list_union([X|Y],Z,[X|W]) :- \+ list_member(X,Z),
list_union(Y,Z,W).
list_union([],Z,Z).
Note − In the program, we have used (\+) operator, this operator is
used for NOT.
Output
| ?- [list_set].
compiling D:/TP Prolog/Sample_Codes/list_set.pl for byte code...
D:/TP Prolog/Sample_Codes/list_set.pl:6: warning: singleton
variables [Head] for list_subset/2
D:/TP Prolog/Sample_Codes/list_set.pl compiled, 9 lines read -
2004 bytes written, 18 ms
yes
| ?- list_union([a,b,c,d,e],[a,e,i,o,u],L3).

L3 = [b,c,d,a,e,i,o,u] ?

(16 ms) yes

| ?- list_union([a,b,c,d,e],[1,2],L3).

L3 = [a,b,c,d,e,1,2]

yes

Intersection Operation
Let us define a clause called list_intersection(L1,L2,L3), So this will
take L1 and L2, and perform Intersection operation, and store the result
into L3. Intersection will return those elements that are present in both
lists. So L1 = [a,b,c,d,e], L2 = [a,e,i,o,u], then L3 = [a,e]. Here, we will
use the list_member() clause to check if one element is present in a list
or not.
Program
list_member(X,[X|_]).
list_member(X,[_|TAIL]) :- list_member(X,TAIL).

list_intersect([X|Y],Z,[X|W]) :-
list_member(X,Z), list_intersect(Y,Z,W).
list_intersect([X|Y],Z,W) :-
\+ list_member(X,Z), list_intersect(Y,Z,W).
list_intersect([],Z,[]).
Output
| ?- [list_set].
compiling D:/TP Prolog/Sample_Codes/list_set.pl for byte code...
D:/TP Prolog/Sample_Codes/list_set.pl compiled, 13 lines read -
3054 bytes written, 9 ms

(15 ms) yes


| ?- list_intersect([a,b,c,d,e],[a,e,i,o,u],L3).

L3 = [a,e] ?

yes
| ?- list_intersect([a,b,c,d,e],[],L3).

L3 = []
yes
| ?-

Divide List Operation


This operation divides a list into two lists, and these lists are of
approximately same length. So if the given list is [a,b,c,d,e], then the
result will be [a,c,e],[b,d]. This will place all of the odd placed elements
into one list, and all even placed elements into another list. We will
define a predicate, list_divide(L1,L2,L3) to solve this task.
 If given list is empty, then it will return empty lists.
 If there is only one element, then the first list will be a list with
that element, and the second list will be empty.
 Suppose X,Y are two elements from head, and rest are Tail, So
make two lists [X|List1], [Y|List2], these List1 and List2 are
separated by dividing Tail.
Program
list_divide([],[],[]).
list_divide([X],[X],[]).
list_divide([X,Y|Tail], [X|List1],[Y|List2]) :-
list_divide(Tail,List1,List2).
Output
| ?- [list_misc].
compiling D:/TP Prolog/Sample_Codes/list_misc.pl for byte code...
D:/TP Prolog/Sample_Codes/list_misc.pl:2: warning: singleton
variables [Head] for list_even_len/1
D:/TP Prolog/Sample_Codes/list_misc.pl:5: warning: singleton
variables [Head] for list_odd_len/1
D:/TP Prolog/Sample_Codes/list_misc.pl compiled, 8 lines read -
1432 bytes written, 8 ms

yes
| ?- list_divide([a,1,b,2,c,3,d,5,e],L1,L2).

L1 = [a,b,c,d,e]
L2 = [1,2,3,5] ?

yes
| ?- list_divide([a,b,c,d],L1,L2).

L1 = [a,c]
L2 = [b,d]
yes
| ?-
Max Item Operation
This operation is used to find the maximum element from a list. We will
define a predicate, list_max_elem(List, Max), then this will find Max
element from the list and return.
 If there is only one element, then it will be the max element.
 Divide the list as [X,Y|Tail]. Now recursively find max of [Y|Tail]
and store it into MaxRest, and store maximum of X and
MaxRest, then store it to Max.
Program
max_of_two(X,Y,X) :- X >= Y.
max_of_two(X,Y,Y) :- X < Y.
list_max_elem([X],X).
list_max_elem([X,Y|Rest],Max) :-
list_max_elem([Y|Rest],MaxRest),
max_of_two(X,MaxRest,Max).
Output
| ?- [list_misc].
compiling D:/TP Prolog/Sample_Codes/list_misc.pl for byte code...
D:/TP Prolog/Sample_Codes/list_misc.pl:2: warning: singleton
variables [Head] for list_even_len/1
D:/TP Prolog/Sample_Codes/list_misc.pl:5: warning: singleton
variables [Head] for list_odd_len/1
D:/TP Prolog/Sample_Codes/list_misc.pl compiled, 16 lines read -
2385 bytes written, 16 ms

yes
| ?- list_max_elem([8,5,3,4,7,9,6,1],Max).

Max = 9 ?

yes
| ?- list_max_elem([5,12,69,112,48,4],Max).

Max = 112 ?

yes
| ?-

List Sum Operation


In this example, we will define a clause, list_sum(List, Sum), this will
return the sum of the elements of the list.
 If the list is empty, then sum will be 0.
 Represent list as [Head|Tail], find sum of tail recursively and
store them into SumTemp, then set Sum = Head + SumTemp.

Program
list_sum([],0).
list_sum([Head|Tail], Sum) :-
list_sum(Tail,SumTemp),
Sum is Head + SumTemp.
Output
yes
| ?- [list_misc].
compiling D:/TP Prolog/Sample_Codes/list_misc.pl for byte code...
D:/TP Prolog/Sample_Codes/list_misc.pl:2: warning: singleton
variables [Head] for list_even_len/1
D:/TP Prolog/Sample_Codes/list_misc.pl:5: warning: singleton
variables [Head] for list_odd_len/1
D:/TP Prolog/Sample_Codes/list_misc.pl compiled, 21 lines read -
2897 bytes written, 21 ms

(32 ms) yes


| ?- list_sum([5,12,69,112,48,4],Sum).

Sum = 250

yes
| ?- list_sum([8,5,3,4,7,9,6,1],Sum).

Sum = 43

yes
| ?-

Merge Sort on a List


If the list is [4,5,3,7,8,1,2], then the result will be [1,2,3,4,5,7,8]. The
steps of performing merge sort are shown below −
 Take the list and split them into two sub-lists. This split will be
performed recursively.
 Merge each split in sorted order.
 Thus the entire list will be sorted.
We will define a predicate called mergesort(L, SL), it will take L and
return result into SL.
Program
mergesort([],[]). /* covers special case */
mergesort([A],[A]).
mergesort([A,B|R],S) :-
split([A,B|R],L1,L2),
mergesort(L1,S1),
mergesort(L2,S2),
merge(S1,S2,S).

split([],[],[]).
split([A],[A],[]).
split([A,B|R],[A|Ra],[B|Rb]) :-
split(R,Ra,Rb).
merge(A,[],A).
merge([],B,B).
merge([A|Ra],[B|Rb],[A|M]) :-
A =< B, merge(Ra,[B|Rb],M).
merge([A|Ra],[B|Rb],[B|M]) :-
A > B, merge([A|Ra],Rb,M).
Output
| ?- [merge_sort].
compiling D:/TP Prolog/Sample_Codes/merge_sort.pl for byte
code...
D:/TP Prolog/Sample_Codes/merge_sort.pl compiled, 17 lines
read - 3048 bytes written, 19 ms

yes
| ?- mergesort([4,5,3,7,8,1,2],L).

L = [1,2,3,4,5,7,8] ?

yes
| ?- mergesort([8,5,3,4,7,9,6,1],L).

L = [1,3,4,5,6,7,8,9] ?

yes
| ?-
Fibonacci series
fib(0, 1) :-!.

fib(N, F) :- fib(1, N, 1, 1, F).

fib(N, N, _, F, F) :-!.

fib(N0, N, F0, F1, F) :-

N1 is N0 + 1,

F2 is F0 + F1,

fib(N1, N, F1, F2, F).

it gives the nth value of the sequence

? fib(5,X)

Gives the 5th value of the sequence

Horizontal and Vertical Line Segments


There are three types of line segments, horizontal, vertical or oblique.
This example verifies whether a line segment is horizontal, vertical or
oblique.
From this diagram we can understand that −
 For Horizontal lines, the y coordinate values of two endpoints are
same.
 For Vertical lines, the x coordinate values of two endpoints are
same.
 For Oblique lines, the (x,y) coordinates of two endpoints are
different.
Now let us see how to write a program to check this

Program
vertical(seg(point(X,_),point(X,_))).

horizontal(seg(point(_,Y),point(_,Y))).

oblique(seg(point(X1,Y1),point(X2,Y2)))
:-X1 \== X2,
Y1 \== Y2.
Output
| ?- [line_seg].
compiling D:/TP Prolog/Sample_Codes/line_seg.pl for byte code...
D:/TP Prolog/Sample_Codes/line_seg.pl compiled, 6 lines read -
1276 bytes written, 26 ms

yes
| ?- vertical(seg(point(10,20), point(10,30))).

yes
| ?- vertical(seg(point(10,20), point(15,30))).

no
| ?- oblique(seg(point(10,20), point(15,30))).

yes
| ?- oblique(seg(point(10,20), point(15,20))).

no
| ?- horizontal(seg(point(10,20), point(15,20))).

yes
| ?-

Loops
Loop statements are used to execute the code block multiple times. In
general, for, while, do-while are loop constructs in programming
languages (like Java, C, C++).
Code block is executed multiple times using recursive predicate logic.
There are no direct loops in some other languages, but we can
simulate loops with few different techniques.
Program
count_to_10(10) :- write(10),nl.
count_to_10(X) :-
write(X),nl,
Y is X + 1,
count_to_10(Y).
Output
| ?- [loop].
compiling D:/TP Prolog/Sample_Codes/loop.pl for byte code...
D:/TP Prolog/Sample_Codes/loop.pl compiled, 4 lines read - 751
bytes written, 16 ms
(16 ms) yes
| ?- count_to_10(3).
3
4
5
6
7
8
9
10

true ?
yes
| ?-

Now create a loop that takes lowest and highest values. So, we can
use the between() to simulate loops.
Program
Let us see an example program −
count_down(L, H) :-
between(L, H, Y),
Z is H - Y,
write(Z), nl.

count_up(L, H) :-
between(L, H, Y),
Z is L + Y,
write(Z), nl.
Output
| ?- [loop].
compiling D:/TP Prolog/Sample_Codes/loop.pl for byte code...
D:/TP Prolog/Sample_Codes/loop.pl compiled, 14 lines read -
1700 bytes written, 16 ms

yes
| ?- count_down(12,17).
5

true ? ;
4

true ? ;
3

true ? ;
2

true ? ;
1
true ? ;
0

yes
| ?- count_up(5,12).
10

true ? ;
11

true ? ;
12

true ? ;
13

true ? ;
14

true ? ;
15
true ? ;
16

true ? ;
17

yes
| ?-

In this section, we will see some examples of cuts in prolog. Let us


consider, we want to find the maximum of two elements. So we will
check these two conditions.
 If X > Y, then Max := X
 if X <= Y, then Max := Y
Now from these two lines, we can understand that these two
statements are mutually exclusive, so when one is true, another one
must be false. In such cases we can use the cut. So let us see the
program.
We can also define a predicate where we use the two cases using
disjunction (OR logic). So when first one satisfies, it does not check for
the second one, otherwise, it will check for the second statement.
Program
max(X,Y,X) :- X >= Y,!.
max(X,Y,Y) :- X < Y.

max_find(X,Y,Max) :- X >= Y,!, Max = X; Max = Y.


Output
| ?- [cut_example].
1 1 Call: [cut_example] ?
compiling D:/TP Prolog/Sample_Codes/cut_example.pl for byte
code...
D:/TP Prolog/Sample_Codes/cut_example.pl compiled, 3 lines
read - 1195 bytes written, 43 ms
1 1 Exit: [cut_example] ?
yes
{trace}
| ?- max(10,20,Max).
1 1 Call: max(10,20,_23) ?
2 2 Call: 10>=20 ?
2 2 Fail: 10>=20 ?
2 2 Call: 10<20 ?
2 2 Exit: 10<20 ?
1 1 Exit: max(10,20,20) ?
Max = 20

yes
{trace}
| ?- max_find(20,10,Max).
1 1 Call: max_find(20,10,_23) ?
2 2 Call: 20>=10 ?
2 2 Exit: 20>=10 ?
1 1 Exit: max_find(20,10,20) ?
Max = 20

yes
{trace}
| ?-
Program
Let us see another example, where we will use list. In this program we
will try to insert an element into a list, if it is not present in the list
before. And if the list has the element before we will simply cut it. For
the membership checking also, if the item is at the head part, we
should not check further, so cut it, otherwise check into the tail part.
list_member(X,[X|_]) :- !.
list_member(X,[_|TAIL]) :- list_member(X,TAIL).

list_append(A,T,T) :- list_member(A,T),!.
list_append(A,T,[A|T]).
Output
| ?- [cut_example].
compiling D:/TP Prolog/Sample_Codes/cut_example.pl for byte
code...
D:/TP Prolog/Sample_Codes/cut_example.pl compiled, 9 lines
read - 1954 bytes written, 15 ms

yes
| ?- trace.
The debugger will first creep -- showing everything (trace)

yes
{trace}
| ?- list_append(a,[a,b,c,d,e], L).
1 1 Call: list_append(a,[a,b,c,d,e],_33) ?
2 2 Call: list_member(a,[a,b,c,d,e]) ?
2 2 Exit: list_member(a,[a,b,c,d,e]) ?
1 1 Exit: list_append(a,[a,b,c,d,e],[a,b,c,d,e]) ?

L = [a,b,c,d,e]

yes
{trace}
| ?- list_append(k,[a,b,c,d,e], L).
1 1 Call: list_append(k,[a,b,c,d,e],_33) ?
2 2 Call: list_member(k,[a,b,c,d,e]) ?
3 3 Call: list_member(k,[b,c,d,e]) ?
4 4 Call: list_member(k,[c,d,e]) ?
5 5 Call: list_member(k,[d,e]) ?
6 6 Call: list_member(k,[e]) ?
7 7 Call: list_member(k,[]) ?
7 7 Fail: list_member(k,[]) ?
6 6 Fail: list_member(k,[e]) ?
5 5 Fail: list_member(k,[d,e]) ?
4 4 Fail: list_member(k,[c,d,e]) ?
3 3 Fail: list_member(k,[b,c,d,e]) ?
2 2 Fail: list_member(k,[a,b,c,d,e]) ?
1 1 Exit: list_append(k,[a,b,c,d,e],[k,a,b,c,d,e]) ?

L = [k,a,b,c,d,e]

(16 ms) yes


{trace}
| ?-

ROOTS OF A QUADRATIC EQUATION


% Define the predicate for computing the roots of a quadratic equation
roots(A, B, C, X1, X2) :-
% Compute the discriminant
D is B*B - 4*A*C,
% Check if the roots are real or complex
( D < 0 ->
% Roots are complex
X1 is -B/(2*A),
X2 is sqrt(-D)/(2*A),
format('Roots are complex: ~f + ~f i, ~f - ~f i', [X1, X2, X1, X2])
; % Roots are real
X1 is (-B + sqrt(D))/(2*A),
X2 is (-B - sqrt(D))/(2*A),
format('Roots are real: ~f, ~f', [X1, X2])
).

% Example query
?- roots(1, -5, 6, X1, X2).
% Output: Roots are real: 3.0, 2.0
% X1 = 3.0,
% X2 = 2.0.

Towers of Hanoi Problem is a famous puzzle to move N disks from the


source peg/tower to the target peg/tower using the intermediate peg as
an auxiliary holding peg. There are two conditions that are to be
followed while solving this problem −
 A larger disk cannot be placed on a smaller disk.
 Only one disk can be moved at a time.
The following diagram depicts the starting setup for N=3 disks.
To solve this, we have to write one procedure move(N, Source, Target,
auxiliary). Here N number of disks will have to be shifted from Source
peg to Target peg keeping Auxiliary peg as intermediate.
For example – move(3, source, target, auxiliary).
 Move top disk from source to target
 Move top disk from source to auxiliary
 Move top disk from target to auxiliary
 Move top disk from source to target
 Move top disk from auxiliary to source
 Move top disk from auxiliary to target
 Move top disk from source to target
Program
move(1,X,Y,_) :-
write('Move top disk from '), write(X), write(' to '), write(Y), nl.
move(N,X,Y,Z) :-
N>1,
M is N-1,
move(M,X,Z,Y),
move(1,X,Y,_),
move(M,Z,Y,X).
Output
| ?- [towersofhanoi].
compiling D:/TP Prolog/Sample_Codes/towersofhanoi.pl for byte
code...
D:/TP Prolog/Sample_Codes/towersofhanoi.pl compiled, 8 lines
read - 1409 bytes written, 15 ms

yes
| ?- move(4,source,target,auxiliary).
Move top disk from source to auxiliary
Move top disk from source to target
Move top disk from auxiliary to target
Move top disk from source to auxiliary
Move top disk from target to source
Move top disk from target to auxiliary
Move top disk from source to auxiliary
Move top disk from source to target
Move top disk from auxiliary to target
Move top disk from auxiliary to source
Move top disk from target to source
Move top disk from auxiliary to target
Move top disk from source to auxiliary
Move top disk from source to target
Move top disk from auxiliary to target
true ?

(31 ms) yes

In this prolog example, we will see one very interesting and famous
problem, The Monkey and Banana Problem.

Problem Statement
Suppose the problem is as given below −
 A hungry monkey is in a room, and he is near the door.
 The monkey is on the floor.
 Bananas have been hung from the center of the ceiling of the
room.
 There is a block (or chair) present in the room near the window.
 The monkey wants the banana, but cannot reach it.
So how can the monkey get the bananas?
So if the monkey is clever enough, he can come to the block, drag the
block to the center, climb on it, and get the banana. Below are few
observations in this case −
 Monkey can reach the block, if both of them are at the same
level. From the above image, we can see that both the monkey
and the block are on the floor.
 If the block position is not at the center, then monkey can drag it
to the center.
 If monkey and the block both are on the floor, and block is at the
center, then the monkey can climb up on the block. So the
vertical position of the monkey will be changed.
 When the monkey is on the block, and block is at the center,
then the monkey can get the bananas.
Now, let us see how we can solve this using Prolog. We will create
some predicates as follows −
We have some predicates that will move from one state to another
state, by performing action.
 When the block is at the middle, and monkey is on top of the
block, and monkey does not have the banana (i.e. has
not state), then using the grasp action, it will change from has
not state to have state.
 From the floor, it can move to the top of the block (i.e. on
top state), by performing the action climb.
 The push or drag operation moves the block from one place to
another.
 Monkey can move from one place to another
using walk or move clauses.
Another predicate will be canget(). Here we pass a state, so this will
perform move predicate from one state to another using different
actions, then perform canget() on state 2. When we have reached to
the state ‘has>’, this indicates ‘has banana’. We will stop the
execution.

Program
move(state(middle,onbox,middle,hasnot),
grasp,
state(middle,onbox,middle,has)).
move(state(P,onfloor,P,H),
climb,
state(P,onbox,P,H)).
move(state(P1,onfloor,P1,H),
drag(P1,P2),
state(P2,onfloor,P2,H)).
move(state(P1,onfloor,B,H),
walk(P1,P2),
state(P2,onfloor,B,H)).
canget(state(_,_,_,has)).
canget(State1) :-
move(State1,_,State2),
canget(State2).

Output
| ?- [monkey_banana].
compiling D:/TP Prolog/Sample_Codes/monkey_banana.pl for
byte code...
D:/TP Prolog/Sample_Codes/monkey_banana.pl compiled, 17
lines read - 2167 bytes written, 19 ms

(31 ms) yes


| ?- canget(state(atdoor, onfloor, atwindow, hasnot)).

true ?

yes
| ?- trace
.
The debugger will first creep -- showing everything (trace)

yes
{trace}
| ?- canget(state(atdoor, onfloor, atwindow, hasnot)).
1 1 Call: canget(state(atdoor,onfloor,atwindow,hasnot)) ?
2 2 Call:
move(state(atdoor,onfloor,atwindow,hasnot),_52,_92) ?
22
Exit:move(state(atdoor,onfloor,atwindow,hasnot),walk(atdoor,_8
0),state(_80,onfloor,atwindow,hasnot)) ?
3 2 Call: canget(state(_80,onfloor,atwindow,hasnot)) ?
4 3 Call:
move(state(_80,onfloor,atwindow,hasnot),_110,_150) ?
4 3 Exit:
move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwin
dow,onbox,atwindow,hasnot)) ?
5 3 Call: canget(state(atwindow,onbox,atwindow,hasnot)) ?
6 4 Call:
move(state(atwindow,onbox,atwindow,hasnot),_165,_205) ?
6 4 Fail:
move(state(atwindow,onbox,atwindow,hasnot),_165,_193) ?
5 3 Fail: canget(state(atwindow,onbox,atwindow,hasnot)) ?
4 3 Redo:
move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwin
dow,onbox,atwindow,hasnot)) ?
4 3 Exit:
move(state(atwindow,onfloor,atwindow,hasnot),drag(atwindow,_
138),state(_138,onfloor,_138,hasnot)) ?
5 3 Call: canget(state(_138,onfloor,_138,hasnot)) ?
6 4 Call: move(state(_138,onfloor,_138,hasnot),_168,_208) ?
6 4 Exit:
move(state(_138,onfloor,_138,hasnot),climb,state(_138,onbox,_1
38,hasnot)) ?
7 4 Call: canget(state(_138,onbox,_138,hasnot)) ?
8 5 Call: move(state(_138,onbox,_138,hasnot),_223,_263) ?
8 5 Exit:
move(state(middle,onbox,middle,hasnot),grasp,state(middle,onb
ox,middle,has)) ?
9 5 Call: canget(state(middle,onbox,middle,has)) ?
9 5 Exit: canget(state(middle,onbox,middle,has)) ?
7 4 Exit: canget(state(middle,onbox,middle,hasnot)) ?
5 3 Exit: canget(state(middle,onfloor,middle,hasnot)) ?
3 2 Exit: canget(state(atwindow,onfloor,atwindow,hasnot)) ?
1 1 Exit: canget(state(atdoor,onfloor,atwindow,hasnot)) ?

true ?

(78 ms) yes

You might also like