Prolog Tutorial
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.
Comparison Operators
Comparison operators are used to compare two equations or states.
Following are different comparison operators −
Operator Meaning
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.
Operator Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
** Power
// Integer Division
mod Modulus
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
| ?-
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
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
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
true ?
yes
| ?- gte(100,100).
X and Y are same
true ?
yes
| ?-
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.
Operations Definition
Length Calculation With this operation, we can find the length of a list.
Delete Items This operation removes the specified element from a list.
Append Items Append operation adds one list into another (as an item).
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
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
| ?-
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
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
| ?-
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
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 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
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).
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]
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
| ?-
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] ?
| ?- 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
L3 = [a,e] ?
yes
| ?- list_intersect([a,b,c,d,e],[],L3).
L3 = []
yes
| ?-
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
| ?-
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
Sum = 250
yes
| ?- list_sum([8,5,3,4,7,9,6,1],Sum).
Sum = 43
yes
| ?-
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, N, _, F, F) :-!.
N1 is N0 + 1,
F2 is F0 + F1,
? fib(5,X)
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
| ?-
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]
% Example query
?- roots(1, -5, 6, X1, X2).
% Output: Roots are real: 3.0, 2.0
% X1 = 3.0,
% X2 = 2.0.
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 ?
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
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 ?