Prolog Tutorial [Autosaved]
Prolog Tutorial [Autosaved]
Prolog ― Prolog
Introduction
Prolog as the name itself suggests, is the short form of LOGical PROgramming. It is a
logical and declarative programming language. Before diving deep into the concepts of
Prolog, let us first understand what exactly logical programming is.
Logic Programming is one of the Computer Programming Paradigm, in which the program
statements express the facts and rules about different problems within a system of formal
logic. Here, the rules are written in the form of logical clauses, where head and body are
present. For example, H is head and B1, B2, B3 are the elements of the body. Now if we
state that “H is true, when B1, B2, B3 all are true”, this is a rule. On the other hand, facts
are like the rules, but without any body. So, an example of fact is “H is true”.
Some logic programming languages like Datalog or ASP (Answer Set Programming) are
known as purely declarative languages. These languages allow statements about what the
program should accomplish. There is no such step-by-step instruction on how to perform
the task. However, other languages like Prolog, have declarative and also imperative
properties. This may also include procedural statements like “To solve the problem H,
perform B1, B2 and B3”.
We will discuss about the differences between Logic programming and the traditional
functional programming languages. We can illustrate these two using the below diagram:
1
Prolog
From this illustration, we can see that in Functional Programming, we have to define the
procedures, and the rule how the procedures work. These procedures work step by step
to solve one specific problem based on the algorithm. On the other hand, for the Logic
Programming, we will provide knowledge base. Using this knowledge base, the machine
can find answers to the given questions, which is totally different from functional
programming.
In functional programming, we have to mention how one problem can be solved, but in
logic programming we have to specify for which problem we actually want the solution.
Then the logic programming automatically finds a suitable solution that will help us solve
that specific problem.
Functional Programming follows the Von- Logic Programming uses abstract model,
Neumann Architecture, or uses or deals with objects and
the sequential steps. their relationships.
The syntax is actually the sequence of The syntax is basically the logic formulae
statements like (a, s, I). (Horn Clauses).
Logic and controls are mixed together. Logics and controls can be separated.
2
Prolog
What is Prolog?
In Prolog, we need not mention the way how one problem can be solved, we just need to
mention what the problem is, so that Prolog automatically solves it. However, in Prolog
we are supposed to give clues as the solution method.
Facts: The fact is predicate that is true, for example, if we say, “Tom is the son of Jack”,
then this is a fact.
Rules: Rules are extinctions of facts that contain conditional clauses. To satisfy a rule
these conditions should be met. For example, if we define a rule as:
grandfather(X, Y) :- father(X, Z), parent(Z, Y)
This implies that for X to be the grandfather of Y, Z should be a parent of Y and X should
be father of Z.
Questions: And to run a prolog program, we need some questions, and those questions
can be answered by the given facts and rules.
History of
Prolog
The heritage of prolog includes the research on theorem provers and some other
automated deduction system that were developed in 1960s and 1970s. The Inference
mechanism of the Prolog is based on Robinson’s Resolution Principle, that was proposed
in 1965, and Answer extracting mechanism by Green (1968). These ideas came together
forcefully with the advent of linear resolution procedures.
The explicit goal-directed linear resolution procedures, gave impetus to the development
of a general purpose logic programming system. The first Prolog was the Marseille
Prolog based on the work by Colmerauer in the year 1970. The manual of this Marseille
Prolog interpreter (Roussel, 1975) was the first detailed description of the Prolog language.
Some Applications of
Prolog
Prolog is used in various domains. It plays a vital role in automation system. Following are
some other important fields where Prolog is used:
Intelligent Database Retrieval
Natural Language Understanding
3
Prolog
Specification Language
Machine Learning
Robot Planning
Automation System
Problem Solving
4
2. Prolog — Environment Prolog
Setup
Prolog
Version
In this tutorial, we are using GNU Prolog, Version: 1.4.5
Official
Website
This is the official GNU Prolog website where we can see all the necessary details about
GNU Prolog, and also get the download link.
http://www.gprolog.org/
Direct Download
Link below are the direct download links of GNU Prolog for Windows. For other operating
Given
systems like Mac or Linux, you can get the download links by visiting the official website
(Link is given above):
Installation
Guide
Download the exe file and run it.
You will see the window as shown below, then click on next:
5
Prolog
Select proper directory where you want to install the software, otherwise let it be installed
on the default directory. Then click on next.
6
Prolog
You can verify the below screen, and check/uncheck appropriate boxes, otherwise you
can leave it as default. Then click on next.
In the next step, you will see the below screen, then click on Install.
7
Prolog
8
Prolog
9
3. Prolog — Hello Prolog
World
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.
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.
Now let us see how to run the Prolog script file (extension is *.pl) into the Prolog console.
Before running *.pl file, we must store the file into the directory where the GNU prolog
console is pointing, otherwise just change the directory by the following steps:
Step 1: From the prolog console, go to File > Change Dir, then click on that menu.
10
Prolog
Now we can see in the prolog console, it shows that we have successfully changed the
directory.
Step 3: Now create one file (extension is *.pl) and write the code as follows:
Now let’s run the code. To run it, we have to write the file name as follows:
[hello_world]
11
Prolog
12
4. Prolog — Prolog
Basics
In this chapter, we will gain some basic knowledge about Prolog. So we will move on to
the first step of our Prolog Programming.
Knowledge Base: This is one of the fundamental parts of Logic Programming. We will
see in detail about the Knowledge Base, and how it helps in logic programming.
Facts, Rules and Queries: These are the building blocks of logic programming. We will
get some detailed knowledge about facts and rules, and also see some kind of queries
that will be used in logic programming.
Here, we will discuss about the essential building blocks of logic programming. These
building blocks are Facts, Rules and the Queries.
Facts
We can define fact as an explicit relationship between objects, and properties these objects
might have. So facts are unconditionally true in nature. Suppose we have some facts as
given below:
Tom is a cat
Kunal loves to eat Pasta
Hair is black
Nawaz loves to play games
Pratyusha is lazy.
So these are some facts, that are unconditionally true. These are actually statements, that
we have to consider as true.
Syntax
The syntax for facts is as follows:
13
Prolog
relation(object1,object2...).
Example
cat(tom).
loves_to_eat(kunal,pasta
). of_color(hair,black).
loves_to_play_games(nawaz
). lazy(pratyusha).
Rules
We can define rule as an implicit relationship between objects. So facts are conditionally
true. So when one associated condition is true, then the predicate is also true. Suppose
we have some rules as given below:
Lili is happy if she dances.
Tom is hungry if he is searching for food.
Jack and Bili are friends if both of them love to play cricket.
Ryan will go to play if school is closed, and he is free.
So these are some rules that are conditionally true, so when the right hand side is true,
then the left hand side is also true.
Here the symbol ( :- ) will be pronounced as “If”, or “is implied by”. This is also known as
neck symbol, the LHS of this symbol is called the Head, and right hand side is called Body.
Here we can use comma (,) which is known as conjunction, and we can also use semicolon,
that is known as disjunction.
Syntax
Suppose a clause is
like : P :- Q;R.
This can also be written
as P :- Q.
P :- R.
Is understood as
14
Prolog
P :- (Q,R);(S,T,U).
Example
happy(lili) :- dances(lili).
hungry(tom) :-
search_for_food(tom).
friends(jack, bili) :-
lovesCricket(jack),
lovesCricket(bili).
Queries
goToPlay(ryan) :-
isClosed(school), free(ryan).
Queries are some questions on the relationships between objects and object properties.
So question can be anything, as given below:
Is tom a cat?
Does Kunal love to eat pasta?
Is Lili happy?
Will Ryan go to play?
So according to these queries, Logic programming language can find the answer and return
them.
In this section, we will see what knowledge base in logic programming is.
Well, as we know there are three main components in logic programming: Facts, Rules
and Queries. Among these three if we collect the facts and rules as a whole then that
forms a Knowledge Base. So we can say that the knowledge base is a collection of
facts and rules.
Now, we will see how to write some knowledge bases. Suppose we have our very first
knowledge base called KB1. Here in the KB1, we have some facts. The facts are used to
state things, that are unconditionally true of the domain of interest.
Knowledge Base 1
Suppose we have some knowledge, that Priya, Tiyasha, and Jaya are three girls, among
them, Priya can cook. Let’s try to write these facts in a more generic way as shown below:
girl(priya).
girl(tiyasha)
.
girl(jaya).
can_cook(priya) 15
.
Prolog
Note: Here we have written the name in lowercase letters, because in Prolog, a string
starting with uppercase letter indicates a variable.
Now we can use this knowledge base by posing some queries. “Is priya a girl?”, it will reply
“yes”, “is jamini a girl?” then it will answer “No”, because it does not know who jamini is.
Our next question is “Can Priya cook?”, it will say “yes”, but if we ask the same question
for Jaya, it will say “No”.
Output
yes
| ?- [kb1]
.
compiling D:/TP Prolog/Sample_Codes/kb1.pl for byte
code...
D:/TP Prolog/Sample_Codes/kb1.pl compiled, 3 lines read - 489 bytes
written, 10 ms
yes
| ?- girl(priya)
.
yes
| ?- girl(jamini).
no
| ?- can_cook(priya).
yes
| ?- can_cook(jaya).
no
| ?-
Knowledge Base 2
16
Prolog
Let us see another knowledge base, where we have some rules. Rules contain some
information that are conditionally true about the domain of interest. Suppose our
knowledge base is as follows:
sing_a_song(ananya).
listens_to_music(rohit
).
listens_to_music(ananya) :-
sing_a_song(ananya). happy(ananya) :-
sing_a_song(ananya). happy(rohit) :-
listens_to_music(rohit).
So there are some facts and rules given above. The first two are facts, but the rest are
playes_guitar(rohit)
rules. :-
As we know that Ananya sings a song, this implies she also listens to music. So if
we ask “Does Ananya
listens_to_music(rohit).listen to music?”, the answer will be true. Similarly, “is Rohit
happy?”, this will also be true because he listens to music. But if our question is “does
Ananya play guitar?”, then according to the knowledge base, it will say “No”. So these are
some examples of queries based on this Knowledge base.
Output
| ?- [kb2].
compiling D:/TP Prolog/Sample_Codes/kb2.pl for byte code...
D:/TP Prolog/Sample_Codes/kb2.pl compiled, 6 lines read - 1066 bytes
written,
15 ms
yes
| ?- happy(rohit).
yes
| ?- sing_a_song(rohit).
no
| ?- sing_a_song(ananya).
yes
| ?- playes_guitar(rohit).
yes
| ?- playes_guitar(ananya).
no
17
Prolog
| ?- listens_to_music(ananya).
yes
| ?-
Knowledge Base 3
The facts and rules of Knowledge Base 3 are as follows:
can_cook(priya).
can_cook(jaya).
can_cook(tiyasha
).
likes(priya,jaya) :- can_cook(jaya).
likes(priya,tiyasha) :-
Suppose we want to see the members who can cook, we can use one variable in our
can_cook(tiyasha).
query. The variables should start with uppercase letters. In the result, it will show one by
one. If we press enter, then it will come out, otherwise if we press semicolon (;), then it
will show the next result.
Output
| ?- [kb3].
compiling D:/TP Prolog/Sample_Codes/kb3.pl for byte code...
D:/TP Prolog/Sample_Codes/kb3.pl compiled, 5 lines read - 737 bytes
written, 22 ms
warning: D:/TP Prolog/Sample_Codes/kb3.pl:1: redefining procedure
can_cook/1 D:/TP Prolog/Sample_Codes/kb1.pl:4: previous
definition
yes
| ?- can_cook(X).
X = priya ? ;
X = jaya ? ;
X = tiyasha
yes
18
Prolog
| ?- likes(priya,X).
X = jaya ? ;
X =
tiyasha
yes
| ?-
19
5. Prolog — Prolog
Relations
Relationship is one of the main features that we have to properly mention in Prolog. These
relationships can be expressed as facts and rules. After that we will see about the family
relationships, how we can express family based relationships in Prolog, and also see the
recursive relationships of the family.
We will create the knowledge base by creating facts and rules, and play query on them.
Relations in Prolog
In Prolog programs, it specifies relationship between objects and properties of the objects.
Suppose, there’s a statement, “Amit has a bike”, then we are actually declaring the
ownership relationship between two objects — one is Amit and the other is bike.
If we ask a question, “Does Amit own a bike?”, we are actually trying to find out about
one relationship.
There are various kinds of relationships, of which some can be rules as well. A rule can
find out about a relationship even if the relationship is not defined explicitly as a fact.
These clauses can give us the answer that piyus and raj are brothers, but we will get three
pairs of output here. They are: (piyus, piyus), (piyus, raj), (raj, raj). For these pairs, given
conditions are true, but for the pairs (piyus, piyus), (raj, raj), they are not actually
brothers, they are the same persons. So we have to create the clauses properly to form a
relationship.
Here from this tree, we can understand that there are few relationships. Here bob is a
child of pam and tom, and bob also has two children — ann and pat. Bob has one brother
liz, whose parent is also tom. So we want to make predicates as follows:
21
Prolog
Predicates
parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(pat, jim).
parent(bob, peter).
parent(peter, jim).
The user can easily query the Prolog system about relations defined in the program.
The arguments of relations can (among other things) be: concrete objects, or
constants (such as pat and jim), or general objects such as X and Y. Objects of the
first kind in our program are called atoms. Objects of the second kind are called
variables.
Some facts can be written in two different ways, like sex of family members can be written
in either of the forms:
female(pam).
male(tom).
male(bob).
female(liz).
female(pat).
female(ann).
male(jim).
22
Prolog
Now if we want to make mother and sister relationship, then we can write as given below:
female(pam)
.
female(liz)
.
female(pat)
.
female(ann)
.
male(jim).
male(bob).
male(tom).
male(peter)
.
parent(pam,bob).
parent(tom,bob).
parent(tom,liz).
parent(bob,ann). 23
parent(bob,pat).
parent(pat,jim).
parent(bob,peter
Prolog
mother(X,Y):- parent(X,Y),female(X).
father(X,Y):-
parent(X,Y),male(X).
haschild(X):- parent(X,_).
sister(X,Y):-
parent(Z,X),parent(Z,Y),female(
X),X\==Y.
Output
brother(X,Y):-
| ?- [family].
parent(Z,X),parent(Z,Y),male(X)
,X\==Y.
compiling D:/TP Prolog/Sample_Codes/family.pl for byte code...
D:/TP Prolog/Sample_Codes/family.pl compiled, 23 lines read - 3088
bytes written, 9 ms
yes
| ?- parent(X,jim).
X = pat ? ;
X =
peter
yes
| ?-
mother(X
,Y).
X = pam
Y =
bob ? ;
X = pat
Y =
jim ? ;
no
| ?-
haschild
(X).
24
X =
pam ? ;
Prolog
X = tom ? ;
X = bob ? ;
X = bob ? ;
X = pat ? ;
X = bob ? ;
X = peter
yes
| ?- sister(X,Y).
X = liz
Y = bob ? ;
X = ann
Y = pat ? ;
X = ann
Y = peter ? ;
X = pat
Y = ann ? ;
X = pat
Y = peter ? ;
(16 ms) no
| ?-
Now let us see some more relationships that we can make from the previous relationships
of a family. So if we want to make a grandparent relationship, that can be formed as
follows:
25
Prolog
We can also create some other relationships like wife, uncle, etc. We can write the
relationships as given below:
grandparent(X,Y) :- parent(X,Z), parent(Z,Y).
grandmother(X,Z) :- mother(X,Y), parent(Y,Z).
grandfather(X,Z) :- father(X,Y), parent(Y,Z).
wife(X,Y) :- parent(X,Z),parent(Y,Z), female(X),male(Y).
uncle(X,Z) :- brother(X,Y), parent(Y,Z).
So let us write a prolog program to see this in action. Here we will also see the trace to
trace-out the execution.
female(pam)
.
female(liz)
.
female(pat)
.
female(ann)
.
male(jim).
male(bob).
male(tom).
male(peter)
.
26
parent(pam,bob)
.
parent(tom,bob)
Prolog
parent(bob,pat)
.
parent(pat,jim)
.
parent(bob,peter
).
parent(peter,jim
).
mother(X,Y):-
parent(X,Y),fema
le(X).
father(X,Y):-
parent(X,Y),male
(X).
sister(X,Y):-
parent(Z,X),pare
Output
nt(Z,Y),female(X
),X\==Y.
| ?- [family_ext].
brother(X,Y):-
compiling D:/TP Prolog/Sample_Codes/family_ext.pl for byte code...
parent(Z,X),pare
nt(Z,Y),male(X),
D:/TP Prolog/Sample_Codes/family_ext.pl compiled, 27 lines read - 4646
X\==Y.
bytes written, 10 ms
grandparent(X,Y)
:-
| ?- uncle(X,Y).
parent(X,Z),pare
nt(Z,Y).
grandmother(X,Z)
X = peter
:-
Y = jim ? ;
mother(X,Y),pare
nt(Y,Z).
grandfather(X,Z)
no
:-
father(X,Y),pare
| ?- grandparent(X,Y).
nt(Y,Z).
wife(X,Y):-
X = pam
parent(X,Z),parent(Y,Z),female(X),male(Y).
Y = ann ? ;
uncle(X,Z):-brother(X,Y),parent(Y,Z).
X = pam
Y = pat ? ;
X = pam
Y = peter ? ;
27
Prolog
X = tom
Y = ann ? ;
X = tom
Y = pat ? ;
X = tom
Y = peter ? ;
X = bob
Y = jim ? ;
X = bob
Y = jim ? ;
no
| ?- wife(X,Y).
X = pam
Y = tom ? ;
X = pat
Y = peter ? ;
(15 ms) no
| ?-
28
Prolog
Program
| ?- [family_ext].
compiling D:/TP Prolog/Sample_Codes/family_ext.pl for byte code...
D:/TP Prolog/Sample_Codes/family_ext.pl compiled, 27 lines read - 4646
bytes written, 10 ms
X = pam
Y = bob ? ;
X = pat
Y = jim ? ;
no
| ?- trace.
The debugger will first creep -- showing everything (trace)
yes
{trace}
| ?- mother(pam,Y).
1 1 Call: mother(pam,_23 ?
)
2 2 Call: parent(pam,_23 ?
)
2 2 Exit: parent(pam,bob ?
)
3 2 Call: female(pam) ?
3 2 Exit: female(pam) ?
1 1 Exit: mother(pam,bob ?
)
Y = bob
{trace}
| ?- notrace.
The debugger is switched off
yes
| ?-
Recursion in Family
Relationship
In the previous section, we have seen that we can define some family relationships. These
relationships are static in nature. We can also create some recursive relationships which
can be expressed from the following illustration:
30
Prolog
female(pam).
female(liz)
.
female(pat)
.
female(ann)
.
male(jim).
male(bob).
male(tom).
male(peter)
.
parent(pam,bob) 31
.
parent(tom,bob)
.
Prolog
parent(bob,pat)
.
parent(pat,jim)
.
parent(bob,peter
).
parent(peter,jim
).
Output
| ?-
predecessor(X,
[family_rec].
compiling D:/TP Prolog/Sample_Codes/family_rec.pl for byte
Z) :- parent(X,
code...
Z).
- 1851
predecessor(X,
D:/TP Prolog/Sample_Codes/family_rec.pl compiled, 21 lines bytes
Z) :-written,
read parent(X,
14 ms
Y),predecessor(Y
, Z).
yes
| ?- predecessor(peter,X).
X =
jim ? ; no
| ?-
trace.
The
debugger
will first
creep --
showing
everything
(trace)
1 1 Call: predecessor(bob,_23 ?
)
yes 2 2 Call: parent(bob,_23) ?
{trace}
2 2 Exit: parent(bob,ann) ?
| ?- 1 1 Exit: predecessor(bob,ann ?
predecesso )
r(bob,X).
X =
ann ? ;
1 1 Redo: predecessor(bob,ann ?
)
2 2 Redo: parent(bob,ann) ?
32
Prolog
2 2 Exit: parent(bob,pat) ?
1 1 Exit: predecessor(bob,pat) ?
X = pat ? ;
1 1 Redo: predecessor(bob,pat)
?
2 2 Redo: parent(bob,pat) ?
2 2 Exit: parent(bob,peter) ?
1 1 Exit: predecessor(bob,pete ?
r)
X = pete ?
r ; Redo: predecessor(bob,pete ?
r)
1 1
2 2 Call: parent(bob,_92) ?
2 2 Exit: parent(bob,ann) ?
3 2 Call: predecessor(ann,_23)
?
4 3 Call: parent(ann,_23) ?
4 3 Fail: parent(ann,_23) ?
4 3 Call: parent(ann,_141) ?
4 3 Fail: parent(ann,_129) ?
3 2 Fail: predecessor(ann,_23)
?
2 2 Redo: parent(bob,ann) ?
2 2 Exit: parent(bob,pat) ?
3 2 Call: predecessor(pat,_23)
?
4 3 Call: parent(pat,_23) ?
4 3 Exit: parent(pat,jim) ?
3 2 Exit: predecessor(pat,jim)
?
1 1 Exit: predecessor(bob,jim)
?
X = jim ? ;
1 1 Redo: predecessor(bob,jim ?
)
3 2 Redo: predecessor(pat,jim ?
)
4 3 Call: parent(pat,_141) ? 33
4 3 Exit: parent(pat,jim) ?
5 3 Call: predecessor(jim,_23 ?
)
Prolog
6 4 Call: parent(jim,_23) ?
6 4 Fail: parent(jim,_23) ?
6 4 Call: parent(jim,_190) ?
6 4 Fail: parent(jim,_178) ?
5 3 Fail: predecessor(jim,_23)
?
3 2 Fail: predecessor(pat,_23)
?
2 2 Redo: parent(bob,pat) ?
2 2 Exit: parent(bob,peter) ?
3 2 Call: predecessor(peter,_2 ?
3)
4 3 Call: parent(peter,_23) ?
4 3 Exit: parent(peter,jim) ?
3 2 Exit: predecessor(peter,ji ?
m)
1 1 Exit: predecessor(bob,jim)
?
X = jim ?
{trace}
| ?-
34
6. Prolog — Data Prolog
Objects
In this chapter, we will learn data objects in Prolog. They can be divided into few different
categories as shown below:
35
Prolog
In this section, we will discuss the atoms, numbers and the variables of Prolog.
Atoms
Atoms are one variation of constants. They can be any names or objects. There are few
rules that should be followed when we are trying to use Atoms as given below:
Strings of letters, digits and the underscore character, ‘_', starting with a lower-
case letter. For example:
azahar
b59
b_59
b_59AB
b_x25
antara_sarkar
We have to keep in mind that when using atoms of this form, some care is necessary as
some strings of special characters already have a predefined meaning; for example ':-'.
<--->
=======>
...
.:.
::=
This is useful if we want to have an atom that starts with a capital letter. By enclosing it
in quotes, we make it distinguishable from variables:
‘Rubai'
‘Arindam_Chatterjee'
‘Sumit Mitra'
Numbers
Another variation of constants is the Numbers. So integer numbers can be represented as
100, 4, -81, 1202. In Prolog, the normal range of integers is from -16383 to 16383.
Prolog also supports real numbers, but normally the use-case of floating point number is
very less in Prolog programs, because Prolog is for symbolic, non-numeric computation.
The treatment of real numbers depends on the implementation of Prolog. Example of real
numbers are 3.14159, -0.00062, 450.18, etc.
Variables
36
Prolog
The variables come under the Simple Objects section. Variables can be used in many
such cases in our Prolog program, that we have seen earlier. So there are some rules of
defining variables in Prolog.
We can define Prolog variables, such that variables are strings of letters, digits and
underscore characters. They start with an upper-case letter or an underscore
character. Some examples of Variables are:
X
Sum
Memer_name
Student_list
Shoppinglist
_a50
_15
Now the question is, where should we use these anonymous variables?
Suppose in our knowledge base we have some facts — “jim hates tom”, “pat hates bob”.
So if tom wants to find out who hates him, then he can use variables. However, if he wants
to check whether there is someone who hates him, we can use anonymous variables. So
when we want to use the variable, but do not want to reveal the value of the variable,
then we can use anonymous variables.
yes
| ?- hates(X,tom).
37
Prolog
X = jim ? ;
X =
peter
yes
| ?-
hates(_,
tom).
true ? ;
(16 ms)
yes
| ?-
hates(_,pa
t).
no
| ?-
hates(_,fo
x).
true ?
; no
| ?-
38
7. Prolog — Prolog
Operators
In 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
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
39
Prolog
| ?- 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 are used to perform arithmetic operations. There are few different
types of arithmeticOperator
operators as follows:
Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
** Power
// Integer Division
mod Modulus
Let us see one practical code to understand the usage of these operators.
Program
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 40
'),write(C),nl,
Prolog
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
| ?-
41
8. Prolog — Loop & Decision Prolog
Making
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,
Output
count_to_10
| ?- (Y).
[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 ?
42
Prolog
yes
| ?-
Now create a loop that takes lowest and highest values. So, we can use the between() to
simulate loops.
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 ?
; 43
Prolog
true ?
; 0
yes
| ?-
count_up(5,12). 10
true ?
; 11
true ?
; 12
true ?
; 13
true ?
; 14
true ?
; 15
true ?
; 16
true ?
; 17
yes
| ?-
44
Prolog
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:
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
% If-Elif-Else statement
| ?- [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
45
Prolog
| ?- gte(10,20).
X is smaller
true
? yes
| ?-
gte(1
00,10
0).
X and
Y are
same
true
? yes
| ?-
46
9. Prolog — Conjunctions & Prolog
Disjunctions
In this chapter, we shall discuss Conjunction and Disjunction properties. These properties
are used in other programming languages using AND and OR logics. Prolog also uses the
same logic in its syntax.
Conjunction
Conjunction (AND logic) can be implemented using the comma (,) operator. So two
predicates separated by comma are joined with AND statement. Suppose we have a
predicate, parent(jhon, bob), which means “Jhon is parent of Bob”, and another
predicate, male(jhon), which means “Jhon is male”. So we can make another predicate
that father(jhon,bob), which means “Jhon is father of Bob”. We can define predicate
father, when he is parent AND he is male.
Disjunction
Disjunction (OR logic) can be implemented using the semi-colon (;) operator. So two
predicates as
predicate separated
child(),bythis
semi-colon
will bearetrue
joined with OR
when statement. Suppose
father(jhon, bob) is we
truehave
ORa
predicate, father(jhon,
mother(lili,bob) is true. bob). This tells that “Jhon is father of Bob”, and another
predicate, mother(lili,bob), this tells that “lili is mother of bob”. If we create another
Program
parent(jhon,bob)
.
parent(lili,bob)
.
male(jhon).
female(lili)
.
%
Conjunction
Logic
father(X,Y)
:-
Output
parent(X,Y),
male(X).
| ?- [conj_disj].
mother(X,Y)
compiling
:- D:/TP Prolog/Sample_Codes/conj_disj.pl for byte code...
parent(X,Y),
female(X). 47
%
Disjunction
Logic
Prolog
yes
| ?- father(jhon,bob).
yes
| ?- child_of(jhon,bob).
true
? yes
| ?-
child
_of(l
ili,b
ob).
yes
| ?-
48
10. Prolog — Prolog
Lists
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.
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.
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
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.
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
50
Prolog
| ?- list_member(b,[a,b,c]).
true
? yes
| ?-
list_
membe
r(b,
[a,
[b,c]
]).
no
| ?-
list_
membe
r([b,
c],
[a,
[b,c]
]).
Length
true
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
? yesthe elements in a list L and instantiate N to their number. As was the case with our
count
| ?- relations involving lists, it is useful to consider two cases:
previous
list_
If list is empty, then length is 0.
membe
r(d,
If the list is not empty, then L = [Head|Tail], then its length is 1 + length of Tail.
[a,b,
c]).
Program
list_length([],0).
no
list_length([_|TAIL],N)
| ?- :- list_length(TAIL,N1), N is N1 + 1.
list_
Output
membe
r(d,
[a,b,
| ?- [list_basics].
c]).
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).
51
Prolog
Len =
10 yes
| ?-
list_le
ngth([]
,Len).
Len =
0 yes
| ?-
list_l
ength(
[[a,b]
,
[c,d],
[e,f]]
,Len).
Concatenation
Concatenation of two lists means adding the list items of the second list after the first one.
Len =
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.
3 yes
| ?- 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).
52
Prolog
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],
Delete from
List
[p,q,r],a,b,c] yes
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
yes
| ?- list_delete(a,[a,e,i,o,u],NewList).
53
Prolog
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
| ?- 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 =
Insert into
[[a,b],e,i,o,u] yes
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
Output
list_insert(X,L,R) :-
| ?- [list_basics].
list_delete(X,R,L).
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
55
Prolog
| ?- 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 =
no
Repositioning
| ?- operations of list
items are repositioning operations:
Following
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.
X is member of L if either:
56
Prolog
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,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]
57
Prolog
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]
58
X =
[d,c,b,a]
Prolog
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.
This can also be used to check whether two lists are reverse of each other or not.
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,
OutputRevTail),list_concat(RevTa
il, [Head],Reversed).
| ?- [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).
59
Prolog
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] (16
ms) yes
| ?-
list_shift([a,b
,c,d,e],
[b,c,d,e,a]).
Order Operation
yes
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.
Program
list_order([X]).
60
Prolog
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])
.
Set operations on
no
lists
Following are the set operations:
| ?-
Set operations Definition
Subset Finding
Operation
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.
61
Prolog
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 = []
X = [x,y,z] ? a
X = [x,y]
X = [x,z]
X = [x]
X = [y,z]
62
Prolog
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]
63
Prolog
| ?- 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 = []
64
Prolog
yes
| ?-
Misc Operations on
Lists are some miscellaneous operations that can be performed on lists:
Following
Even and Odd Length Finding Verifies whether the list has odd number or
even number of elements.
Program
list_even_len([]).
list_even_len([Head|Tail]) :- list_odd_len(Tail).
list_odd_len([_]).
65
Prolog
list_odd_len([Head|Tail]) :- list_even_len(Tail).
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, 4 lines read - 726
bytes written, 20 ms
yes
| ?- list_odd_len([a,2,b,3,c]).
true
? yes
| ?-
list_
odd_l
en([a
,2,b,
3]).
no
| ?-
list_
even_
len([
a,2,b
,3]).
true
Divide
? yes List
Operation
This
| ?-operation divides a list into two lists, and these lists are of approximately same length.
Solist_
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
even_
the odd placed elements into one list, and all even placed elements into another list. We
len([
will define a predicate, list_divide(L1,L2,L3) to solve this task.
a,2,b
If given list is empty, then it will return empty lists.
,3,c]
).
66
no
| ?-
Prolog
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
| ?-
67
Prolog
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|
Output
Rest],MaxRest),
| ?-max_of_two(X,MaxRest,Max).
[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,1
12,48,4]
,Max).
Max =
112 ?
68
yes
| ?-
Prolog
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
Sum = 250
yes
| ?- list_sum([8,5,3,4,7,9,6,1],Sum).
Sum =
43 yes
| ?-
69
Prolog
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
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|
Output
Rb],[B|M]) :-
| ?-A [merge_sort].
> B, merge([A|
Ra],Rb,M).
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
70
Prolog
| ?- 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
| ?-
71
11. Prolog — Recursion and Prolog
Structures
Recursion
Recursion is a technique in which one predicate uses itself (may be with some other
predicates) to find the truth value.
There may be some other examples also, so let us see one family example. So if we want
to express the predecessor logic, that can be expressed using the following diagram:
72
Prolog
Structures
For example, the date can be viewed as a structure with three components — day, month
and year. Then the date 9th April, 2020 can be written as: date(9, apr, 2020).
Now let us see one example of structures in Prolog. We will define a structure of points,
Segments and Triangle as structures.
To represent a point, a line segment and a triangle using structure in Prolog, we can
consider following statements:
p1 : point(1, 1)
p2: point(2,3)
73
Prolog
Note: Structures can be naturally pictured as trees. Prolog can be viewed as a language
for processing trees.
Matching in Prolog
Matching is used to check whether two given terms are same (identical) or the variables
in both terms can have the same objects after being instantiated. Let us see one example.
Following rules are to be used to check whether two terms S and T match:
If S and T are constants, S=T if both are same objects.
If S is a variable and T is anything, T=S.
If T is variable and S is anything, S=T.
If S and T are structures, S=T if:
o S and T have same functor.
o All their corresponding arguments components have to match.
Binary Trees
74
Prolog
Each node has three fields, data and two nodes. One node with no child (leaf node)
structure is written as node(value, nil, nil), node with only one left child is written as
node(value, left_node, nil), node with only one right child is written as node(value,
nil; right_node), and node with both child has node(value, left_node, right_node).
75
12. Prolog — Prolog
Backtracking
Let us see how backtracking takes place using one tree like structure:
Suppose A to G are some rules and facts. We start from A and want to reach G. The proper
path will be A-C-G, but at first, it will go from A to B, then B to D. When it finds that D is
not the destination, it backtracks to B, then go to E, and backtracks again to B, as there is
no other child of B, then it backtracks to A, thus it searches for G, and finally found G in
the path A-C-G. (Dashed lines are indicating the backtracking.) So when it finds G, it
stops.
Now we know, what is the backtracking in Prolog. Let us see one example,
Note: While we are running some prolog code, during backtracking there may be multiple
answers, we can press semicolon (;) to get next answers one by one, that helps to
backtrack. Otherwise when we get one result, it will stop.
Now, consider a situation, where two people X and Y can pay each other, but the condition
is that a boy can pay to a girl, so X will be a boy, and Y will be a girl. So for these we have
defined some facts and rules:
Knowledge Base
boy(tom).
boy(bob).
76
Prolog
girl(alice)
.
girl(lili).
pay(X,Y) :-
Following is the illustration of the above scenario:
boy(X),
girl(Y).
As X will be a boy, so there are two choices, and for each boy there are two choices alice
and lili. Now let us see the output, how backtracking is working.
Output
| ?- [backtrack].
compiling D:/TP Prolog/Sample_Codes/backtrack.pl for byte code...
D:/TP Prolog/Sample_Codes/backtrack.pl compiled, 5 lines read - 703
bytes written, 22 ms
yes
| ?- pay(X,Y).
X = tom
Y = alice ?
X = tom
77
Prolog
Y = alice ? ;
X = tom
Y = lili ? ;
X = bob
Y = alice ? ;
X = bob
Y =
lili
yes
| ?-
trace.
The
debugge
r will
first
creep
-- 1 1 Call: pay(_23,_24) ?
showing
2 2 Call: boy(_23) ?
everyth
ing 2 2 Exit: boy(tom) ?
(trace)
3 2 Call: girl(_24) ?
3 2 Exit: girl(alice) ?
(16 ms)
yes 1 1 Exit: pay(tom,alice)
?
{trace}
X ?-tom
| =
pay(X,Y
Y = alic ? ;
).
e
1 1 Redo: pay(tom,alice)
?
3 2 Redo: girl(alice) ?
3 2 Exit: girl(lili) ?
1 1 Exit: pay(tom,lili) ?
X = tom
Y = lili ? ;
1 1 Redo:
pay(tom,lili) ?
2 2 Redo: boy(tom)
?
2
2 Exit: boy(bob) 78
?
Prolog
3 2 Call: girl(_24) ?
3 2 Exit: girl(alice) ?
1 1 Exit: pay(bob,alice)
?
X = bob
Y = alice ? ;
1 1 Redo: pay(bob,alice)
?
3 2 Redo: girl(alice) ?
3 2 Exit: girl(lili) ?
1 1 Exit: pay(bob,lili) ?
X = bob
Y = lili
yes
{trace
}
| ?-
Preventing
Backtracking
So far we have seen some concepts of backtracking. Now let us see some drawbacks of
backtracking. Sometimes we write the same predicates more than once when our program
demands, for example to write recursive rules or to make some decision making systems.
In such cases uncontrolled backtracking may cause inefficiency in a program. To resolve
this, we will use the Cut in Prolog.
The first goal f(1,Y) instantiated Y to 0. The second goal becomes 2 < 0 which fails. Prolog
tries through backtracking two unfruitful alternatives (Rule 2 and Rule 3). If we see closer,
we can observe that:
79
Prolog
The three rules are mutually exclusive and one of them at most will succeed.
As soon as one of them succeeds there is no point in trying to use the others as
they are bound to fail.
So we can use cut to resolve this. The cut can be expressed using Exclamation symbol.
The prolog syntax is as follows:
f (X,0) :- X < 3, !. % Rule 1
f (X,2) :- 3 =< X, X < 6, !. % Rule 2
f (X,4) :- 6 =< X. % Rule 3
Now if we use the same question, ?- f (1,Y), 2 < Y. Prolog choose rule 1 since 1 < 3 and
fails the goal 2 < Y fails. Prolog will try to backtrack, but not beyond the point marked ! In
the program, rule 2 and rule 3 will not be generated.
Program
| ?- [backtrack].
compiling D:/TP Prolog/Sample_Codes/backtrack.pl for byte code...
D:/TP Prolog/Sample_Codes/backtrack.pl compiled, 10 lines read - 1224
bytes written, 17 ms
yes
| ?- f(1,Y), 2<Y.
no
| ?- trace
.
The debugger will first creep -- showing everything (trace)
yes
{trace}
| ?- 2<Y.
f(1,Y),
1 1 Call: f(1,_23)
?
2 2 Call: 1<3 ?
2 2 Exit: 1<3 ? 80
Prolog
1 1 Exit: f(1,0)
?
3 1 Call:
2<0 ?
3 1 Fail: 2<0 ?
1 1 Redo: f(1,0)
?
2 2 Call:
3=<1 ?
2 2 Fail:
3=<1 ?
2
2 Call:
2 2 Fail: 6=<1 ?
6=<1 ?
1 1 Fail: f(1,_23)
?
(46 ms) no
{trace}
| ?-
Program
| ?- [backtrack].
1 1 Call: [backtrack] ?
compiling D:/TP Prolog/Sample_Codes/backtrack.pl for byte code...
D:/TP Prolog/Sample_Codes/backtrack.pl compiled, 10 lines read - 1373
bytes written, 15 ms
1 1 Exit: [backtrack] ?
(16 ms) yes
{trace}
| ?- 2<Y.
f(1,Y),
1 1 Call: f(1,_23)
?
2 2 Call: 1<3 ?
2 2 Exit: 1<3 ?
1 1 Exit: f(1,0) ?
3 1 Call: 2<0 ?
3 1 Fail: 2<0 ?
81
Prolog
no
{trace}
| ?-
Negation as
Failure
Here we will perform failure when condition does not satisfy. Suppose we have a
statement, “Mary likes all animals but snakes”, we will express this in Prolog.
It would be very easy and straight forward, if the statement is “Mary likes all animals”. In
that case we can write “Mary likes X if X is an animal”. And in prolog we can write this
statement as, likes(mary, X) := animal(X).
The ‘fail’ statement causes the failure. Now let us see how it works in Prolog.
Program
animal(dog).
animal(cat).
animal(elephant)
.
animal(tiger).
animal(cobra).
animal(python)
.
snake(cobra).
snake(python)
.
Output
likes(mary,
X)?-
| :-[negate_fail].
snake(X), !,
compiling
fail. D:/TP Prolog/Sample_Codes/negate_fail.pl for byte code...
D:/TP Prolog/Sample_Codes/negate_fail.pl compiled, 11 lines read - 1118
likes(mary,
bytes
X) :- written, 17 ms
animal(X). 82
Prolog
yes
| ?- likes(mary,elephant).
yes
| ?- likes(mary,tiger).
yes
| ?- likes(mary,python).
no
| ?- likes(mary,cobra).
no
| ?- trace
.
The debugger will first creep -- showing everything
(trace)
yes
{trace}
| ?- likes(mary,dog).
1 1 Call: likes(mary,dog)
?
2 2 Call: snake(dog) ?
2 2 Fail: snake(dog) ?
2 2 Call: animal(dog) ?
2 2 Exit: animal(dog) ?
1 1 Exit: likes(mary,dog)
?
yes
{trace}
| ?-
likes(mary,python).
1 1 Call: likes(mary,python ?
)
2 2 Call: snake(python) ?
2 2 Exit: snake(python) ?
3 2 Call: fail ?
3 2 Fail: fail ?
1 1 Fail: likes(mary,python ?
) 83
Prolog
no
{trace}
| ?-
84
13. Prolog — Different and Prolog
Not
Here we will define two predicates — different and not. The different predicate will
check whether two given arguments are same or not. If they are same, it will return
false, otherwise it will return true. The not predicate is used to negate some statement,
which means, when a statement is true, then not(statement) will be false, otherwise if
the statement is false, then not(statement) will be true.
So the term ‘different’ can be expressed in three different ways as given below:
X and Y are not literally the same
X and Y do not match
The values of arithmetic expression X and Y are not equal
Program
Output
| ?- [diff_rel].
compiling D:/TP Prolog/Sample_Codes/diff_rel.pl for byte code...
D:/TP Prolog/Sample_Codes/diff_rel.pl:2: warning: singleton variables
[X,Y] for different/2
D:/TP Prolog/Sample_Codes/diff_rel.pl compiled, 2 lines read - 327
bytes written, 11 ms
yes
| ?- different(100,200).
85
Prolog
yes
| ?- different(100,100).
no
| ?- different(abc,def).
yes
| ?- different(abc,abc).
no
| ?-
Program
Output
| ?- [diff_rel].
compiling D:/TP Prolog/Sample_Codes/diff_rel.pl for byte code...
D:/TP Prolog/Sample_Codes/diff_rel.pl compiled, 0 lines read - 556
bytes written, 17 ms
yes
| ?- different(100,200).
yes
| ?- different(100,100).
no
| ?- different(abc,def).
yes
| ?- different(abc,abc).
no
| ?-
86
Prolog
Not Relation in
Prolog
The not relation is very much useful in different cases. In our traditional programming
languages also, we use the logical not operation to negate some statement. So it means
that when a statement is true, then not(statement) will be false, otherwise if the statement
is false, then not(statement) will be true.
So if P is true, then cut and fail, this will return false, otherwise it will be true. Now let us
see one simple code to understand this concept.
Program
Output
| ?- [not_rel].
compiling D:/TP Prolog/Sample_Codes/not_rel.pl for byte code...
D:/TP Prolog/Sample_Codes/not_rel.pl compiled, 0 lines read - 630
bytes written, 17 ms
yes
| ?- not(true).
no
| ?- not(fail).
yes
| ?-
87
14. Prolog — Inputs and Prolog
Outputs
In this chapter, we will see some techniques to handle inputs and outputs through prolog.
We will use some built in predicates to do these tasks, and also see file handling
techniques.
So far we have seen that we can write a program and the query on the console to
execute. In some cases, we print something on the console, that are written in our prolog
code. So here we will see that writing and reading tasks in more detail using prolog. So
this will be the input and output handling techniques.
Program
| ?-
write(56). 56
yes
| ?-
write('hello').
hello
yes
| ?-
write('hello'),nl,write('world').
hello
world
88
Prolog
yes
| ?- write("ABCDE")
.
[65,66,67,68,69
]
yes
From the above example, we can see that the write() predicate can write the contents into
the console. We can use ’nl’ to create a new line. And from this example, it is clear that, if
we want to print some string on the console, we have to use single quotes (‘string‘). But if
we use double quote (“string”), then it will return a list of ASCII values.
Program
cube :-
write('Write a number:
'), read(Number),
process(Number).
process(stop) :-
!.
process(Number) :
-
C is Number *
Number *
Number,
Output
write('Cube of '),write(Number),write(':
| ?- [read_write].
'),write(C),nl, cube.
compiling D:/TP Prolog/Sample_Codes/read_write.pl for byte code...
D:/TP Prolog/Sample_Codes/read_write.pl compiled, 9 lines read - 1226
bytes written, 12 ms
89
Prolog
Write a number:
10. Cube of 10:
1000
Write a number:
12. Cube of 12:
1728 Write a
number: 8.
Cube of 8: 512
Write a number:
stop
.
The
(31 tab() Predicate
ms) yes
The
| ?-tab() is one additional predicate that can be used to put some blank-spaces while we
write something. So it takes a number as an argument, and prints those many number of
blank spaces.
Program
| ?-
write('hello'),tab(15),write('world').
hello world
yes
We
| ?- use
will tabs
write('We'),tab(5),write('will'),tab(5),
write('use'),tab(5),write('tabs').
yes
| ?-
Reading/Writing
Files
In this section, we will see how we can use files to read from, and write into the files.
There are some built-in predicates, that can be used to read from file and write into it.
Prolog Commands
90
Prolog
| ?- told('myFile.txt').
uncaught exception: error(existence_error(procedure,told/1),top_level/0)
| ?- told("myFile.txt").
uncaught exception: error(existence_error(procedure,told/1),top_level/0)
| ?- tell('myFile.txt').
yes
| ?- tell('myFile.txt').
yes
| ?- write('Hello World').
yes
| ?- write(' Writing into a file'),tab(5),write('myFile.txt'),nl.
yes
| ?- write("Write some ASCII values").
yes
| ?- told.
yes
| ?-
Output (myFile.txt)
Similarly, we can also read from files. Let us see some example of reading from file.
Output
| ?-
see('sample_predicate.txt'),
read(X),
read(Y)
, seen,
read(Z)
.
the_end
.
X =
end_of_
file
Y =
end_of_
Sofile
from this example, we can see that using the see() predicate we can read from the file.
Now
Z = after using seen command, the control transfers to the console again. So finally it
takes input from console.
the_end
Processing
yes files of terms
| ?-
We have seen how to read specific contents (few lines) of a file. Now if we want to
read/process all the contents of a file, we need to write a clause to process file
(process_file), until we reach the end of the file.
Program
process_file
:-
read(Line)
,
Line \== end_of_file, % when Line is not not end of file,
call process. process(Line).
domestic(dog)
.
domestic(cat)
Output
.
| ?- [process_file].
compiling D:/TP Prolog/Sample_Codes/process_file.pl for byte code...
D:/TP Prolog/Sample_Codes/process_file.pl compiled, 9 lines read - 774
bytes written, 23 ms
yes
| ?- see('sample_predicate.txt'), process_file,
seen. likes(lili,cat)
likes(jhon,dog)
domestic(dog
)
domestic(cat
)
true ?
Manipulating
| ?-
characters
Using read() and write() we can read or write the value of atoms, predicates, strings, etc.
Now in this section we will see how to write single characters into the current output
stream, or how to read from current input stream. So there are some predefined predicates
to do these tasks.
Program
| ?-
put(97),put(98),put(99),put(100),put(101).
abcde
yes
| ?-
put(97),put(66),put(99),put(100),put(101). 93
Prolog
aBcde
yes
| ?-
put_char('h'),put_char('e'),put_char('l'),put_char('l'),put_char('o')
. hello
yes
| ?-
The get_char(C) and get_code(C) predicates
To read a single character from the current input stream, we can use the get_char(C)
predicate. This will take the character. if we want the ASCII code, we can use get_code(C).
Program
| ?-
get_char(X). A.
X = 'A'
yes
uncaught exception: error(syntax_error('user_input:6 (char:689)
expression expected'),read_term/3)
| ?-
get_code(X). A.
X = 65
yes
uncaught exception: error(syntax_error('user_input:7 (char:14)
expression expected'),read_term/3)
| ?-
94
Prolog
Constructing
Atoms
The atom constructing means from a list of characters, we can make one atom, or from a
list of ASCII values also we can make atoms. To do this, we have to use atom_chars() and
atom_codes() predicates. In both cases, the first argument will be one variable, and the
second argument will be a list. So atom_chars() constructs atom from characters, but
atom_codes() construct atoms from ASCII sequence.
Example
| ?- atom_chars(X, ['t','i','g','e','r']).
X =
tiger
yes
| ?-
atom_cha
rs(A,
['t','o'
,'m']).
A =
tom
yes
| ?-
atom_c
odes(X
,
[97,98
,99,10
0,101]
).
Decomposing Atoms
X =
The atom decomposing means from an atom, we can get a sequence of characters, or a
sequence ASCII codes. To do this, we have to use the same atom_chars() and
atom_codes()
abcde predicates. But one difference is that, in both cases, the first argument will
be one atom, and the second argument will be a variable. So atom_chars() decomposes
atom to characters, but atom_codes() decomposes atoms to ASCII sequence.
yes
Example
| ?-
atom_cod
| ?- atom_chars(tiger,X).
es(A,
[97,98,9
9]). 95
A =
Prolog
X =
[t,i,g,e,r]
yes
| ?-
atom_chars(tom
,A).
A =
[t,o,m]
yes
| ?-
atom_codes
(tiger,X).
X =
[116,105,1
03,101,114
]
The
yes consult in
Prolog
The consulting is a technique, that is used to merge the predicates from different files. We
| ?-
can use the consult() predicate, and pass the filename to attach the predicates. Let us see
atom_codes
one example program to understand this concept.
(tom,A).
likes(suman,mouse
).
likes(angshu,deer
Output
).
96
Prolog
| ?- [prog1].
compiling D:/TP Prolog/Sample_Codes/prog1.pl for byte code...
D:/TP Prolog/Sample_Codes/prog1.pl compiled, 2 lines read - 443 bytes
written,
23 ms
yes
| ?- likes(joy,rabbit).
yes
| ?- likes(suman,mouse).
no
| ?- consult('prog2.pl').
compiling D:/TP Prolog/Sample_Codes/prog2.pl for byte code...
D:/TP Prolog/Sample_Codes/prog2.pl compiled, 1 lines read - 366 bytes
written,
20 ms
warning: D:/TP Prolog/Sample_Codes/prog2.pl:1: redefining procedure
likes/2 D:/TP Prolog/Sample_Codes/prog1.pl:1: previous
definition
yes
| ?- likes(suman,mouse).
yes
| ?- likes(joy,rabbit).
Now from this output we can understand that this is not as simple as it seems. If two files
no
have completely different clauses, then it will work fine. But if there are same
| ?-
predicates, then while we try to consult the file, it will check the predicates from the
second file, when it finds some match, it simply deletes all of the entry of the same
predicates from the local database, then load them again from the second file.
97
15. Prolog — Built-In Prolog
Predicates
In Prolog, we have seen the user defined predicates in most of the cases, but there are
some built-in-predicates. There are three types of built-in predicates as given below:
Identifying terms
Decomposing structures
Collecting all solutions
So this is the list of some predicates that are falls under the identifying terms group:
Predicate Description
The var(X)
Predicate
When X is not initialized, then, it will show true, otherwise false. So let us see an example.
Example
| ?- var(X).
yes
| ?- X = 5, var(X).
no
| ?- var([X]).
no
98
Prolog
| ?-
Example
| ?- nonvar(X).
no
| ?- X = 5,nonvar(X).
X = 5
yes
| ?- nonvar([X]).
yes
| ?-
The atom(X)
Predicate
This will return true, when a non-variable term with 0 argument and a not numeric term is
passed as X, otherwise false.
Example
| ?- atom(paul).
yes
| ?- X = paul,atom(X).
X =
paul
yes
| ?-
atom([]
).
yes 99
| ?-
atom([a
,b]).
Prolog
no
| ?-
The number(X)
Predicate
This will return true, X stands for any number, otherwise false.
Example
| ?- number(X).
no
| ?- X=5,number(X).
X = 5
yes
| ?- number(5.46).
yes
| ?-
Example
| ?- integer(5).
yes
| ?- integer(5.46).
no
| ?-
The float(X)
Predicate
This will return true, X is a floating point number, otherwise false.
Example
| ?- float(5).
100
Prolog
no
| ?- float(5.46).
yes
| ?-
The atomic(X)
Predicate
We have atom(X), that is too specific, it returns false for numeric data, the atomic(X) is
like atom(X) but it accepts number.
Example
| ?- atom(5).
no
| ?- atomic(5).
yes
| ?-
Example
| ?- compound([]).
no
| ?- compound([a]).
yes
| ?- compound(b(a)).
yes
| ?-
101
Prolog
The ground(X)
Predicate
This will return true, if X does not contain any un-instantiated variables. This also checks
inside the compound terms, otherwise returns false.
Example
| ?- ground(X).
no
| ?- ground(a(b,X)).
no
| ?- ground(a).
yes
| ?- ground([a,b,c]).
yes
| ?-
Decomposing
Structures
Now we will see, another group of built-in predicates, that is Decomposing structures. We
have seen the identifying terms before. So when we are using compound structures we
cannot use a variable to check or make a functor. It will return error. So functor name
cannot be represented by a variable.
Error
X = tree, Y = X(maple).
Syntax error Y=X<<here>>(maple)
Now, let us see some inbuilt predicates that falls under the Decomposing structures group.
Example
| ?- functor(t(f(X),a,T),Func,N).
Func = t
102
Prolog
N = 3
Example
| ?- arg(1,t(t(X),[]),A).
A = t(X)
yes
| ?- arg(2,t(t(X),[]),A).
A = []
yes
| ?-
Now, let us see another example. In this example, we are checking that the first argument
of D will be 12, the second argument will be apr and the third argument will be 2020.
Example
D =
date(12,apr,2020)
yes
| ?-
The ../2
Predicate
This is another predicate represented as double dot (..). This takes 2 arguments, so ‘/2’ is
written. So Term = .. L, this is true if L is a list that contains the functor of Term, followed
by its arguments.
Example
| ?- f(a,b) =.. L.
103
Prolog
L =
[f,a,b]
yes
| ?- T =..
[is_blue,s
am,today].
T =
F = f
L =
f(6,3) N
= 2
N1 = 6
Y = [3]
yes
| ?-
Collecting All
Solutions
Now let us see the third category called the collecting all solutions, that falls under built-
in predicates in Prolog.
We have seen that to generate all of the given solutions of a given goal using the
semicolon in the prompt. So here is an example of it.
Example
| ?- member(X, [1,2,3,4]).
X = 1 ? ;
X = 2 ? ;
104
Prolog
X = 3 ? ;
X = 4
yes
Sometimes, we need to generate all of the solutions to some goal within a program in
some AI related applications. So there are three built-in predicates that will help us to get
the results. These predicates are as follows:
findall/3
setoff/3
bagof/3
These three predicates take three arguments, so we have written ‘/3’ after the name of
the predicates.
These are also known as meta-predicates. These are used to manipulate Prolog’s Proof
strategy.
Syntax
findall(X,P,L).
setof(X,P,L)
bagof(X,P,L)
These three predicates a list of all objects X, such that the goal P is satisfied (example:
age(X,Age)). They all repeatedly call the goal P, by instantiating variable X within P and
adding it to the list L. This stops when there is no more solution.
Here we will see the three different built-in predicates findall/3, setof/3 and the bagof/3,
that fall into the category, collecting all solutions.
Now we can also do some advancement on them. The second argument, which is the goal,
that might be a compound goal. Then the syntax will be as findall(X, (Predicate on X,
other goal), L)
And also the first argument can be a term of any complexity. So let us see the examples
of these few rules, and check the output. 105
Prolog
Example
Results =
[1,2,3,4] yes
| ?- findall(X,
(member(X,
[1,2,3,4]), X >
2), Results).
Results =
[3,4] yes
| ?-
findall(X/Y,
(member(X,
[1,2,3,4]), Y
is X * X),
Results).
The setof/3
Results = Predicate
The setof/3 is also like findall/3, but here it removes all of the duplicate outputs, and the
answers will be sorted.
[1/1,2/4,3/9,4/16] yes
If any variable is used in the goal, then that will not appear in the first argument, setof/3
| ?-
will return a separate result for each possible instantiation of that variable.
Let us see one example to understand this setof/3. Suppose we have a knowledge base
as shown below:
age(peter, 7).
age(ann, 5).
age(pat, 8).
age(tom, 5).
age(ann, 5).
Here we can see that age(ann, 5) has two entries in the knowledge base. And the ages
are not sorted, and names are not sorted lexicographically in this case. Now let us see one
example of setof/3 usage.
Example 1
| ?- setof(Child, age(Child,Age),Results).
106
Prolog
Age = 5
Results = [ann,tom] ? ;
Age = 7
Results = [peter] ? ;
Age = 8
Results =
[pat]
We can use the nested call of setof/3, to collect together the individual results. We will see
another example, where the first argument will be Age/Children. As the second argument,
it will take another setof like before. So this will return a list of (age/Children) pair. Let us
see this in the prolog execution:
Example 2
AllResults =
[5/[ann,tom],7/[peter],8/[pat]] yes
| ?-
Now if we do not care about a variable that does not appear in the first argument, then
we can use the following example:
Example 3
Results =
[ann,pat,peter,tom] yes
| ?-
Here we are using the upper caret symbol (^), this indicates that the Age is not in the first
argument. So we will read this as, “Find the set of all children, such that the child has an
Age (whatever it may be), and put the result in Results”.
107
Prolog
The bagof/3 is like setof/3, but here it does not remove the duplicate outputs, and the
answers may not be sorted.
Let us see one example to understand this bagof/3. Suppose we have a knowledge base
as follows:
Knowledge base
age(peter, 7).
age(ann, 5).
age(pat, 8).
age(tom, 5).
age(ann, 5).
Example
| ?- bagof(Child, age(Child,Age),Results).
Age = 5
Results = [ann,tom,ann] ? ;
Age = 7
Results = [peter] ? ;
Age = 8
Results =
[pat]
The bagof/3 is different from findall/3, as this generates separate results for all the
variables in the goal that do not appear in the first argument. We will see this using an
example below:
Example
| ?- findall(Child, age(Child,Age),Results).
Results = [peter,ann,pat,tom,ann]
108
Prolog
yes
| ?-
Mathematical Predicates
Following are the mathematical predicates:
Predicates Description
ceiling(X). Round up
Besides these, there are some other predicates such as sin, cos, tan, asin, acos, atan,
atan2, sinh, cosh, tanh, asinh, acosh, atanh, log, log10, exp, pi, etc.
Example
| ?- random(0,10,X).
X = 0
yes
| ?- random(0,10,X).
X = 5
yes
| ?- random(0,10,X).
X = 1
109
Prolog
yes
| ?-
between(0,10,X).
X = 0 ? a
X = 1
X = 2
X = 3
X = 4
X = 5
X = 6
X = 7
X = 8
X = 9
X = 1
0
X = 3
yes
| ?- X is abs(-
8).
X = 8
yes 110
Prolog
| ?- X is max(10,5).
X = 10
yes
| ?- X is min(10,5).
X = 5
yes
| ?- X is round(10.56).
X = 11
yes
| ?- X is
truncate(10.56).
X = 10
yes
| ?- X is floor(10.56).
X = 10
yes
| ?- X is
ceiling(10.56).
X = 11
yes
| ?- X is sqrt(144).
X = 12.0
yes
| ?- 111
16. Prolog — Tree Data Structure (Case Prolog
Study)
So far we have seen different concepts of logic programming in Prolog. Now we will see
one case study on Prolog. We will see how to implement a tree data structure using Prolog,
and we will create our own operators. So let us start the planning.
We have to implement this tree using prolog. We have some operations as follows:
op(500, xfx, ‘is_parent’).
op(500, xfx, ‘is_sibling_of’).
op(500, xfx, ‘is_at_same_level’).
And another predicate namely leaf_node(Node)
In these operators, you have seen some parameters as (500, xfx, <operator_name>).
The first argument (here 500) is the priority of that operator. The ‘xfx’ indicates that this
is a binary operator and the <operator_name> is the name of the operator.
These operators can be used to define the tree database. We can use these operators as
follows:
a is_parent b, or is_parent(a, b). So this indicates that node a is the parent of
node b.
112
Prolog
As shown above, other rules are defined in the code. So let us see the program to get
better view.
Program
:- op(500,xfx,'is_parent').
:- op(500,xfx,'is_sibling_of').
X is_sibling_of Y :- Z is_parent X,
Z is_parent Y,
X \== Y.
:-op(500,xfx,'is_at_same_level').
Prolog
X is_at_same_level X .
X is_at_same_level Y :- W is_parent X,
Z is_parent Y,
W is_at_same_level Z.
Output
| ?- [case_tree].
compiling D:/TP Prolog/Sample_Codes/case_tree.pl for byte code...
D:/TP Prolog/Sample_Codes/case_tree.pl:20: warning: singleton variables
[Child] for leaf_node/1
D:/TP Prolog/Sample_Codes/case_tree.pl compiled, 28 lines read - 3244
bytes written, 7 ms
yes
| ?- i is_parent p.
yes
| ?- i is_parent s.
no
| ?- is_parent(i,p).
yes
| ?- e is_sibling_of f.
true
? yes
| ?-
is_si
bling
_of(e
,g).
no
| ?-
leaf_
node(
v).
yes 114
| ?-
leaf_
node(
a).
Prolog
true
? yes
| ?-
l
is_at
_same
_leve
l v.
More
no on Tree Data
Structure
| ?-we will see some more operations that will be performed on the above given tree
Here,
data structure.
As we have created the last database, we will create a new program that will hold these
operations, then consult the new file to use these operations on our pre-existing program.
115
Prolog
path(Node): This will display the path from the root node to the given node. To
solve this, suppose X is parent of Node, then find path(X), then write X. When root
node ‘a’ is reached, it will stop.
locate(Node): This will locate a node (Node) from the root of the tree. In this
case, we will call the path(Node) and write the Node.
Program
Output
| ?- consult('case_tree_more.pl').
compiling D:/TP Prolog/Sample_Codes/case_tree_more.pl for byte code...
D:/TP Prolog/Sample_Codes/case_tree_more.pl compiled, 9 lines read - 866
bytes written, 6 ms
yes
| ?- path(n).
a --> c --> h -->
true
? yes
| ?-
path(
s).
a -->
d -->
j -->
true
116
? yes
Prolog
| ?- path(w).
no
| ?- locate(n).
a --> c --> h --> n
true
? yes
| ?-
locat
e(s).
a -->
d -->
j -->
s
true
? yes
| ?-
locat
e(w).
Advances in Tree Data
Structures
Now
no let us define some advanced operations on the same tree data structure.
| ?-
117
Prolog
Here we will see how to find the height of a node, that is, the length of the longest path
from that node, using the Prolog built-in predicate setof/3. This predicate takes (Template,
Goal, Set). This binds Set to the list of all instances of Template satisfying the goal Goal.
We have already defined the tree before, so we will consult the current code to execute
these set of operations without redefining the tree database again.
ht(Node,H). This finds the height. It also checks whether a node is leaf or not, if so, then
sets height H as 0, otherwise recursively finds the height of children of Node, and add 1
to them.
max([X|R], M,A). This calculates the max element from the list, and a value M. So if M is
maximum, then it returns M, otherwise, it returns the maximum element of list that is
greater than M. To solve this, if given list is empty, return M as max element, otherwise
check whether Head is greater than M or not, if so, then call max() using the tail part and
the value X, otherwise call max() using tail and the value M.
height(N,H). This uses the setof/3 predicate. This will find the set of results using the
goal ht(N,Z) for the template Z and stores into the list type variable called Set. Now find
the max of Set, and value 0, store the result into H.
Program
height(N,H) :- setof(Z,ht(N,Z),Set),
max(Set,0,H).
ht(Node,0) :- leaf_node(Node),!.
118
Prolog
ht(Child,H1)
, H is H1 +
1.
max([],M,M).
max([X|R],M,A) :- (X > M
Output
-> max(R,X,A) ;
max(R,M,A)).
| ?- consult('case_tree_adv.pl').
compiling D:/TP Prolog/Sample_Codes/case_tree_adv.pl for byte code...
D:/TP Prolog/Sample_Codes/case_tree_adv.pl compiled, 9 lines read - 2060
bytes written, 9 ms
yes
| ?- ht(c,H).
H = 1 ?
a H = 3
H = 3
H = 2
H = 2
yes
| ?-
max([1,5
,3,4,2],
10,Max).
Max =
10 yes
| ?-
max([1,
5,3,40,
2],10,M
ax).
119
Max =
40 yes
Prolog
| ?- setof(H, ht(c,H),Set).
Set = [1,2,3]
yes
| ?- max([1,2,3],0,H).
H = 3
yes
| ?- height(c,H).
H = 3
yes
| ?- height(a,H).
H = 4
yes
| ?-
120
Prolog
Prolog — Examples
121
17. Prolog ― Basic Prolog
Programs
In the following chapter, we are going to discuss basic prolog examples to:
Find minimum maximum of two numbers
Find the equivalent resistance of a resistive circuit
Verify whether a line segment is horizontal, vertical or oblique
Program
find_max(X, Y, X) :- X >= Y, !.
find_max(X, Y, Y) :- X < Y.
find_min(X, Y, X) :- X =< Y, !.
find_min(X, Y, Y) :- X > Y.
Output
| ?- find_max(100,200,Max).
Max = 200
yes
| ?- find_max(40,10,Max).
Max =
40 yes
| ?-
find_mi
n(40,10
,Min).
Min =
10 122
Prolog
yes
| ?- find_min(100,200,Min).
Min = 100
yes
| ?-
We have to find the equivalent resistance of this network. At first, we will try to get the
result by hand, then try to see whether the result is matching with the prolog output or
not.
Here 10 Ohm and 40 Ohm resistors are in parallel, then that is in series with 12 Ohm, and
the equivalent resistor of the lower half is parallel with 30 Ohm. So let’s try to calculate
the equivalent resistance.
R3 = (10 * 40)/(10 + 40) = 400/50 = 8 Ohm
123
Prolog
R4 = R3 + 12 = 8 + 12 = 20 Ohm
R5 = (20 * 30)/(20 + 30) = 12 Ohm
Program
series(R1,R2,Re) :- Re is R1 + R2.
parallel(R1,R2,Re) :- Re is ((R1 * R2) / (R1 +
R2)).
Output
| ?- [resistance].
compiling D:/TP Prolog/Sample_Codes/resistance.pl for byte code...
D:/TP Prolog/Sample_Codes/resistance.pl compiled, 1 lines read - 804
bytes written, 14 ms
yes
| ?- parallel(10,40,R3).
R3 = 8.0
yes
| ?- series(8,12,R4).
R4 = 20
yes
| ?- parallel(20,30,R5).
R5 = 12.0
yes
| ?- parallel(10,40,R3),series(R3,12,R4),parallel(R4,30,R5).
R3 = 8.0
R4 = 20.0
R5 = 12.0
yes
| ?-
124
Prolog
Program
vertical(seg(point(X,_),point(X,_))).
horizontal(seg(point(_,Y),point(_,Y)
)).
oblique(seg(point(X1,Y1),point(X2,Y2
Output
)))
| ?-:-X1
[line_seg].
\== X2,
Y1 \== Y2. 125
Prolog
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
| ?-
126
18. Prolog — Examples of Prolog
Cuts
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 1
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) ?
127
Prolog
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 2
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
128
Prolog
{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]
129
19. Prolog — Towers of Hanoi Prolog
Problem
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.
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,
130
Prolog
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 ?
131
20. Prolog — Linked Prolog
Lists
Following chapters describe how to generate/create linked lists using recursive structures.
Linked list has two components, the integer part and the link part. The link part will hold
another node. End of list will have nil into the link part.
Note: The smallest possible list is nil, and every other list will contain nil as the "next" of
the end node. In list terminology, the first element is usually called the head of the list,
and the rest of the list is called the tail part. Thus the head of the above list is 2, and its
tail is the list node(5, node(6, nil)).
Program
add_back(nil, E, NList)
:- NList =
node(E,nil).
add_back(node(Head,Tail), E, NList)
:- add_back(Tail, E, NewTail),
NList = node(Head,NewTail).
Output
| ?- [linked_list].
compiling D:/TP Prolog/Sample_Codes/linked_list.pl for byte code...
D:/TP Prolog/Sample_Codes/linked_list.pl compiled, 7 lines read - 966
bytes written, 14 ms
L1 = node(6,nil)
L2 = node(5,node(6,nil))
132
Prolog
L3 = node(2,node(5,node(6,nil)))
yes
| ?- add_back(nil, 6, L1), add_back(L1, 5, L2), add_back(L2, 2, L3).
L1 = node(6,nil)
L2 = node(6,node(5,nil))
L3 = node(6,node(5,node(2,nil)))
yes
| ?- add_front(nil, 6, L1), add_front(L1, 5, L2), add_back(L2, 2, L3).
L1 = node(6,nil)
L2 = node(5,node(6,nil))
L3 = node(5,node(6,node(2,nil)))
yes
| ?-
133
21. Prolog — Monkey and Banana Prolog
Problem
In this prolog example, we will see one very interesting and famous problem, The Monkey
and Banana Problem.
Problem Statement
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.
134
Prolog
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,hasno
t), 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)
).
135
canget(state(_,_,_,has))
. canget(State1) :-
move(State1,_,State2),
Prolog
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
debug
ger
will
first
creep
--
showi 1 1 Call: canget(state(atdoor,onfloor,atwindow,hasnot)) ?
ng 2 2 Call:
every move(state(atdoor,onfloor,atwindow,hasnot),_52,_92) ?
thing 2 2 Exit:
move(state(atdoor,onfloor,atwindow,hasnot),walk(atdoor,_80),state(_80,onf
(trac
loor,a
e) twindow,hasnot)) ?
3 2 Call: canget(state(_80,onfloor,atwindow,hasnot)) ?
yes 4 3 Call:
move(state(_80,onfloor,atwindow,hasnot),_110,_150) ?
{trac 4
3 Exit:
move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwindow,onbox,a
e}
twindo w,hasnot)) ?
| ?-
cange 5 3 Call: canget(state(atwindow,onbox,atwindow,hasnot)) ?
t(sta
te(at 6 4 Call:
door, 6 move(state(atwindow,onbox,atwindow,hasnot),_165,_205) ?
onflo 4 Fail:
or, 5 3 Fail:
move(state(atwindow,onbox,atwindow,hasnot),_165,_193) ?
atwin 4 canget(state(atwindow,onbox,atwindow,hasnot)) ?
3 Redo:
dow,
move(state(atwindow,onfloor,atwindow,hasnot),climb,state(atwindow,onbox,a
hasno
twindo w,hasnot)) ?
t)).
136
Prolog
43 Exit:
move(state(atwindow,onfloor,atwindow,hasnot),drag(atwindow,_138),state(
_138,onf loor,_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,_138,hasno
7 4 Call: canget(state(_138,onbox,_138,hasnot)) ?
t)) ?
8 5 Call:
move(state(_138,onbox,_138,hasnot),_223,_263) ?
8
5 Exit:
move(state(middle,onbox,middle,hasnot),grasp,state(middle,onbox,middle,h
as)) ?
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:
3 2 Exit:
canget(state(middle,onfloor,middle,hasnot)) ?
canget(state(atwindow,onfloor,atwindow,hasnot)) ?
1 1 Exit:
canget(state(atdoor,onfloor,atwindow,hasnot)) ?
true ?
(78 ms)
yes
137