Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Lab 1

Download as pdf or txt
Download as pdf or txt
You are on page 1of 34

Lab .

Se Topics Page

Lab 1 Introducing Prolog and SWI-Prolog Environment ................................................ 1

Lab 2 Syntax and Data objects of Prolog..............................................................................

Lab 3 Fact, Rules, and Queries in Prolog...............................................................................

Lab 4 Mathematical and logical operation in Prolog........................................................

Lab 5 Lists and Recursion in Prolog part I.............................................................................

Lab 6 Lists and Recursion in Prolog part II............................................................................

Lab 7 Input Output and Interfacing in Prolog.....................................................................

Lab 8 Modules in Prolog.............................................................................................................

Lab 9 AI in Prolog fact representation and implementation of different AI


functions...............................................................................................................................

Lab 10 Implementation of Breadth and Depth First Search In Prolog goal finding,

Lab 11 Implementation of Breadth and Depth First Search In Prolog path finding
and path Checking..................................................................................

Lab 12 Implementation of Heuristic Function in Prolog. Straight line distance and


Manhattan distance cost computation in prolog....................................................

Lab 13 Implementation of A* search in Prolog......................................................................


Laboratory Secession One

Introducing Prolog and its Environment

I. What is Prolog?

Prolog (programming in logic) is one of the most widely used programming languages in
artificial intelligence research. As opposed to imperative languages such as C or Java (the
latter of which also happens to be object-oriented) it is a declarative programming
language.

That means, when implementing the solution to a problem, instead of specifying how to
achieve a certain goal in a certain situation, we specify what the situation (rules and facts)
and the goal (query) are and let the Prolog interpreter derive the solution for us.
Prolog is very useful in some problem areas, such as artificial intelligence, natural language
processing, and databases and so on but pretty useless in others, such as graphics or
numerical algorithms.
A program is partly like a database but much more powerful since we can also have
general rules to infer new facts!

A Prolog interpreter can follow these facts/rules and answer queries by sophisticated search.
There are different version and products of prolog interpreters. The Commonly used
interpreters in academic environment for prolog is SWI-Prolog

II. Introduction to SWI PROLOG

Swi‐Prolog can be freely downloaded from http://www.swi‐prolog.org and can easily install
it.

Starting Prolog and loading a program in a Swi-prolog

The SWI-Prolog executable swipl-win.exe can be started from the Start Menu or by
opening a .pl file holding Prolog program text from the Windows explorer.The .PL file
extension can be changed during installation. See section 3.2.

Start All Programs SWI-Prolog Prolog

1.3 Create a source file of prolog


There are two options
A. Using Notepad Editor
 Open notepad Using Windows start menu
 Write the source code
 Save the source code file in a pl extension (mysample1.pl)
B. Using Swi-Prolog Editor
 After you open Swi_Prolog interpreter
 Click file from the Menu bar
 Click New and from the file menu
 A new save as dialog box will appear
 Provide name and save the new pl file and write the source codes later

1.4 Consulting a source file


 1. In a prolog window click file menu
 2. Click consult
 3. Select appropriate file and press open button

Fig 1.1 SWI-Prolog interfaces

Getting Started Prolog Programming:


An Example bigger.pl
In the introduction it has been said that Prolog is a declarative (or descriptive) language.
 Programming in Prolog means describing the world.
 Using such programs means asking Prolog questions about the previously described
world.
 The simplest way of describing the world is by stating facts, like the following one:
Let us assume that, we have some simple fact that we want to declare like “elephant is
bigger animal than horse” for the prolog compiler. The first step is generating a new prolog
editor either of the described above way and write the following structure.
bigger (elephant, horse).
And save the source code with bigger.pl file name(see the picture described in fig 1.2).

The above states, quite intuitively describes, the fact that an elephant is bigger than a
horse. (Whether the world described by a Prolog program has anything to do with our real
world is, of course, entirely up to the programmer imagination.)
Let's add a few more facts to our little program:
bigger(elephant, horse).
bigger(horse, donkey).
bigger(donkey, dog).
bigger(donkey, monkey).

Fig 1.2 source code with prolog editor


This is a syntactically correct program, and after having compiled it we can ask the Prolog
system questions (or queries in proper Prolog-jargon) about it. Here's an example how we
can provides questions (or queries in proper Prolog-jargon):
Even though there are different ways for presenting queries for prolog engine, queries for
prolog system in SWI-prolog environment queries usually presented in the interactive
interface of the SWI-prolog interpreter shown in the following picture.

In this environment prior to query presentation, the user first should call the prolog source
file (bigger.pl) to memory buffer for consultation of the stored facts and rules in the file
usually named as knowledge base for some domain specific query need of a user. (Refer
consulting source file topics in the previous portion).

Fig 1.3 interactive interface of SWI-Prolog


The user of bigger.pl knowledge base may present the following sample queries and can obtain the
respected answer see fig 1.4.

Fig 1.4 user query and answer of the prolog engine in the interactive interface

In a similar fascine we can present different queries for the prolog engine. The following are few
instance of user query and the answer from prolog engine that consulted prolog engine.
?- bigger(donkey, dog). The answer for this query will be
true
Or
?bigger(donkey,X). the answer will be
Y = dog ;
Y = monkey.
or
?- bigger(X,Y).the answer will be
X = elephant,
Y = horse ;
X = horse,
Y = donkey ;
X = donkey,
Y = dog ;
X = donkey,
Y = monkey.
or
?- bigger(monkey, elephant).
The answer will be false
Fig 1.6 queries and positive responds as interpreted by SWI-Prolog engine

All the answers we got are exactly the answer we expected?

But what happens when we ask the other way round?


?- bigger(elephant, monkey).

Fig 1.7 queries and false responds for unknown facts interpreted by SWI-Prolog engine
According to this elephants are not bigger than monkeys. This is clearly wrong as far as our real world
is concerned, but if you check our little program again (check contents of biiger.pl at fig 1.2), you will
find that it says nothing about the relationship between elephants and monkeys. This kind of problem
can be solved by generalized rules.

Example 2 Family.pl
Let us see other features of prolog programming with family.pl. Sometimes it may be too tedious to
describe every real world facts to prolog engine explicitly through fact description. Instead, if there are
some common features and clear relationships among real world facts, programmer may write rules in
their knowledge base that used to generalize about facts for prolog engine from available facts during
interpretation of queries (see fig 1.8). In this example the programmer define rules for father, mother,
daughter, and son facts using available facts such as parent, male, and female predicates.

male(abebe).
male(tadesse).
female(aster).
female(almaz).m
parent(abebe,tadesse).
parent(almaz,tadesse).
parent(abebe,aster).
parent(almaz,aster).
father(X,Y):-parent(X,Y),male(X).
mother(X,Y):-parent(X,Y),female(X).
doughter(X,Y):-parent(Y,X),female(X).
son(X,Y):-parent(Y,X),male(X).

Fig 1.8 knowledge base for family relationship made using facts and rules
In the above example one can see that, facts such as parent, male, and female predicates
are written in different format than their precedent set of facts. First the argument for each
predicates written in capital letter (variable writing form for prolog programming) since,
variables usually used to generalize about some common features of objects in the real
world.
Notes: Variables in prolog programming written using alphanumeric character that starts
with capital letter and constant facts written using any combination of alphanumeric
characters that starts with small letters. (Next time we will see in detail about prolog object
type).
Figure 1.9 shows queries and responds of SWI-Prolog engine by consulting family.pl
knowledge base.
Exercise of Lab session one
1. Take your own case and write prolog codes and test with different form of queries
2. Consider family.pla as your knowledge base and define other rule for brother, sister,
and other relationship of family.
Laboratory Secession Two

Objectives of the laboratory secession is to provide students an insight about object


structure of a prolog language and its usage in different data representation.

Syntax of Prolog

Data objects/Terms

Types of objects that a prolog interpreter recognizes by its syntactic forms are called data-
object/terms.

The central data structure in Prolog is that of a term. There are terms of four kinds: atoms,
numbers, variables, and compound terms. Atoms and numbers are sometimes grouped
together and called atomic terms or simple object. A combination of two or more atomic
terms can form compound term or structure.

Simple objects (terms) can be a static facts (constant) that represent specific real-world
facts or events or a generalized fact that can symbolically represent similar real-world
objects’ fact called variable. We have already seen the different between variables and
constants terms in the previous section examples.

Variable start with upper case letter while constant start with small letter. No additional
information such as data type declaration has been communicated to prolog in order to
recognize the objects.

Data objects

Simple objects Structure

Constant Variables

Atoms Numbers

Fig 2.1 anatomy of terms

Static facts (constant) can be either atoms or numbers.


Atoms: Atoms are usually strings made up of lower- and uppercase letters, digits, and the
underscore, starting with a lowercase letter. The following are all valid Prolog atoms:

Example

elephant, b, abcXYZ, x_123, another_pint_for_me_please

On top of that also any series of arbitrary characters enclosed in single quotes denotes an
atom.

'This is also a Prolog atom.'

Finally, strings made up solely of special characters like + - * = < > : & (check the manual of
our SWI-Prolog system for the exact set of these characters) are also atoms.

Examples:

+, ::, <------>, ***

Numbers. All Prolog implementations have an integer type: a sequence of digits,


optionally preceded by a - (minus) for negative number.

Variables. Variables are strings of letters, digits, and the underscore, starting with a
capital letter or an underscore. Examples:

X, Elephant, _4711, X_1_2, MyVariable, _

The last one of the above examples (the single underscore) constitutes a special case. It is
called the anonymous variable and is used when the value of a variable is of no particular
interest. Multiple occurrences of the anonymous variable in one expression are assumed to
be distinct, i.e., their values don't necessarily have to be the same.

Structure/Compound terms.
Compound terms are made up of a functor (a Prolog atom) and a number of arguments
(Prolog terms, i.e., atoms, numbers, variables, or other compound terms) enclosed in
parentheses and separated by commas.
The following are some examples for compound terms:
is_bigger(horse, X),
f(g(X, _), 7),
'My Functor'(dog)
Structured objects (or simply structures are objects that have several components. The
components themselves can, in turn, be structures. For example,

Date is an example of structured or compound terms as it is represented in a tree and as it


is represented in a prolog.

The date can be viewed as a structure with three components day, month, and year.
Although composed of several components, structures are treated in the program as single
objects. In order to combine the components in to a single object we have to choose a
function

You can write more structure forms in the following way

haliday('Ethiopian ChristMass',date(january,7,2013)).
haliday('Eid_al_adha',date(january,10,2013)).
haliday('Epiphany',date(january,19,2013)).
haliday('Adwa Victory day',date(march,2,2013)).
haliday('The phrophet Birth Day',date(april,11,2013)).
haliday('Ethiopian Good Friday',date(april,21,2013)).
haliday('Ethiopian Easter Sunday',date(april,23,2013)).
haliday('International Labor Day',date(may,1,2013)).
haliday('Freedom Day',date(may,5,2013)).
haliday('Derg Downfall Day',date(may,28,2013)).
haliday('Ethiopian New Year',date(september,11,2013)).
haliday('Finding of the True
Cross',date(september,27,2013)).
haliday('Eid-al-Fitr',date(october,24,2013)).
haliday('Eid al-Adha',date(december,31,2013)).

Structures (Compound terms) in a prolog can be of the following three forms.

Exercises
1. Write the appropriate prolog statement for the following statements.
a. Abebe likes aster.
b. Kebede is handsom.
c. Today is holiday.
d. Abebe likes French food.
e. Haile G/Silassie was famous runner since from 1996E.C.
f. Aster merried to Alemayeu.
g. Every man is mortal.
h. Africa connected with ther est of world through Addis Ababa
2. See the following table and represent the data in prolog to keep the appropriate
information students information.

Student Department Batch Sex Date of


Name Birth
Alemu Computer 4th M January 4,
Kebede Science 1995
Dawit Taye Computer 3rd M March 2,
Science 1997
Sofonias Information 4th M January 1,
Alemu system 1991
Aster Ezira Information 3rd F January 4,
System 1995
Lulit Information 4th F January 4,
Sewmehon Technoogy 1995
Senait Information 3rd F January 4,
Alemu technologyt 1995

(s)
3. Assume given a set of facts of the form father(name1,name2) (name1 is the father
of name2).
a. Define a predicate brother(X,Y) which holds iff X and Y are brothers.
b. Define a predicate cousin(X,Y) which holds iff X and Y are cousins.
c. Define a predicate grandson(X,Y) which holds iff X is a grandson of Y.
d. Define a predicate descendent(X,Y) which holds iff X is a descendent of Y.
e. Consider the following genealogical tree:
f. father(a,b).
g. father(a,c).
h. father(b,d).
i. father(b,e).
j. father(c,f).

whose graphical representation is:

a
/\
b c
/\ |
d ef
4. See the following knowledge base interpret what the program does with your own
statement.
Laboratory Secession 3 : Operators and Arithmetic

Operators

Prolog defines a set of prefix, infix, and postfix operators that includes the classical
arithmetic symbols: “+”, “-”, “*”, and “/”. The Prolog interpreter considers operators as
functors and transforms expressions into terms.

Thus, 2 * 3 + 4 * 2 is equivalent to +(*(2, 3), *(4, 2)).

The mapping of operators onto terms is governed by rules of priority and classes of
associatively:

Arithmetic in Prolog

Prolog is not the programming language of choice for carrying out heavy duty
mathematics. It does, however, provide arithmetical capabilities. The pattern for
evaluating arithmetic expressions is (where Expression is some arithmetical expression) the
general for arithmetic expression in prolog is

X is Expression
or
is(X,expression).
example
writing X is 10+5*6/3.12 to prolog consol gives you the following result
X = 20.
the above statement can be rewritten in the form of is(X,expression) as follows
is(X,+(10,/(*(5,6),3.12))).
to find the predicate equivalent for the arithmetic expression you should first know the
operator precedence
 Multiplication
 division
 addition
 subtraction
for example if you want to convert Y is 2*6/2+12 start first forming the multiplication
predicate then the division predicate the addition and finally the is predicate.
is(Y,+(/(*(2,6),2),12)).
to find the equivalent expression for a particular arithmetic expression you can use
display(expression).
is(X,+(10,/(*(5,6),3)))
Typical Arithmetic Operators
+ addition
_substraction
/division
* multiplication
mod modulo

Population Examples
pop(usa,280).
pop(india,1000).
pop(china,1200).
pop(brazil,130).
pop(ethiopia,90).
area(usa,3).
area(india,1).
area(china,4).
area(brazil,3).
area(ethiopia,1.3).
density(X,Y) :-
pop(X,P),
area(X,A),
Y is P/A.
Typical relational operators.
X = Y X and Y stand for the same number
X \= Y X and Y stand for different numbers
X < Y X is less than Y
X > Y X is greater than Y
X =< Y X is less than or equal to Y
X >= Y X is greater than or equal to Y

Exercises
1. Write a prolog program that can calculate area of a circle by taking the radios of a
circle from the user.
Area=pi*2r
2. Write a prolog program that can respond to peoples as Hello Miss Name or Mr. by
taking Sex information from the User.
3. re write the following expression in the forms of is(X,Expression format).
a. X is 12/2*14-2+13
Laboratory Secession 4: Cuts, Negation, and Related Predicates

Cuts

The cut predicate, written “!”, is a device to prune some backtracking alternatives. It
modifies the way Prolog explores goals and enables a programmer to control the execution
of programs. When executed in the body of a clause, the cut always succeeds and removes
backtracking points set before it in the current clause. Figure 4.1 shows the execution model
of the rule p(X) :- q(X), !, r(X) that contains a cut.

Fig. 4.1 The execution box representing the rule p(X) :- q(X), !, r(X).

Let us suppose that a predicate P consists of three clauses:

P :- A1, ..., Ai, !, Ai+1, ..., An.

P :- B1, ..., Bm.

P :- C1, ..., Cp.

Executing the cut in the first clause has the following consequences:

1. All other clauses of the predicate below the clause containing the cut are pruned. That is,
here the two remaining clauses of P will not be tried.

2. All the goals to the left of the cut are also pruned. That is, A1, ..., Ai will no longer
be tried.

3. However, it will be possible to backtrack on goals to the right of the cut.

P :- A1, ..., Ai, !, Ai+1, ..., An.

P :- B1, ..., Bm.

P :- C1, ..., Cp.

Cuts are intended to improve the speed and memory consumption of a program.
However, wrongly placed cuts may discard some useful backtracking paths and solutions.
Then, they may introduce vicious bugs that are often difficult to track. Therefore, cuts
should be used carefully.

An acceptable use of cuts is to express determinism. Deterministic predicates always


produce a definite solution; it is not necessary then to maintain backtracking possibilities. A
simple example of it is given by the minimum of two numbers:
minimum(X, Y, X) :- X < Y.

minimum(X, Y, Y) :- X >= Y.

Once the comparisons done, there is no means to backtrack because both clauses are
mutually exclusive. This can be expressed by adding two cuts:

minimum(X, Y, X) :- X < Y, !.

minimum(X, Y, Y) :- X >= Y, !.

Some programmers would rewrite minimum/3 using a single cut:

minimum(X, Y, X) :- X < Y, !. minimum(X, Y, Y).

The idea behind this is that once Prolog has compared X and Y in the first clause, it is not
necessary to compare them again in the second one. Although the latter program may be
more efficient in terms of speed, it is obscure. In the first version of minimum/3, cuts respect
the logical meaning of the program and do not impair its legibility. Such cuts are called
green cuts. The cut in the second minimum/3 predicate is to avoid writing a condition
explicitly. Such cuts are error-prone and are called red cuts. Sometimes red cuts are crucial
to a program but when overused, they are a bad programming practice.

Negation

A logic program contains no negative information, only queries that can be proven or not.
The Prolog built-in negation corresponds to a query failure: the program cannot prove the
query. The negation symbol is written “\+” or not in older Prolog systems:

• If G succeeds then\+ G fails.


• If G fails then\+ G succeeds. The Prolog negation is defined using a cut:

\+(P) :- P, !, fail. \+(P) :- true.

where fail/0 is a built-in predicate that always fails. Most of the time, it is preferable to
ensure that a negated goal is ground: all its variables are instantiated. Let us illustrate it
with the somewhat odd rule:

mother(X, Y) :- \+ male(X), child(Y, X).

and facts:

child(telemachus, penelope).

male(ulysses).

male(telemachus).

The query

?- mother(X, Y).
false because the subgoal male(X) is not ground and unifies with the fact male(ulysses). If
the subgoals are inverted:

mother(X, Y) :- child(Y, X), \+ male(X).

the term child(Y, X) unifies with the substitution X = penelope and Y =


telemachus, and since male(penelope) is not in the database, the goal mother(X,
Y) succeeds. Predicates similar to “\+” include if-then and if-then-else constructs. If-then is
expressed by the built-in ’->’/2 operator. Its syntax is

Condition -> Action

as in

print_if_parent(X, Y) :- (parent(X, Y) -> write(X), nl,


write(Y), nl).

?- print_if_parent(X, Y). penelope telemachus

X = penelope, Y = telemachus

Just like negation, ’->’/2 is defined using a cut:

’->’(P, Q):- P, !, Q.

The if-then-else predicate is an extension of ’->’/2 with a second member to the right. Its
syntax is

Condition -> Then ; Else

If Condition succeeds, Then is executed, otherwise Else is executed.

The once/1 Predicate

The built-in predicate once/1 also controls Prolog execution. once(P) executes P once and
removes backtrack points from it. If P is a conjunction of goals as in the rule:

A :- B1, B2, once((B3, ..., Bi)), Bi+1, ..., Bn.

the backtracking path goes directly from Bi+1 to B2, skipping B3, ..., Bi. It is necessary to
bracket the conjunction inside once twice because its arity is equal to one. A single level of
brackets, as in once(B3, ..., Bi), would tell Prolog that once/1 has an arity of i-3. once(Goal)
is defined as:

once(Goal) :- Goal, !
Laboratory Secession 5: Lists and Recursion

Lists are data structures essential to many programs. A Prolog list is a sequence of an
arbitrary number of terms separated by commas and enclosed within square brackets. For
example:

• [a] is a list made of an atom.


• [a, b] is a list made of two atoms.
• [a, X, father(X, kebede)] is a list made of an atom, a variable, and a compound
term.
• [[a, b], [[[father(X, kebede)]]]] is a list made of two sub- lists.
• [] is the atom representing the empty list.

Although it is not obvious from these examples, Prolog lists are compound terms and the
square bracketed notation is only a shortcut. The list functor is a dot: “./2”, and [a, b] is
equivalent to the term .(a,.(b,[])). Computationally, lists are recursive structures. They
consist of two parts:

• a head, the first element of a list,


• and a tail, the remaining list without its first element.

The head and the tail correspond to the first and second argument of the Prolog list func-
tor. Figure 5.1 shows the term structure of the list [a, b, c]. The tail of a list is possibly empty
as in .(c,[])).

The term structure of the list [a, b, c].

The notation “|” splits a list into its head and tail, and [H | T] is equivalent to .(H, T).
Splitting a list enables us to access any element of it and therefore it is a very frequent
operation. Here are some examples of its use:

?- [a, b] = [H | T]. H = a, T = [b]

?- [a] = [H | T]. H = a, T = []

?- [a, [b]] = [H | T]. H = a, T = [[b]]

?- [a, b, c, d] = [X, Y | T]. X = a, Y = b, T = [c, d]

?- [[a, b, c], d, e] = [H | T]. H = [a, b, c], T = [d, e]


The empty list cannot be split:

?- [] = [H | T]. No

Some List-Handling Predicates

Many applications require extensive list processing. This section describes some useful
predicates. Generally, Prolog systems provide a set of built-in list predicates. Consult your
manual to see which ones; there is no use in reinventing the wheel.

The member/2 Predicate

The member/2 predicate checks whether an element is a member of a list:

?- member(a, [b, c, a]).

Yes

?- member(a, [c, d]).

No

member/2 is defined as:

member(X, [X | Y]). % Termination case

member(X, [Y | YS]) :- % Recursive case

member(X, YS).

We could also use anonymous variables to improve legibility and rewrite mem- ber/2 as

member(X, [X | _]).

member(X, [_ | YS]) :- member(X, YS).

member/2 can be queried with variables to generate elements member of a list, as in:

?- member(X, [a, b, c]).

X = a ;

X = b ;

X = c ;

False

Or lists containing an element:

?- member(a, Z).

Z = [a | Y] ; Z = [Y, a | X] ; etc.
Finally, the query:

?- \+ member(X, L).

true

where X and L are ground variables, returns Yes if member(X, L) fails and No if it succeeds.

The append/3 Predicate

The append/3 predicateappendstwo lists and unifiesthe resultto a thirdargument:

?- append([a, b, c], [d, e, f], [a, b, c, d, e, f]). Yes

?- append([a, b], [c, d], [e, f]). No

?- append([a, b], [c, d], L). L = [a, b, c, d]

?- append(L, [c, d], [a, b, c, d]). L = [a, b]

?- append(L1, L2, [a, b, c]). L1 = [], L2 = [a, b, c] ; L1 = [a], L2 = [b, c] ;

etc., with all the combinations.

append/3 is defined as

append([], L, L).

append([X | XS], YS, [X | ZS]) :- append(XS, YS, ZS).

The delete/3 Predicate

The delete/3 predicate deletes a given element from a list. Its synopsis is:

delete(List, Element, ListWithoutElement).

example queries

?- delete([2,3,4,5,6],6,X).

X = [2, 3, 4, 5].

It is defined as:

delete([], _, []).

delete([E | List], E, ListWithoutE):- !, delete(List, E,


ListWithoutE).

delete([H | List], E, [H | ListWithoutE]):- H \= E, !,


delete(List, E, ListWithoutE).
The three clauses are mutually exclusive, and the cuts make it possible to omit the
condition H \= E in the second rule. This improves the program efficiency but makes it less
legible.

The intersection/3 Predicate

The intersection/3 predicate computesthe intersection of two sets represented as lists:


intersection(InputSet1, InputSet2, Intersection).

?- intersection([a, b, c], [d, b, e, a], L).

L = [a, b]

InputSet1 and InputSet2 should be without duplicates; otherwise intersection/3


approximates the intersection set relatively to the first argument:

?- intersection([a, b, c, a], [d, b, e, a], L).

L = [a, b, a]

The predicate is defined as:

% Termination case

intersection([], _, []).

% Head of L1 is in L2

intersection([X | L1], L2, [X | L3]) :- member(X, L2),

!, intersection(L1, L2, L3). % Head of L1 is not in L2

intersection([X | L1], L2, L3) :- \+ member(X, L2), !,


intersection(L1, L2, L3).

As for delete/3, clauses of intersection/3 are mutually exclusive, and the programmer can
omit the condition\+ member(X, L2) in the third clause.

The reverse/2 Predicate

The reverse/2 predicate reverses the elements of a list. There are two classic ways to define
it. The first definition is straight forward but consumes much memory. It is often called the
naïve reverse:

reverse([],[]). reverse([X | XS], YS] :- reverse(XS,,


RXS), append(RX, [X], Y).

A second solution improves the memory consumption. It uses a third argument as an


accumulator.

reverse(X, Y) :- reverse(X, [], Y).


reverse([], YS, YS). reverse([X | XS], Accu, YS):- reverse(XS,
[X | Accu], YS).

Exercises

Write a predicate twice(In,Out) whose left argument is a list, and whose right argument is
a list consisting of every element in the left list written twice. For example, the query

twice([a,4,buggle],X).

should return

X = [a,a,4,4,buggle,buggle]).

And the query

twice([1,2,1,1],X).

should return

X = [1,1,2,2,1,1,1,1].

Some Built-in Predicates for List Manipulation

Prolog comes with a range of predefined predicates for manipulating lists. Some of the
most important ones are presented here. Note that they could all easily be implemented
by exploiting the head/tail-pattern.

length/2: The second argument is matched with the length of the list in the first argu- ment.
Example:

?- length([elephant, [], [1, 2, 3, 4]], Length). Length = 3 Yes

It is also possible to use length/2 with an uninstantiated first argument. This will generate a
list of free variables of the specified length:

?- length(List, 3). List = [_G248, _G251, _G254] Yes

The names of those variables may well be different every time you call this query, because
they are generated by Prolog during execution time.

member/2: The goal member(Elem, List) will succeed, if the term Elem can be matched
with one of the members of the list List. Example:

?- member(dog, [elephant, horse, donkey, dog, monkey]). Yes

append/3: Concatenate two lists. This built-in works exactly like the predicate concat_lists/3
presented in Section 2.2.

last/2: This predicate succeeds, if its second argument matches the last element of the list
given as the first argument of last/2.
reverse/2: This predicate can be used to reverse the order of elements in a list. The first
argument has to be a (fully instantiated) list and the second one will be matched with the
reversed list. Example:

?- reverse([1, 2, 3, 4, 5], X). X = [5, 4, 3, 2, 1] Yes

select/3: Given a list in the second argument and an element of that list in the first, this
predicate will match the third argument with the remainder of that list. Example:

?- select(bird, [mouse, bird, jellyfish, zebra], X). X = [mouse, jellyfish, zebra] Yes
Laboratory Secession 6: Input and Output in Prolog
write( ) : Writes a single term to the terminal. write(term) is true if term is a Prolog term.
For example: write(a), or write(‘How are you?’)
write_ln() Writes a term to the terminal followed by a new line.
tab(X) Writes an X number of spaces to the terminal.
read(X) Reads a term from the keyboard and instantiates variable X to the value of the
read term.
_ This term to be read has to be followed by a dot “.” and a white space character (such as
an enter or space).
_ For example:
hello :-
write(‘What is your name ?’),
read(X),
write(‘Hello’), tab(1), write(X).
You can write more than one horn clause in prolog file

sum :-
write('Enter the first Number ?'),
read(X),
write('Enter the Second Number'),
read(Y),
Z is X+Y,
write('The sum of the two number is'), write(Z).
subtract:-
write('Enter the first Number ?'),
read(X),
write('Enter the Second Number'),
read(Y),
Z is X-Y,
write('The first number minus the second number is'),
write(Z).
divide :-
write('Enter the first Number ?'),
read(X),
write('Enter the Second Number'),
read(Y),
Z is X/Y,
write('The fiirst number divided for second number is'),
write(Z).
product:-
write('Enter the first Number ?'),
read(X),
write('Enter the Second Number'),
read(Y),
Z is X*Y,
write('The product of the two number is'), write(Z).
modules:-
write('Enter the first Number ?'),
read(X),
write('Enter the Second Number'),
read(Y),
Z is mod(X,Y),
write('The modulo of first number to the second is'),
write(Z).
Laboratory Secession 8: Fact representation for AI Problems directed graph,
and defining successor function

The most concise and easy way to remember illustration of AI searches is using the road
map model that connects different locations shown in figure 6.1

figure 6.1 a simple road map model connects

As there are different types of searching techniques in AI, in this laboratory secession we will
see implementation of one type of blind-searching techniques called breadth first Search
for the road map model that has described in figure 6.1.
For the convenience of understanding the codes clearly, We alienated the facts that
describes the road maps facts from the actual depth first implementation. The fact
description implementation module created and saved by the name fact.pl. Later we will
call this module in the search algorithm bodies by its file name.
:- module(edges,[link/2]).
connect(a,b).
connect(a,d).
connect(a,s).
connect(b,c).
connect(b,e).
connect(d,e).
connect(d,s).
connect(e,f).
connect(f,g).
link(Node1,Node2) :- connect(Node1,Node2).
link(Node1,Node2) :- connect(Node2,Node1).

Exercises

1. Represent the following directed graph in prolog predicate form


Laboratory Secession 9: Implementation of Breadth First
and Depth first search goal finding
the important topics here in this laboratory secession is to show students the
implementation of breadth search algorithm.

As we have remember from our lecture discussion breadth-first search characterized by


expanding the shallowest node of the tree for finding the goal of the problem iteratively
until it comes with the solution if there is any.

Important functions and lists to implement this searching techniques described in the
following table .

1 Goal-test function That check whether the nodes to be expanded is a goal node or
not before given
2 Successor function A function that generates the child nodes from the current nodes
if the current node is not a goal node.
3 Merger function A function that checks weather the newly generated nodes are
not a member of explored nodes(a nodes that have been already
tested with goal test function and their child nodes are generated
usually kept as closed list) and merge with a node that has kept
in an open list that are waiting for further to be checked by goal-
test function and by successor function. Newopenlist={listof nodes
generated by successor function} n {nodes lists that is not in closed
list} plus previous open list compliment current node.
4 Open list Lists that contain the set of nodes that has been generated by
successor-function through each and further weighting for
checking by goal test function and successor-function. always
updated by merger-function. Note Remember Breadth first
search use FIFO data structure for accessing lists and
implemented in queue data structure.
5 Closed List Lists that contain a set of nodes that have already cheked with
goal-test function and were not a goal.

BreadthFirst(StartNode,GoalNode)
comment: Depth First Search with a List of Closed Nodes
RootNode ← StartNode
OpenList← [RootNode]
ClosedList← []
[H|T] ← OpenList while [H = GoalNode]
do
{
SuccList← successors of H ....................(1)
OpenList← (SuccList∩ClosedList copmliment) ..............(2)
ClosedList← [H|ClosedList]................... (3)
if OpenList = [] then return (failure)
[H|T] ← OpenListreturn (success)
}

The following figure shows the general algorithm for breadth first search

:-use_module(fact).
breadth_first(Start,Goal):-write('Open: '),
write([Start]), write(', Closed: '), write([]),
nl,
loop([Start],[],Goal).
loop([Goal|_],_,Goal):- write('The Goal is : '),
write(Goal).
loop([CurrNode|OtherNodes],ClosedList,Goal):-
successors(CurrNode,SuccNodes),
write('Node '), write(CurrNode),
write(' is being expanded.'),
findall(Node,(member(Node,SuccNodes),
not(member(Node,ClosedList))),Nodes),
append(OtherNodes,Nodes,NewOpenNodes),
write('Sucessor nodes: '),
write(SuccNodes),nl,
write('Open Nodes: '), write(NewOpenNodes),
write(', Closed Node : '),
write([CurrNode|ClosedList]),nl,
loop(NewOpenNodes,[CurrNode|ClosedList],Goal)
.
successors(Node,SuccNodes):-
findall(Successor,link(Node,Successor),SuccNodes)
.
Exercises

1. Implement depth first search and Iterative deepening search for similar problem of goal
finding.
Laboratory Secession 10: Implementation of Breadth First Search and Depth
first search with Path finder

1. Extend the above Implementation of BFS to be more interactive and finds the
paths instead of the nodes alone.

for this laboratory secession we implement the depth first search which finds paths for a
particular path finding problem. what makes different this implementation from previous
topic is that

 its first argument will take the list of open paths (and not that of open nodes). This
is the argument where we accumulate (maintain) the agenda.
• Into an additional (fourth) argument will the path from Start to Goal be copied as
soon as it appears at the head of the agenda. The search is then finished.
• The second and third arguments of will hold, as before, the list of closed nodes and
the goal node, respectively.

the following is the algorithm for path finding problem using depth first search
:- use_module(paths).

depth_first(Start,Goal,PathFound) :-
dfs_loop([[Start]],[],Goal,PathFoundRev),
reverse(PathFoundRev,PathFound).

dfs_loop([[Goal|PathTail]|_],_,Goal,[Goal|PathTail]).

dfs_loop([[CurrNode|T]|Others],ClosedList,Goal,PathFound) :-
successors(CurrNode,SuccNodes),

findall(Node,(member(Node,SuccNodes),
not(member(Node,ClosedList))),Nodes),

extend_path(Nodes,[CurrNode|T],Paths),
append(Others,Paths,NewOpenPaths),

dfs_loop(NewOpenPaths,[CurrNode|ClosedList],Goal,PathFound).

successors(Node,SuccNodes) :-
findall(Successor,link(Node,Successor),SuccNodes).

extend_path([],_,[]). % clause 1

extend_path([Node|Nodes],Path,[[Node|Path]|Extended]) :- %
clause 2

extend_path(Nodes,Path,Extended). %

Exercises

1. Implement the path finder solution for breadth and iterative deepening search

You might also like