Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Adrian Craciun
November 22, 2013
1
Contents
I An Introduction to Prolog 5
1 Introduction 5
1.1 Traditional programming paradigms . . . . . . . . . . . . . . . . 5
1.2 Logic programming . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5 Recursion 27
5.1 Introducing Recursion . . . . . . . . . . . . . . . . . . . . . . . . 27
5.2 Recursive Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.3 Recursive Comparison . . . . . . . . . . . . . . . . . . . . . . . . 29
5.4 Joining Structures . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.5 Accumulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.6 Difference Structures . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.7 Further Reading and Exercises . . . . . . . . . . . . . . . . . . . 36
2
7 Efficient Prolog 47
7.1 Declarative vs. Procedural Thinking . . . . . . . . . . . . . . . . 47
7.2 Narrow the search . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.3 Let Unification do the Work . . . . . . . . . . . . . . . . . . . . . 48
7.4 Understand Tokenization . . . . . . . . . . . . . . . . . . . . . . 49
7.5 Tail recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
7.6 Let Indexing Help . . . . . . . . . . . . . . . . . . . . . . . . . . 51
7.7 How to Document Prolog Code . . . . . . . . . . . . . . . . . . . 52
7.8 Reading and Further Exercises . . . . . . . . . . . . . . . . . . . 52
11 Resolution 69
11.1 Ground Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . 69
11.2 Substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
11.3 Unification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
11.4 Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
11.5 Reading and Further Exercises . . . . . . . . . . . . . . . . . . . 75
12 Logic Programming 76
12.1 Formulas as programs . . . . . . . . . . . . . . . . . . . . . . . . 76
12.2 Horn Clauses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.3 SLD Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
12.4 Reading and Further Exercises . . . . . . . . . . . . . . . . . . . 82
3
Overview of the Lecture
Contents of this lecture
4
Part I
An Introduction to Prolog
1 Introduction
1.1 Traditional programming paradigms
Recalling the Von Neumann machine
5
1.2 Logic programming
Logic programming: some history
Alan Robinson (1965): the resolution method for first order logic (i.e.
machine reasoning in first order logic).
Robert Kowalski (1971): procedural interpretation of Horn clauses, i.e.
computation in logic.
Symbolic computation:
relational databases,
mathematical logic,
abstract problem solving,
natural language understanding,
symbolic equation solving,
design automation,
artificial intelligence,
biochemical structure analysis, etc.
Industrial applications:
aviation:
* SCORE - a longterm aiport capacity management system for
coordinated airports (20% of air traffic worldwide, according to
www.pdc-aviation.com)
6
* FleetWatch - operational control, used by 21 international air
companies.
personnel planning: StaffPlan (airports in Barcelona, Madrid; Hov-
edstaden region in Denmark).
information management for disasters: ARGOS - crisis management
in CBRN (chemical, biological, radiological and nuclear) incidents
used by Australia, Brasil, Canada, Ireland, Denmark, Sweden, Nor-
way, Poland, Estonia, Lithuania and Montenegro.
Programming in Prolog:
Examples:
7
2.2 Facts
Stating a fact in Prolog:
l i k e s ( johnny , mary ) .
Prolog searches in the knowledge base for facts that match the question:
Prolog answers true if :
8
Variables
Instead of:
? l i k e s ( john , mary ) .
? l i k e s ( john , a p p l e s ) .
? l i k e s ( john , candy ) .
ask something like What does John like? (i.e. give everything that John
likes).
Variables stand for objects to be determined by Prolog.
To the query
? l i k e s ( john , X ) .
Prolog searches the knowledge base for a fact that matches the query,
9
if the user presses ; then Enter, Prolog looks for a new match, from
the previously marked place, and with the variable(s) in the query unin-
stantiated.
In the example above, two more ; Enter will determine Prolog to an-
swer:
X = mary .
false
When no (more) matching facts are found in the knowledge base, Prolog
answers false .
the query reads does john like mary and does mary like john?
Prolog will answer false : it searches for each goal in turn (all goals
have to be satisfied, if not, it will fail, i.e. answer false ).
Prolog: try to satisfy the first goal (if it is satisfied put a place-
marker), then try to satisfy the second goal (if yes, put a place-
marker).
If at any point there is a failure, backtrack to the last placemarker
and try alternatives.
10
Figure 1: Success for the first goal.
11
2.4 Rules
John likes all people can be represented as:
l i k e s ( john , alfred ).
l i k e s ( john , bertrand ) .
l i k e s ( john , charles ).
l i k e s ( john , david ) .
...
Enter rules: John likes any object, but only that which is a person is a
rule about what (who) John likes.
Rules express that a fact depends on other facts.
Rules as definitions
Example:
Example:
Rules are general statements about objects and their relationships (in
general variables occur in rules, but not always).
12
Rules in Prolog
Attention! The scope of the variables that occur in a rule is the rule itself
(rules do not share variables).
Example (royals)
Knowledge base:
male ( a l b e r t ) .
male ( edward ) .
female ( a l i c e ) .
female ( v i c t o r i a ) .
parents ( alice , albert , victoria ).
p a r e n t s ( edward , a l b e r t , victoria ).
s i s t e r o f (X, Y):
f e m a l e (X) ,
p a r e n t s (X, M, F ) .
p a r e n t s (Y, M, F ) .
Goals:
? s i s t e r o f ( a l i c e , edward ) .
? s i s t e r o f ( a l i c e , X ) .
Exercise (thieves)
/ * 2 * / l i k e s ( mary , f o o d ) .
/ * 3 * / l i k e s ( mary , wine ) .
/ * 4 * / l i k e s ( john , X): l i k e s (X, wine ) .
/ * 5 * / m a y s t e a l (X, Y) :
t h i e f (X) , l i k e s (X, Y ) .
13
Explain how the query
? m a y s t e a l ( john , X ) .
is executed by Prolog.
2.5 Summary
In this introduction to Prolog, the following were discussed:
asserting facts about objects,
asking questions about facts,
using variables, scopes of variables,
conjunctions,
an introduction to backtracking (in examples).
14
3 Syntax and Data Structures
3.1 Terms
Prolog programs are built from terms (written as strings of characters).
constants,
variables,
structures.
3.1.1 Constants
Constants are simple (basic) terms.
atoms,
numbers: integers, rationals (with special libraries), reals (floating
point representation).
Examples of atoms
atoms:
likes ,
a (lowercase letters),
=,
>,
Void (anything between single quotes),
george smith (constants may contain underscore),
not atoms:
15
3.1.2 Variables
Variables are simple (basic) terms,
3.1.3 Structures
Structure are compound terms, single objects consisting of collections of
objects (terms),
Characters in Prolog
Characters:
A-Z
a-z
0-9
+-*/\ <>: .
? @#$&
Characters are ASCII (printing) characters with codes greater than 32.
16
3.2 Operators
Arithmetic operators
Arithmetic operators:
+,
,
*,
/,
+(x, (y, z)) is equivalent with x + (y z)
Operators do not cause evaluation in Prolog.
Example: 3+4 (structure) does not have the same meaning with 7 (term).
X is 3+4 causes evaluation ( is represents the evaluator in Prolog).
The result of the evaluation is that X is assigned the value 7.
17
3.3 Unification
The unification predicate =
Prolog will try to match(unify) X and Y, and will answer true if successful.
In general, we try to unify 2 terms (which can be any of constants, vari-
ables, structures):
?T1 = T2 .
Occurs check
Answer of Prolog:
X = f (**).
X = f (X ) .
18
In fact this is due to the fact that according to the unification procedure,
the result is X = f(X) = f(f(X)) = ...= f( f (...( f (X )...))) - an infinite loop
would be generated.
X = Y,
X \= Y,
X < Y,
X > Y,
X =< Y,
X >= Y,
Note that variables have to be instantiated in most cases (with the excep-
tion of the first two above, where unification is performed in the case of
uninstantiation).
19
The Prolog evaluator is has the form:
X i s Expr .
r e i g n s ( rhondri , 844 , 8 7 8 ) .
r e i g n s ( anarawd , 8 7 8 , 9 1 6 ) .
r e i g n s ( hywel dda , 9 1 6 , 9 5 0 ) .
r e i g n s ( lago ap idwal , 950 , 9 7 9 ) .
r e i g n s ( hywel ap ieuaf , 979 , 9 8 5 ) .
r e i g n s ( cadwallon , 9 8 5 , 9 8 6 ) .
r e i g n s ( maredudd , 9 8 6 , 9 9 9 ) .
p r i n c e (X, Y):
r e i g n s (X, A, B) ,
Y >= A,
Y =< B .
? p r i n c e ( cadwallon , 9 8 6 ) .
true
? p r i n c e (X, 9 7 9 ) .
X = lago ap idwal ;
X = hywel ap ieuaf
pop ( p l a c e 1 , 203).
pop ( p l a c e 2 , 548).
pop ( p l a c e 3 , 800).
pop ( p l a c e 4 , 108).
d e n s i t y (X, Y):
pop (X, P) ,
a r e a (X, A) ,
Y i s P/A.
? d e n s i t y ( p l a c e 3 , X ) .
X = 200
true
20
3.5 Summary
The notions covered in this section:
Prolog syntax: terms (constants, variables, structures).
Arithmetic in Prolog.
Unification procedure.
Subtle point: occurs check.
parent
Other examples:
a + b* c
a *
b c
21
book
herman melville
sentence
X verb noun
Y Z
f (X, g (X, a ) ) .
4 X a
In the above, the variable X is shared between nodes in the tree represen-
tation.
4.2 Lists
Introducing lists
22
Elements of lists are terms (any type, including other lists).
List representations
.( a, [ ]) is represented as
or []
a [] a
tree vine
representation representation
.( a, .( b, [ ])) is
[]
a b
23
[]
[] a X
[a] ,
[a, b] ,
[[ a ], a, X].
List manipulation
Lists are naturally split between the head and the tail.
[ X, Y, Z ] = [ john , l i k e s , f i s h ]
X = john
Y = likes
Z = fish
24
[ c a t ] = [X | Y]
X = cat
Y = [ ]
[ X, Y | Z ] = [ mary , l i k e s , wine ]
X = mary
Y = likes
Z = [ wine ]
[ [ the , Y] | Z ] = [ [ X, h a r e ] , [ i s , h e r e ] ]
X = the
Y = hare
Z = [ [ is , here ] ]
[ g o l d e n | T ] = [ golden , n o r f o l k ]
T = [ norfolk ]
[ v a l e , h o r s e ] = [ h o r s e , X]
false
[ w h i t e |Q] = [ P | h o r s e ]
P = white
Q = horse
Strings
In Prolog, strings are written inside double quotation marks.
Example: a string.
Internally, a string is a list of the corresponding ASCII codes for the
characters in the string.
? X = a s t r i n g .
X = [ 9 7 , 32 , 115 , 116 , 114 , 105 , 110 , 1 0 3 ] .
Summary
Items of interest:
the anatomy of a list in Prolog .( h, t)
graphic representations of lists: tree representation, vine repre-
sentation,
syntactic sugar for lists [...] ,
list manipulation: head-tail notation [H|T],
strings as lists,
unifying lists.
25
Reading
Read the corresponding Chapter 3, Section 3.2, from [Clocksin and Mellish, 2003].
26
5 Recursion
5.1 Introducing Recursion
Induction/Recursion
Inductive domain:
A domain composed of objects constructed in a manageable way,
i.e.:
there are some simplest(atomic) objects, that cannot be decom-
posed,
there are complex objects that can be decomposed into finitely
many simpler objects,
and this decomposition process can be performed finitely many times
before one reaches the simplest objects.
In such domains, one can use induction as an inference rule.
Recursion is the dual of induction, i.e.:
recursion describes computation in inductive domains,
recursive procedures (functions, predicates) call themselves,
but the recursive call has to be done on a simpler object.
As a result, a recursive procedure will have to describe the behaviour
for:
(a) The simplest objects, and/or the objects/situations for which the
computation stops, i.e. the boundary conditions, and
(b) the general case, which describes the recursive call.
Example: member
% The boundary c o n d i t i o n .
member (X, [X| ] ) .
% The r e c u r s i v e c o n d i t i o n .
member (X, [ |Y] ) :
member (X, Y ) .
27
The boundary condition is, in this case, the condition for which the com-
putation stops (not necessarily for the simplest list, which is [ ] ).
For [ ] the predicate is false, therefore it will be omitted.
Note that the recursive call is on a smaller list (second argument). The ele-
ments in the recursive call are getting smaller in such a way that eventually
the computation will succeed, or reach the empty list and fail. predicate
for the empty list (where it fails).
In this case,
?p e r s o n (X ) .
will loop (no chance to backtrack). Prolog tries to satisfy the rule and this
leads to the loop.
The order in which the rules and facts are given matters. In general, place
facts before rules.
28
Mapping procedure:
1. accept a sentence,
2. change you to i,
3. change are to am not,
4. change french to german,
5. change do to no,
6. leave everything else unchanged.
The program:
change ( you , i ) .
change ( are , [ am, not ] ) .
change ( f r e n c h , german ) .
change ( do , no ) .
change (X, X ) .
alter ( [ ] , [ ] ) .
a l t e r ( [ H| T ] , [X|Y] ) :
change (H, X) ,
a l t e r (T, Y ) .
The program:
29
a l e s s (X, Y):
name(X, L ) , name(Y, M) , a l e s s x (L ,M) .
alessx ( [ ] , [ | ] ) .
a l e s s x ( [ X| ] , [Y| ] ) : X < Y.
a l e s s x ( [ H|X] , [H|Y] ) : a l e s s (X, Y ) .
This illustrate the use of appendLists/3 for testing that a list is the result
of appending two other lists.
Other uses of appendLists/3:
- Total list computation:
? a p p e n d L i s t s ( [ a , b , c ] , [ 3 , 2 , 1 ] , X ) .
- Isolate:
? a p p e n d L i s t s (X, [ 2 , 1 ] , [ a , b , c , 2 , 1 ] ) .
- Split:
? a p p e n d L i s t s (X, Y, [ a , b , c , 3 , 2 , 1 ] ) .
% t h e boundary c o n d i t i o n
appendLists ( [ ] , L, L ) .
% recursion
a p p e n d L i s t s ( [ X| L1 ] , L2 , [X| L3 ] ) :
a p p e n d L i s t s ( L1 , L2 , L3 ) .
5.5 Accumulators
Summary
The recursive nature of structures (and in particular lists) gives a way to
traverse them by recursive decomposition.
When the boundary is reached, the decomposition stops and the result is
composed in a reverse of the decomposition process.
This process can be made more efficient: introduce an extra variable in
which the result so far is accumulated.
When the boundary is reached this extra variable already contains the
result, no need to go back and compose the final result.
This variable is called an accumulator.
30
Example: List Length
Without accumulator:
% length of a l i s t
% boundary c o n d i t i o n
listlen ([] , 0).
% recursion
l i s t l e n ( [ H| T ] , N):
l i s t l e n (T, N1 ) ,
N i s N1+1.
With accumulator:
% l e n g t h of a l i s t with accumulators
% c a l l of the accumulator :
l i s t l e n 1 (L , N):
l e n a c c (L , 0 , N ) .
% boundary c o n d i t i o n f o r a c c u m u l a t o r
l e n a c c ( [ ] , A, A ) .
% recursion f o r the accumulator
l e n a c c ( [ H| T ] , A, N):
A1 i s A + 1 ,
l e n a c c (T, A1 , N ) .
Example: Reverse
Without accumulators:
%% r e v e r s e
% boundary c o n d i t i o n
reverse1 ( [ ] , [ ] ) .
% recursion
r e v e r s e 1 ( [ X|TX] , L):
r e v e r s e 1 (TX, NL) ,
a p p e n d L i s t s (NL, [X] , L ) .
With accumulators:
31
%% r e v e r s e w i t h a c c u m u l a t o r s
% c a l l the accumulator
r e v e r s e 2 (L , R):
r e v e r s e A c c (L , [ ] , R ) .
% boundary c o n d i t i o n f o r t h e a c c u m u l a t o r
r e v e r s e A c c ( [ ] , R, R ) .
% recursion f o r the accumulator
r e v e r s e A c c ( [ H| T ] , A, R):
r e v e r s e A c c (T, [H|A] , R ) .
a b c
Consider
? X = [ a , b , c | L ] , L = [ d , e , f , g ] .
X = [a, b, c , d, e , f , g] ,
L = [d, e , f , g ].
32
the hole was filled partially.
i.e. we have an open list (OpenList), with a hole (Hole) is filled with a list
(L):
? X = [ a , b , c , d | Hole ] ,
d i f f a p p e n d 1 (X, Hole , [ d , e ] ) .
X = [a, b, c , d, d, e] ,
Hole = [ d , e ] .
Note that when we work with open lists we need to have information (i.e.
a variable) both for the open list and its hole.
A list can be represented as the the difference between an open list and
its hole.
Notation: OpenListHole
its usage:
? X = [ a , b , c , d | Hole ] Hole ,
d i f f a p p e n d 2 (X , [ d , e ] ) .
X = [ a , b , c , d , d , e ] [ d , e ] ,
Hole = [ d , e ] .
Perhaps the fact that the answer is given as a difference list is not conve-
nient.
A new version that returns a(n open) list (with the hole filled) as the
answer:
d i f f a p p e n d 3 ( OpenListHole , L , OpenList ):
Hole = L .
its usage:
33
? X = [ a , b , c , d | Hole ] Hole ,
d i f f a p p e n d 3 (X , [ d , e ] , Ans ) .
X = [ a , b , c , d , d , e ] [ d , e ] ,
Hole = [ d , e ] ,
Ans = [ a , b , c , d , d , e ] .
or, if we want the result to be just the list, fill the hole with the empty
list:
? X=[a , b , c | Ho]Ho , d i f f a p p e n d 6 (X, [ d , e , f | Hole2 ] Hole2 , Ans [ ] ) .
X = [ a , b , c , d , e , f ] [ d , e , f ] ,
Ho = [ d , e , f ] ,
Hole2 = [ ] ,
Ans = [ a , b , c , d , e , f ] .
its usage:
? X=[a , b , c |H]H,
a p p e n d d i f f (X, [ d , e , f | Hole2 ] Hole2 , Ans [ ] ) .
X = [ a , b , c , d , e , f ] [ d , e , f ] ,
H = [d, e , f ] ,
Hole2 = [ ] ,
Ans = [ a , b , c , d , e , f ] .
34
Example: adding to back
Let us consider the program for adding one element to the back of a list:
% boundary c o n d i t i o n
a d d t o b a c k ( El , [ ] , [ El ] ) .
% recursion
a d d t o b a c k ( El , [ Head | T a i l ] , [ Head | NewTail ):
a d d t o b a c k ( El , T a i l , NewTail ) .
The program above is quite inefficient, at least compared with the similar
operation of adding an element at the beginning of a list (linear in the
length of the list one goes through the whole list to find its end versus
constant one step).
But difference lists can help - the hole is at the end of the list:
a d d t o b a c k d ( El , OpenListHole , Ans):
a p p e n d d i f f ( OpenListHole , [ El | ElHole ] ElHole , Ans [ ] ) .
Consider:
? a p p e n d d i f f ( [ a , b ] [ b ] , [ c , d ] [ d ] , L ) .
false .
? empty ( [ a |Y]Y ) .
Y = [a|**].
The query succeeds, but the result is not the one expected.
This can be fixed:
a p p e n d d i f f f i x (XY, YZ , XZ):
s u f f i x (Y, X) ,
s u f f i x (Z , Y) .
35
5.7 Further Reading and Exercises
Read Chapter 3, Chapter 7, Sections 7.5, 7.6, 7.7 of [Clocksin and Mellish, 2003].
36
6 Backtracking and the Cut (!)
6.1 Backtracking behaviour
Undesired backtracking behavior
Example:
f a t h e r ( mary , g e o r g e ) .
f a t h e r ( john , g e o r g e ) .
f a t h e r ( sue , h a r r y ) .
f a t h e r ( g e o r g e , edward ) .
Once we find that george is a father, we dont expect to get the answer
again.
37
? i s n a t (X ) .
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5 ;
X = 6 ;
...
Consider:
member (X, [X| ] ) .
member (X, [ |Y] ) :
member (X, Y ) .
the query:
? member ( a , [ a , b , a , a , a , v , d , e , e , g , a ] ) .
true ;
true ;
true ;
true ;
true ;
false .
Backtracking confirms the answer several times. But we only need it once!
The cut predicate !/0 tells Prolog to discard certain choices of backtrack-
ing.
As an effect,
38
Example:library
Reference library:
f a c i l i t y ( Pers , Fac ):
b o o k o v e r d u e ( Pers , Book ) ,
b a s i c f a c i l i t y ( Fac ) .
a d d i t i o n a l f a c i l i t y ( borrowing ) .
additional facility ( inter library exchange ).
g e n e r a l f a c i l i t y (X):
b a s i c f a c i l i t y (X ) .
g e n e r a l f a c i l i t y (X):
a d d i t i o n a l f a c i l i t y (X ) .
c l i e n t ( C . Wetzer ) .
c l i e n t ( A. J o n e s ) .
b o o k o v e r d u e ( C . Wetzer , book00101 ) .
b o o k o v e r d u e ( C . Wetzer , book00111 ) .
b o o k o v e r d u e ( A. J o n e s , book010011 ) .
? c l i e n t (X) , f a c i l i t y (X, Y ) .
X = C . Wetzer ,
Y = references ;
X = C . Wetzer ,
Y = enquiries ;
X = A. J o n e s ,
Y = references ;
X = A. J o n e s ,
Y = enquiries .
f a c i l i t y ( Pers , Fac ):
b o o k o v e r d u e ( Pers , Book ) ,
!,
b a s i c f a c i l i t y ( Fac ) .
39
basic facility ( references ).
basic facility ( enquiries ).
a d d i t i o n a l f a c i l i t y ( borrowing ) .
additional facility ( inter library exchange ).
g e n e r a l f a c i l i t y (X):
b a s i c f a c i l i t y (X ) .
g e n e r a l f a c i l i t y (X):
a d d i t i o n a l f a c i l i t y (X ) .
? - client(X) , facility(X, Y).
X=C.Wetzer
X X
the system becomes commited to all the choices made since the parent
(here this is facility ) was invoked,
all other alternatives are discarded (e.g. the branch indicated by
above),
40
an attempt to satisfy any goal between the parent and the cut goal
will fail,
if the user asks for a different solution, Prolog goes to the backtrack
point above the parent goal (if any). In the example above the first
goal is ( client (X)) is the backtrack point above the goal.
Situation:
sum to ( 1 , 1 ) .
sum to (N, Res ):
N1 i s N1 ,
sum to (N1 , Res1 ) ,
Res i s Res1 + N.
41
The system is commited to the boundary condition, it will not backtrack
for others anymore:
? csum to ( 5 , X ) .
X = 15.
However:
? csum to ( 3 , Res ) .
ERROR: Out o f l o c a l s t a c k
Placing the condition N =< 1 in the boundary condition fixes the problem:
ssum to (N, 1):
N =< 1 , ! .
42
The cut-fail combination
Example:
a v e r a g e t a x p a y e r (X):
f o r e i g n e r (X) , ! , f a i l .
a v e r a g e t a x p a y e r (X):
s a t i s f i e s g e n e r a l c r i t e r i o n (X ) .
s a t i s f i e s g e n e r a l c r i t e r i o n (X):
s p o u s e (X, Y) ,
g r o s s i n c o m e (Y, I n c ) ,
Inc > 3000 ,
! , fail .
satisfies g e n e r a l c r i t e r i o n (X):
gross i n c o m e (X, I n c ) ,
Inc < 3000 ,
Inc > 2000.
Gross income:
43
g r o s s i n c o m e (X, Y):
r e c e i v e s p e n s i o n (X, P) ,
P < 500 ,
! , fail .
g r o s s i n c o m e (X, Y):
g r o s s s a l a r y (X, Z ) ,
i n v e s t m e n t i n c o m e (X, W) ,
Y i s Z + W.
Note though that Prolog will take issue with you trying to redefine essen-
tial predicates.
This replacement does not affect the efficiency in the cut-fail situations.
Tic-tac-toe.
44
Problems with the cut
? cappend ( [ 1 , 2 , 3 ] , [ a , b , c ] , X ) .
X = [1 , 2 , 3 , a , b, c ] .
? cappend ( [ 1 , 2 , 3 ] , X, [ 1 , 2 , 3 , a , b , c ] ) .
X = [a, b, c ].
? cappend (X, Y, [ 1 , 2 , 3 , a , b , c ] ) .
X = [] ,
Y = [1 , 2 , 3 , a , b, c ] .
The variant of append with a cut works as expected for the first two
queries above. However, for the third, it only offers one solution (all the
others are cut!)
Consider:
n u m b e r o f p a r e n t s ( adam , 0 ) : ! .
n u m b e r o f p a r e n t s ( eve , 0 ) : ! .
n u m b e r o f p a r e n t s (X, 2 ) .
? n u m b e r o f p a r e n t s ( eve , X ) .
X = 0.
? n u m b e r o f p a r e n t s ( john , X ) .
X = 2.
? n u m b e r o f p a r e n t s ( eve , 2 ) .
true .
The third query gives an unexpected answer. This is due to the fact that
the particular instantiation of the arguments does not match the special
condition where the cut was used.
In fact, here, the pattern that distinguishes between the special condition
and the general case is formed by both arguments together.
45
n u m b e r o f p a r e n t s 1 ( adam , N) : ! , N = 0 .
n u m b e r o f p a r e n t s 1 ( eve , N) : ! , N = 0 .
n u m b e r o f p a r e n t s 1 (X, 2 ) .
n u m b e r o f p a r e n t s 2 ( adam , 0 ) : ! .
n u m b e r o f p a r e n t s 2 ( eve , 0 ) : ! .
n u m b e r o f p a r e n t s 2 (X, 2):
X \ = adam , X, \= eve .
The cut is a powerful construct and should be used with great care.
The advantages of using the cut can be major, but so are the dangers.
Items of interest:
what is the effect of the cut predicate (!), guarded gate metaphor,
common uses of the cut: 1. confirming the use of a rule, 2. cut-fail
combination, 3. terminate a generate and test,
cut elimination (can it be done, does it cost in terms of computational
complexity?)
problems with cut (green cuts/red cuts).
46
7 Efficient Prolog
7.1 Declarative vs. Procedural Thinking
The procedural aspect of Prolog
can be read
declaratively, as the equation x = y + z,
procedurally: load y, load z, store x.
However, ignoring its procedural meaning, this can lead to infinite loops
(when B and C are both unknown).
47
7.2 Narrow the search
The task of a Prolog programmer is to build a model of the problem and
to represent it in Prolog.
Knowledge about this model can improve performance significantly.
?horse(X), gray(X). will find the answer much faster than ?gray(X), horse(X).
in a model with 1000 gray objects and 10 horses.
Narrowing the search can be even more subtle:
s e t e q u i v a l e n t ( L1 , L2):
permute ( L1 , L2 ) .
i.e. to find whether two lists are set-equivalent it is enough to see whether
they are permutations of eachother. But for N element lists, there are N !
permutations (e.g. for 20 elements, 2.4 1018 possible permutations).
i.e. two lists are set equivalent if their sorted versions are the same. And
sorting can be done in N logN steps (e.g. approx 86 steps for 20 element
lists).
h a s 3 e l e m e n t s (X):
length (X, N) ,
N = 3.
has 3 elements ( [ , , ]).
Also consider the predicate for swapping the first two elements from a list:
s w a p f i r s t 2 ( [ A, B | Rest ] , [ B, A| Rest ] ) .
48
7.4 Understand Tokenization
Atoms are represented in Prolog in a symbol table where each atom ap-
pears once - a process called tokenization.
Atoms in a program are replaced by their address in the symbol table.
Because of this:
f ( What an a w f u l l y l o n g atom t h i s a p p e a r s t o be ,
What an a w f u l l y l o n g atom t h i s a p p e a r s t o be ,
What an a w f u l l y l o n g atom t h i s a p p e a r s t o be ) .
the continuation, i.e. what has to be done after returning with success
from b (i.e. c),
the backtrack point, i.e. where can an alternative be tried in case of
returning with failure from b (i.e. d).
Tail recursion
They are much more effficient than the non-tail recursive variants.
49
The following is tail recursive:
t e s t 1 (N): write (N) , nl , NewN i s N+1 , t e s t 1 (NewN ) .
In the above write writes (prints) the argument on the console and suc-
ceeds, nl moves on a new line and succeeds. The predicate will print
natural numbers on the console until the resources run out (memory or
number representations limit).
The following is tail recursive (the alternative clause comes before the
recursive clause so there is no backtracking point for the recursive call):
t e s t 3 a (N): N<0.
t e s t 3 a (N): write (N) , nl , NewN i s N+1 , t e s t 3 a (NewN ) .
The following is not tail recursive (it has alternatives for predicates in
the recursive clause preceding the recursive call, so backtracking may be
necessary):
t e s t 4 (N): write (N) , nl , m(N, NewN) , t e s t 4 (NewN ) .
50
Note that tail recursion can be indirect. The following is tail recursive:
t e s t 7 (N): write (N) , nl , t e s t 7 a (N ) .
t e s t 7 a (N): NewN i s N+1 , t e s t 7 (NewN ) .
In the above we have mutual recursion, but note that test7a is just used
to rename part of the test7 predicate.
d( e ) .
d( f ) .
These indices will be stored as a hash table or something similar for fast
access.
Therefore, Prolog will find d(f) directly.
Using indexing can make predicates be tail recursive when they would not
be:
t e s t 8 (0): write ( S t i l l g o i n g ) , nl , t e s t 8 ( 0 ) .
t e s t 8 ( 1).
51
7.7 How to Document Prolog Code
Consider some built-in predicates in Prolog, as presented in the help sec-
tion of the program:
append ( ? L i s t 1 , ? L i s t 2 , ? L i s t 3 )
Succeeds when List3 unifies with the concatenation of List1 and List2. The predicate
can be used with any instantiation pattern (even three variables).
Number i s +Expr [ ISO ]
True if Number has successfully been unified with the number Expr evaluates to. If
Expr evaluates to a float that can be represented using an integer (i.e, the value is
integer and within the range that can be described by Prologs integer representation),
Expr is unified with the integer value.
52
8 I/O with Prolog
There are two styles of I/O in Prolog:
Edinburg style I/O is the legacy style, still supported by Prolog im-
plementations. It is relatively simple to use but has some limitations.
ISO I/O is the standard style, supported by all Prolog implementa-
tions.
There are some overlaps between the two styles.
The built-in predicate write takes any Prolog term and displays it on the
screen.
The predicate nl moves the cursor at a new line.
Note that quoted atoms are displayed without quotes. The variant writeq
of write will also display the quotes.
? write (X ) .
G243
true .
? write ( some s t r i n g ) .
[ 1 1 5 , 111 , 109 , 101 , 32 , 115 , 116 , 114 , 105 , 110 , 103]
true .
Reading terms
The predicate read accepts any Prolog term from the keyboard (typed in
Prolog syntax, followed by the period).
? read (X ) .
| : hello .
X = hello .
? read (X ) .
53
| : hello there .
X = hello there .
? read (X ) .
| : hello there .
ERROR: Stream u s e r i n p u t : 0 : 3 7
Syntax e r r o r : Operator e x p e c t e d
? read ( h e l l o ) .
| : hello .
true .
? read ( h e l l o ) .
| : bye .
false .
? read (X ) .
| : mother (Y, ada ) .
X = mother ( G288 , ada ) .
The read predicate succeeds if its argument can be unified with the term
given by the user (if this is a term). The examples above illustrate several
possible uses and situations.
File handling
The predicate see takes a file as argument, the effect is to open the file for
reading such that Prolog gets input from that file rather than the console.
The predicate seen closes all open files, input now comes again from the
console.
? see ( m y f i l e . t x t ) ,
read (X) ,
read (Y) ,
read ( Z ) ,
seen .
When a file is opened, Prolog will keep track of the position of the cursor
in that file.
54
see ( c c c c ) ,
read (X3 ) ,
seen .
The predicate tell opens a file for writing and switches the output to it.
The predicate told closes all files opened for writing and returns the output
to being the console.
? tell ( myfile . txt ) ,
write ( H e l l o t h e r e ) ,
nl ,
told .
The predicate put writes one character (integer representing the ASCII
code corresponding to the character).
? put ( 4 2 ) .
*
true .
The predicate get reads one character from the default input (console).
? g e t (X ) .
| %
X = 37.
For exact details of the Edinburgh style I/O predicates in SWI Prolog, con-
sult [Wielemaker, 2008] (also available in SWI Prolog by calling ? help.).
55
8.2 ISO I/O
Streams
ISO standard I/O in Prolog considers the notion of a stream (open files
or file-like objects).
ISO I/O predicates are provided for:
Open and close streams in different modes.
Inspecting the status of a stream, as well as other information.
Reading/writing is done in streams.
There are two special streams that are always open: user input and user output.
Opening streams
The predicate open(Filename, Mode, Stream, Options) opens a stream, where:
Filename indicates the file name (implementation, OS dependent),
Mode is one of read, write, append,
Stream is a handle for the file,
Options is a (possibly empty) list of options. Options include:
* type(text) (default) or type(binary),
* reposition (true) or reposition ( false ) (the default) indicating
whether it is possible to skip back or forward to specified po-
sitions,
* alias (Atom) a name (atom) for the stream,
* action for reading past the end of the line: eof action (error) -
raise an error condition, oef action (eof code) - return an error
code, eof action ( reset ) - to examine the file again (in case it was
updated e.g. by another concurrent process).
Example:
t e s t :
open ( f i l e . t x t , read , MyStream , [ type ( t e x t ) ] ) ,
r e a d t e r m ( MyStream , Term , [ quoted ( true ) ] ) ,
c l o s e ( MyStream ) , write ( Term ) .
Closing streams
The predicate close(Stream, Options) closes Stream with Options.
close(Stream) is the version without options.
Options include force ( false ) (default) and force (true) - even if there is an
error (e.g. the file was on a removable storage device which was removed),
the file is considered closed, without raising an error.
56
Stream properties
The predicate stream property(Stream, Property) can be used to get prop-
erties like:
file name (...) ,
mode(M),
alias (A),
etc, consult the documentation [Wielemaker, 2008] for the rest of the
options.
Example:
? s t r e a m p r o p e r t y ( u s e r i n p u t , mode (What ) ) .
What = read .
Reading terms
Predicates for reading terms:
read term(Stream, Term, Options),
read term(Term, Options), using the current input stream,
read(Stream, Term) like the above, without the options,
read(Term) like the above, from current input.
Writing terms
Predicates for writing terms include:
write term(Stream, Term, Options),
write term(Term, Options),
write(Stream, Term),
write(Term),
57
Other I/O predicates
Other predicates:
current input, current output, set input , set output, flush output, at the end of stream,
nl, etc.
Items of interest:
However, there are situations where having a different position may make
the programs easier to understand:
X is father of Y
In Prolog, one can define new operators like the one above.
58
the associativity: e.g. is 8/2/2 (8/2)/2 or is it 8/(2/2)?
Note that logic predicates (i.e. those expressions that evaluate to
true or false are not associative in general). Consider:
3 = 4 = 3, and suppose it were left associative,
then (3 = 4) = 3 evaluates to false = 3, which changes the
type of the arguments.
Specifier Meaning
fx Prefix, not associative.
fy Prefix, right-associative.
xf Postfix, not associative.
yf Postfix, left-associative.
xfx Infix, not associative (like =).
xfy Infix, right associative (like comma in compound goals).
yfx Infix, left associative (like +).
Example
% n o t e t h e s y n t a x o f d e c l a r i n g t h e new o p e r a t o r :
: op ( 1 0 0 , xfx , i s f a t h e r o f ) .
m i c h a e l i s f a t h e r o f kathy .
X i s f a t h e r o f Y : male (X) , p a r e n t (X, Y ) .
? X i s f a t h e r o f kathy .
X = michael .
59
9.1 Reading and Further Exercises
Read: Section 6.6, of [Covington et al., 1997].
Items of interest:
Defining operators.
60
Part II
The Theoretical Basis of Logic
Programming
10 Logical Background
10.1 Predicate logic
We review here (first order) predicate logic:
the syntax,
the semantics,
illustrate some difficulties of the semantic evaluation of truth in first
order logic,
review some results that deal with this difficulty.
The vocabulary of the language contains the symbols from which expres-
sions of the language are built:
Reserved symbols:
* ( ),
* , , , , ,
* , .
The set of variables V (countable set).
The set of language symbols L:
* F - function symbols (each with their own arity),
* P - predicate symbols (with arity),
* C - constant symbols.
Terms:
* variables v V are terms,
* constants c C are terms,
* if f/n F and t1 , . . . , tn are terms, then so is f (t1 , . . . , tn ).
Formulae:
61
* if p/n P and t1 , . . . , tn are terms, then p(t1 , . . . , tn ) is an atomic
formula,
* if F, G are formulae, then F , F G, F G, F G, F G
are (compound) formulae,
* if x V and F is a formula then xF , xF are (quantified)
formulae (the universally and existentially quantified formulae,
respectively).
a domain of objects,
relations between the objects (or properties of the objects),
processes or functions that produce new objects from other ob-
jects.
To find (compute) the meaning of an expression, one must first define an
interpretation of the symbols:
62
* I2 () = reverse,
* I2 (<) = substring,
* I1 () = sorted version.
Once an interpretation has been defined, one can compute the value of
an expression E under interpretation I, I (E) (i.e. the meaning of
an expression under interpretation) in the following way:
The value of terms under interpretation:
63
For example, consider I1 as defined above:
I1 ((0 + 1))) =
I1 ()(I1 (0 + 1)) =
factorial(I1 (+)(I1 (0), I1 (1))) =
factorial(multiplication(seven, zero)) =
factorial(zero) =
one.
Using these notions in practice is very difficult: the number of possible in-
tepretations for a language is infinite. Checking the value of an expression
in all possible intepretations is therefore not practical.
If a formula is (or a set of formulae are) true under an interpretation in a
domain, then that domain is called a model of the formula(e).
64
Let L be a language containing the constant symbols C, function symbols
F and predicate symbols P. Let F be a formula over L.
IH (p(t1 , . . . , tn )) = true.
Herbrands Theorem
65
Herbrands theorem (semantic form) tells us that we can reduce the ques-
tion of unsatisfiability in predicate logic to the question of unsatisfiability
in propositional logic.
For propositional logic, the resolution method is used to decide the
question of satisfiability. See [Craciun, 2010] for details.
For using resolution in propositional logic, propositional formulas are writ-
ten in Conjunctive Normal Form (CNF).
To use Herbrands theorem in and propositional resolution, one would
need a similar transformation for predicate logic.
Notation: Since the matrix only consists of universal quantifiers, these can
be omitted. The clausal form can be represented in the following manner
(clauses as sets of literals, formulae in clausal form as sets of clauses):
p(f (x)), q(y, z) ,
p(x), q(y, f (z)), r(x, y) ,
q(x, f (z)), r(f (y), f (z)) .
66
Notation: Let F , G be formulas. We denote F G if F and G are
equisatisfiable (i.e. F is satisfiable iff G is satisfiable).
Skolemization Algorithm
IN: closed formula F .
OUT: formula F 0 in clausal form such that F F 0 .
Running example:
1: Rename the bound variables such that no variable appears in the scope of
two different quantifiers.
3: Push the negations inside the parantheses, until negations apply only to
atomic formulae. Use the equivalences
(F ) F,
(F G) (F G),
(F G) (F G),
(xF [x]) xF [x],
(xF [x]) xF [x].
4: Extract the quantifiers from the matrix. Since the variables have been re-
named, the following equivalences can be applied: AopQxB[x] Qx(AopB[X])
and QxB[x]opA Qx(B[X]opA) where Q is one of , and op is one of
, .
67
5: Use the distributive laws P (Q R) (P Q) (P R),
(P Q) R) (P R) (Q R) to transform the matrix into CNF.
6: Skolemization
If the prefix is of the form y1 . . . yn x, let f be a new n-ary function
symbol. Delete x from the prefix, replace all occurences of x in
the matrix by f (y1 , . . . , yn ). The function f is called a Skolem
function.
If there are no universal quantifiers before x in the prefix, let a
be a new constant. Eliminate x from the prefix and replace every
occurence of x in the matrix with a. The constant a is a Skolem
constant.
Note that steps 1-5 preserve logical consequence. It is relatively easy to show
that step 6 preserves satisfiability. For details, see [Ben-Ari, 2001].
68
11 Resolution
11.1 Ground Resolution
Herbrands theorem reduces the problem of establishing unsatisfiability of
a formula (set) to the problem of establishing unsatisfiability of a finite
set of ground formulae.
For practical purposes, given a finite set of ground formulae, one can
rename the distinct ground atoms by distinct propositional formulae and
thus answer the question of unsatisfiability by propositional resolution.
See [Craciun, 2010] for details on propositional resolution.
However, this approach is not practical: there is no indication how to find
the finite set of ground formulae: the set of possible ground instantiations
is both unbounded and unstructured.
11.2 Substitution
A substitution of terms for variables is a set:
{x1 t1 , . . . , xn tn }
69
Example: let
then:
= {x f (g(a)), y f (a), u z, v f (f (a))}.
11.3 Unification
Unifiers
Consider two nonground literals: p(f (x), g(y)) and p(f (f (a)), g(z)):
the substitution
applied to both the literals will make them identical (will unify
them),
the same effect is obtained when applying the substitutions
{x f (a), y a, z a},
{x f (a), z y}.
Unification algorithm
Note that the unifiability of the literals p(f (x), g(y)) and p(f (f (a)), g(z))
can be expressed as a set of term equations:
f (x) = f (f (a))
g(y) = g(z).
70
A set of term equations is in solved form iff:
Unification Algorithm
INPUT: A set of term equations.
OUTPUT: A set of term equations in solved form, or not unifiable.
t0 1 = t00 1 , . . . , t0 k = t00 k .
Apply rule 1 to the first equation and rule 3 to the second equation:
x = g(y)
x = g(z)
h(x) = w
y = z.
71
Apply rule 4 on the second equation to replace the other occurences of x:
g(z) = g(y)
x = g(z)
h(g(z)) = w
y = z.
z=y
x = g(z)
h(g(z)) = w
y = z.
x = g(z)
h(g(z)) = w
y = z.
x = g(z)
w = h(g(z))
y = z.
{x g(z), w h(g(z)), y z}
= {x1 t1 , . . . , xn tn }
11.4 Resolution
Ground resolution was not practical.
72
It turns out that a practical version of resolution is possible, using unifi-
cation.
Recall the notions of literal, clause, clause sets introduced in Subsec-
tion 10.3.
p(f (x), g(y)) q(x, y) p(f (f (a)), g(z)) q(f (a), g(z))
L1 = p(f (x), g(y)) and L2 c = p(f (f (a)), g(z)) can be unified with the mgu
{x f (a), y z} and the resolvent of the clauses is:
Note that the requirement for clauses to have no variables in common does
not impose any real restrictions on the clause set. Remember that clauses
are implicitly universally quantified, so changing the name of a variable
does not change the meaning of the clause set.
Repeat
until Si+1 = Si
73
Return satisfiable.
Note that the the algorithm above may not terminate, it is not a decision
procedure (indeed that would not be expected since first order predicate
logic is undecidable). The reason for nontermination is the existance of
infinite models.
8. q(a) xa 3, 6
9. q(a) s(f (a)) xa 2.4
10. s(f (a)) 8, 9
11. q(a) r(a, f (a)) xa 1, 4
12. r(a, f (a)) 8.11
13. t(f (a)) y f (a) 5, 12
14. s(f (a)) x f (a) 7, 13
15. 10, 14
Example 10 (Resolution refutation with variable renaming, from [Ben-Ari, 2001]).
First four clauses represent the initial clause set.
1. p(x, y) p(y, x)
2. p(x, y) p(y, z) p(x, z)
3. p(x, f (x))
4. p(x, x)
30 . p(x0 , f (x0 )) Rename 3.
5. p(f (x), x) 1 = {y f (x), x0 x} 1, 30
300 . p(x00 , f (x00 )) Rename 3
6. p(f (x), z) p(x, z) 2 = {y f (x), x00 x} 2, 300
5000 . p(f (x000 ), x000 ) Rename 5
7. p(x, x) 3 = {z x, x000 x} 6, 5000
40000 . p(x0000 , x0000 ) Rename 4
8. 4 = {x0000 x} 7, 40000
74
The substitution resulting from composing all intermediary substitutions:
Restricted to the variables from the initial set, the resulting substitution
is:
= {y f (x), z x}
For details on how the proofs of these theorems, see [Ben-Ari, 2001].
Good choices will lead to the result quickly, while bad choices may lead
to the algorithm not terminating.
The completeness theorem says that if the clause set is unsatisfiable a
resolution refutation (generation of the empty clause) exists, i.e. that
which uses good choices. Variants with bad choices may miss the solution.
Items of interest:
75
12 Logic Programming
12.1 Formulas as programs
Consider a fragment of the theory of strings, with the binary function
symbol (concatenation) and binary predicates substr, pref ix, suf f ix,
described by the following axioms:
1. x substr(x, x)
2. xyz ((substr(x, y) suf f ix(y, z)) substr(x, z))
3. xy suf f ix(x, y x)
4. xyz ((substr(x, y) pref ix(y, z)) substr(x, z))
5. xy pref ix(x, x y)
1. x is a substring of x.
2. To check is x is a substring of z, find a suffix y of z and check if x is
a substring of y.
3. x is a suffix of y x,
4. To check if x is a substring of z, find a prefix y of z and check if x is
a substring of y.
5. x is a prefix of x y.
6. substr(a b c, a a b c c)
7. substr(a b c, y1) suf f ix(y1, a a b c c) 6, 2
8. substr(a b c, a b c c) 7, 3
9. substr(a b c, y2) pref ix(y2, a b c c) 8, 4
10. substr(a b c, a b c) 9, 5
11. 10, 1
wsubstring(w, a a b c c)
76
Denoting the axioms by the formula Axioms, we must show that the
following formula is unsatisfibable:
But this is
The notation used in the first part of this lecture (in particular by the
Prolog syntax) for program clauses is A:-B1 , . . . , Bn . From now on we
will use this notation.
77
A computation rule is a rule for choosing a literal in a goal clause to
solve with. A search rule is a rule for choosing a clause to resolve with
the chosen literal in the goal clause.
3. p(b, a)
4. p(c, a)
5. p(d, b)
6. p(e, b)
7. p(f, b)
8. p(h, g)
9. p(i, h)
10. p(j, h)
In other words, the correct answer substitution makes the negation of the
goal clause a logical consequence of the program.
Example 18.
Consider a refutation for the goal clause :-q(y, b), q(b, z) from the program
introduced in Example 16. At each step, choose a literal within the goal
clause and a clause whose head clashes with that literal:
78
1. Choose q(y, b) and resolve with the clause 1, obtain :-p(y, b), q(b, z).
2. Choose p(y, b) and resolve with clause 5, obtain :-q(b, z). The needed
substitution is {y d}.
3. Choose the remaining literal :-q(b, z) and resolve with clause 1, obtain
:-p(b, z).
4. Choose the remaining literal :-p(b, z) and resolve with clause 3, obtain
. The needed substitution is {z a}.
We obtained the empty clause . With the correct answer substitution
{y d, z a} applied to the goal, we get that
P q(d, b) q(b, a).
79
Proof. See [Ben-Ari, 2001], pp. 179.
Note that the above results only refer to Horn clauses (logic programs),
not to arbitrary clauses. SLD resolution is not complete for arbitrary
clauses:
p q, p q, p q, p q
is unsatisfiable, but there is no SLD-resolution of for it (exercise!).
A correct answer substitution exists but this resolution will not terminate.
Consider the computation rule that always chooses the first literal in the
goal. The SLD resolution proceeds as follows:
1. q(y, b) is chosen and resolved with clause 2, obtain :-p(y, z 0 ), q(z 0 , b), q(b, z).
2. Choose the first literal p(y, z 0 ) and resolve it with clause 6 p(e, b),
then with clause 1 and obtain :-q(b, b), q(b, z), then :-p(b, b), q(b, z).
3. No program clause unifies with p(b, b) and this resolution fails.
Even though an answer substitution exists, resolution fails.
Definition 23 (SLD-trees).
80
Definition 24.
In an SLD-tree, a branch leading to a refutation is called a success
branch. A branch leading to a goal clause which cannot be resolved
is called a failed branch. A branch corresponding to a non-terminating
derivation is called an infinite branch.
Example 25 (SLD-tree).
The following is the SLD tree for the derivation in Examples 16, 18 where
the choice rule is to resolve with the leftmost literal in the goal (see also
Example 22). The chosen literal is underlined, the clause resolved with
is the label of the edge. Successful branches are indicated with , failed
.
branches with , infinite branches with ...
q(y, b)
(1) (2)
Note that the SLD resolution is complete for any computation rule (i.e.
a refutation exists). However, the choice of the search rule is essential in
whether or not this refutation exists.
81
If a more restricted notion of completeness is considered (a refutation
exists and is found), certain search rule make SLD resolution incomplete:
for example the depth-first rule search rule (which Prolog uses: Prolog =
SLD resolution with leftmost literal as computations rule and depth-first
search rule).
There are search rules for which SLD resolution is complete (in the stronger
sense):
breath-first (search every level of the SLD tree),
bounded depth first (go down up to a certain depth, then try another
branch down to that depth, and so on, if the solution is not found,
increase the depth).
However, these complete search rules are computationally expensive. A
trade-off between completeness and efficiency is made.
Items of interest:
References
[Ben-Ari, 2001] Ben-Ari, M. (2001). Mathematical Logic for Computer Science.
Springer Verlag, London, 2nd edition.
82
[Clocksin and Mellish, 2003] Clocksin, W. F. and Mellish, C. S. (2003).
Programming in Prolog. Springer, Berlin, 5th edition.
[Covington, 1989] Covington, M. (1989). Efficient Prolog: A Practical Guide.
Technical Report Research Report AI-1989-08, University of Georgia, Athens,
Georgia.
[Covington et al., 1997] Covington, M., Nute, D., and Vellino, A. (1997). Prolog
Programming in Depth. Prentice Hall, New Jersey.
[Craciun, 2010] Craciun, A. (2005-2010). Logic for Computer Science.
[Nilsson and Maluszynski, 2000] Nilsson, U. and Maluszynski, J. (2000). Logic,
Programming and Prolog. copyright Ulf Nilsson and Jan Maluszynski, 2nd
edition.
[Wielemaker, 2008] Wielemaker, J. (19902008). SWI-Prolog 5.6.60 Reference
Manual. University of Amsterdam.
83