Logic Programming Notes
Logic Programming Notes
Adrian Craciun
November 22, 2013
Contents
I
An Introduction to Prolog
1 Introduction
1.1 Traditional programming paradigms . . . . . . . . . . . . . . . .
1.2 Logic programming . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
8
8
12
14
14
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
15
15
16
16
17
18
19
21
21
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
28
29
30
30
32
36
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
37
37
38
41
46
.
.
.
.
.
.
.
.
7 Efficient Prolog
7.1 Declarative vs. Procedural Thinking
7.2 Narrow the search . . . . . . . . . .
7.3 Let Unification do the Work . . . . .
7.4 Understand Tokenization . . . . . .
7.5 Tail recursion . . . . . . . . . . . . .
7.6 Let Indexing Help . . . . . . . . . .
7.7 How to Document Prolog Code . . .
7.8 Reading and Further Exercises . . .
8 I/O
8.1
8.2
8.3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
47
48
48
49
49
51
52
52
with Prolog
53
Edinburgh style I/O . . . . . . . . . . . . . . . . . . . . . . . . . 53
ISO I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Reading and Further Exercises . . . . . . . . . . . . . . . . . . . 58
II
61
10 Logical Background
10.1 Predicate logic . . . . . . . . .
10.2 Herbrands Theorem . . . . . .
10.3 Clausal Form of Formulae . . .
10.4 Reading and Further Exercises
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61
61
64
66
68
11 Resolution
11.1 Ground Resolution .
11.2 Substitution . . . . .
11.3 Unification . . . . .
11.4 Resolution . . . . . .
11.5 Reading and Further
. . . . . .
. . . . . .
. . . . . .
. . . . . .
Exercises
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
69
69
69
70
72
75
12 Logic Programming
12.1 Formulas as programs . . . . .
12.2 Horn Clauses . . . . . . . . . .
12.3 SLD Resolution . . . . . . . . .
12.4 Reading and Further Exercises
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
76
76
77
79
82
Part I
An Introduction to Prolog
1
Introduction
1.1
In fact, such programming languages take into account the architecture of the machine they address and can be used to write efficient
programs.
The above point is by no means trivial, and it leads to a separation
of work (the software crisis):
finding solutions of problems (using reasoning),
implementation of the solutions (mundane and tedious).
Alternatives to the von Neumann approach
How about making programming part of problem solving?
i.e. write programs as you solve problems?
rapid prototyping?
Logic programming is derived from an abstract model (not a reorganization/abstraction of a von Neumann machine).
In logic programming
1.2
Logic programming
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)
2.1
Overview
2.2
Facts
2.3
Queries (Goals)
A query in Prolog:
? owns ( mary , book ) .
Prolog searches in the knowledge base for facts that match the question:
Prolog answers true if :
Variables
Think variables in predicate logic.
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.
Variables can be:
To the query
? l i k e s ( john , X ) .
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 uninstantiated.
In the example above, two more ; Enter will determine Prolog to answer:
X = mary .
false
When no (more) matching facts are found in the knowledge base, Prolog
answers false .
food ) .
wine ) .
wine ) .
mary ) .
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 ).
Conjunctions: more complex queries (contd)
For the query:
? l i k e s ( mary , X) , l i k e s ( john , X ) .
Prolog: try to satisfy the first goal (if it is satisfied put a placemarker), then try to satisfy the second goal (if yes, put a placemarker).
If at any point there is a failure, backtrack to the last placemarker
and try alternatives.
Example: conjunction, backtracking
The way Prolog computes the answer to the above query is represented:
In Figure 1, the first goal is satisfied, Prolog attempts to find a match for
the second goal (with the variable instantiated).
The failure to find a match in the knowledge base causes backtracking,
see Figure 2.
The new alternative tried is successful for both goals, see Figure 3.
10
11
2.4
Rules
,
,
,
,
alfred ).
bertrand ) .
charles ).
david ) .
Rules as definitions
Rules can be used to express definitions.
Example:
12
Rules in Prolog
Rules in Prolog have a head and a body.
The body of the rule describes the goals that have to be satisfied for the
head to be true.
Example:
l i k e s ( john , X) :
l i k e s (X, wine ) .
l i k e s ( john , X) :
l i k e s (X, wine ) , l i k e s (X, f o o d ) .
l i k e s ( john , X) :
f e m a l e (X) , l i k e s (X, wine ) .
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 ,
p a r e n t s ( edward , a l b e r t ,
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,
p a r e n t s (Y,
victoria ).
victoria ).
M, F ) .
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)
Consider the following:
/ * 1 * / t h i e f ( john ) .
/ * 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
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).
2.6
14
3.1
Terms
constants,
variables,
structures.
3.1.1
Constants
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
3.1.3
Structures
Characters in Prolog
Characters:
A-Z
a-z
0-9
<>: .
+-*/\
? @#$&
Characters are ASCII (printing) characters with codes greater than 32.
Remark: allows the use of any character.
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.
The position:
* infix: x + y, x y
* prefix x
* postfix x!
Precedence: x + y z ?
Associativity: What is x + y + z? x + (y + z) or (x + y) + z?
Each operator has a precedence class:
1 - highest
2 - lower
...
lowest
/ have higher precedence than +
8/2/2 evaluates to:
17
3.3
Unification
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, variables, structures):
?T1 = T2 .
Remark on terminology: while in some Prolog sources the term matching is used, note that in the (logic) literature matching is used for the
situation where one of the terms is ground (i.e. contains no variables).
What = does is unification.
Occurs check
Consider the following unification problem:
? X = f (X ) .
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.
Unification should fail in such situations.
To avoid them, perform an occurs check: If T1 is a variable and T2 a
structure, in an expression like T1 = T2 make sure that T1 does not
occur in T2.
Occurence check is deactivated by default in most Prolog implementations
(is computationally very expensive) - Prolog trades correctness for speed.
A predicate complementary to unification:
3.4
Arithmetic in Prolog
where X is an uninstantiated variable, and Expr is an arithmetic expression, where all variables must be instantiated (Prolog has no equation
solver).
Example (with arithmetic(1))
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
,
,
,
,
area ( place1
area ( place2
area ( place3
area ( place4
203).
548).
800).
108).
,
,
,
,
3).
1).
4).
3).
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
3.6
4.1
Structures as Trees
Structures as trees
Consider the following structure:
parent ( charles , el i s ab e t h , p h i l i p ) .
elisabeth
philip
Other examples:
a + b* c
+
a
*
b
21
book
moby dick
author
herman
melville
sentence
noun
X
john
verb phrase
verb
noun
likes
mary
f (X, g (X, a ) ) .
g
4 X
In the above, the variable X is shared between nodes in the tree representation.
4.2
Lists
Introducing lists
Lists are a common data structure in symbolic computation.
Lists contain elements that are ordered.
22
or
[]
[]
vine
representation
tree
representation
.( a, .( b, [ ])) is
[]
a
.(.( a, []), .( a, .( X, [ ]))) is represented as
23
[]
[]
a
Syntactic sugar for lists
To simplify the notation, , can be used to separate the elements.
The lists introduced above are now:
[a] ,
[a, b] ,
[[ a ], a, X].
List manipulation
Lists are naturally split between the head and the tail.
Prolog offers a construct to take advantage of this: [H | T].
Consider the following example:
p([1 , 2 , 3]).
p ( [ the , cat , s a t , [ on , the , mat ] ] ) .
Y, Z ] = [ john , l i k e s , f i s h ]
john
likes
fish
24
[ c a t ] = [X | Y]
X = cat
Y = [ ]
[ X,
X =
Y =
Z =
Y | Z ] = [ mary , l i k e s , wine ]
mary
likes
[ 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:
Reading
Read the corresponding Chapter 3, Section 3.2, from [Clocksin and Mellish, 2003].
26
Recursion
5.1
Introducing Recursion
Induction/Recursion
Inductive domain:
Example: member
Implement in Prolog the predicate member/2, such that member(X, Y) is
true when X is a member of the list Y.
% 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 computation 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 elements 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.
Order of facts, rules in the database:
i s l i s t ( [ A| B] ) : i s l i s t (B ) .
is list ([]).
The order in which the rules and facts are given matters. In general, place
facts before rules.
5.2
Recursive Mapping
Mapping: given 2 similar structures, change the first into the second,
according to some rules.
Example:
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 ) .
5.3
Recursive Comparison
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 ) .
5.4
Joining Structures
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:
- 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
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 ) .
([a,
([b,
([ c ]
([] ,
b , c ] , 0 , N) .
c ] , 1 , N) .
, 2 , N) .
3 , N)
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 ) .
5.6
Difference Structures
Summary
Accumulators provide a technique to keep trace of the result so far (in
the accumulator variable) at each step of computation, such that when the
structure is traversed the accumulator contains the final result, which
is then passed to the output variable.
Now we consider a technique where we use a variable to hold the final
result and the second to indicate a hole in the final result, where more
things can be inserted.
Consider [a, b, c | X] - we know that this structure is a list up to a point
(up to X). We call this an open list (a list with a hole).
32
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 convenient.
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
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 [ ] ) .
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) .
5.7
Read Chapter 3, Chapter 7, Sections 7.5, 7.6, 7.7 of [Clocksin and Mellish, 2003].
Read Chapter 7 of [Nilsson and Maluszynski, 2000].
Read Section 12.2 of [Brna, 1988].
Try out in Prolog the examples.
Solve the corresponding exercises.
36
6.1
Backtracking behaviour
Once we find that george is a father, we dont expect to get the answer
again.
Consider the following recursive definition:
is nat (0).
i s n a t (X):
i s n a t (Y) ,
X i s Y+1.
37
? i s n a t (X ) .
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5 ;
X = 6 ;
...
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!
6.2
38
Example:library
Reference library:
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 .
39
? - client(X) , facility(X, Y).
X=C.Wetzer
? - bfacility(C.Wetzer, Y)c.
...
Book=book00111
Y =enquiries
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.
6.3
1. Confirm the choice of a rule (tell the system the right rule was found).
2. Cut-fail combination (tell the system to fail a particular goal without
trying to find alternative solutions).
3. Terminate a generate-and-test (tell the system to terminate the
generation of alternative solutions by backtracking).
Confirm the choice of a rule
Situation:
41
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 , ! .
ssum to (N, Res ):
N1 i s N1,
ssum to (N1 , Res1 ) ,
Res i s Res1 + N.
42
g e n e r a l c r i t e r i o n (X):
i n c o m e (X, I n c ) ,
3000 ,
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 essential predicates.
44
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 .
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.
There are two types of cut:
6.4
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
Efficient Prolog
7.1
can be read
declaratively, as the equation x = y + z,
procedurally: load y, load z, store x.
The need to understand the procedural/declarative aspects
The declarative/procedural aspects are not symmetrical: there are situations where one not understanding one aspect can lead to problems.
For procedural programs: A = (B + C) + D and A = B + (C +D) appear
to have equivalent declarative readings but:
However, ignoring its procedural meaning, this can lead to infinite loops
(when B and C are both unknown).
47
7.2
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).
Now considering a faster program:
s e t e q u i v a l e n t ( L1 , L2):
s o r t ( L1 , L3 ) ,
s o r t ( L2 , L3 ) .
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).
7.3
When patterns are involved, unification can do some of the work that the
programmer may have to do.
E.g. consider variants the predicate that detects lists with 3 elements:
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 appears 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 ) .
7.5
Tail recursion
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).
For recursive procedures the continuation and backtracking point have to
be remembered for each of the recursive calls.
This may lead to large memory requirements
Tail recursion
If a recursive predicate has no continuation, and no backtracking point,
Prolog can recognize this and will not allocate memory.
Such recursive predicates are called tail recursive (the recursive call is the
last in the clause and there are no alternatives).
They are much more effficient than the non-tail recursive variants.
49
In the above write writes (prints) the argument on the console and succeeds, 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 not tail recursive (it has a continuation):
t e s t 2 (N): write (N) , nl , NewN i s N+1 , t e s t 2 (NewN) , nl .
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 ) .
m(N, NewN): N >= 0 , NewN i s N + 1 .
m(N, NewN): N < 0 , NewN i s ( 1) *N.
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.
Summary: tail recursion
In Prolog, tail recursion exists when:
7.6
51
7.7
Consider some built-in predicates in Prolog, as presented in the help section 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.
7.8
52
Edinburg style I/O is the legacy style, still supported by Prolog implementations. It is relatively simple to use but has some limitations.
ISO I/O is the standard style, supported by all Prolog implementations.
There are some overlaps between the two styles.
8.1
Writing terms
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.
? write ( H e l l o t h e r e ) , nl , write ( Goodbye ) .
Hello there
Goodbye
true .
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 .
Note that Prolog displays the internal representation of terms. In particular, the internal representation of variables.
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.
One can switch between several open files:
? see ( aaaa ) ,
read (X1 ) ,
see ( bbbb ) ,
read (X2 ) ,
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 get reads one character from the default input (console).
? g e t (X ) .
|
%
X = 37.
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:
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:
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 properties like:
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
get char, peek char, put char, put code, get code, peek code, get byte,
peek byte, put byte.
Other predicates:
current input, current output, set input , set output, flush output, at the end of stream,
nl, etc.
Consult the documentation for the details of the syntax.
8.3
Read: Sections 2.2, 2.3, 2.6, 2.10, 2.12, A.7 of [Covington et al., 1997].
Try out the examples in Prolog.
Items of interest:
Operators in Prolog
The usual way to write a Prolog predicate is to put it in front of its
arguments:
functor ( arg1 , arg2 ,
...)
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.
The following have to be specified:
Meaning
Prefix, not associative.
Prefix, right-associative.
Postfix, not associative.
Postfix, left-associative.
Infix, not associative (like =).
Infix, right associative (like comma in compound goals).
Infix, left associative (like +).
Specifier
xfx
fx
xfx
xfy
xfy
fy
xfx
yfx
yfx
xfy
fy
Operators
:
: ?
;
>
,
not
= \= == \== @< is = =<
+
* / // mod
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
Defining operators.
60
Part II
Logical Background
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.
Syntax of first order predicate logic
The vocabulary of the language contains the symbols from which expressions of the language are built:
Reserved 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
a domain of objects,
relations between the objects (or properties of the objects),
processes or functions that produce new objects from other objects.
To find (compute) the meaning of an expression, one must first define an
interpretation of the symbols:
I1 (0) = seven,
I1 (1) = zero,
I1 (+) = multiplication,
I1 () = factorial,
I1 (<) = smaller than,
I1 () = divides.
62
* I2 () = reverse,
* I2 (<) = substring,
* I1 () = sorted version.
Note that interpretation shows the correspondence between the name of
a concept (constant, function symbol, predicate symbol) and the concept
described by that name.
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
I1 ((0 + 1))) =
I1 ()(I1 (0 + 1)) =
factorial(I1 (+)(I1 (0), I1 (1))) =
factorial(multiplication(seven, zero)) =
factorial(zero) =
one.
Validity, satisfiability, unsatisfiability
We are interested in the meaning of formulae, in particular:
10.2
Herbrands Theorem
Herbrand Universe
Fortunately, the difficulty represented by the immense number of possible
interpretations of a language can be overcome.
We will define a domain and an interpretation that captures all the
properties of all potential domains and interpretation.
Checking satisfiability (and validity) of a formula (set) can be done by
just checking the evaluation under a certain interpretation into this special
universe.
64
If c C then c H.
If t1 , . . . , tn and f F then f (t1 , . . . , tn ) H.
Note that if C = then add an arbitrary constant to the Herbrand
universe H.
The Herbrand universe is the set of ground terms that can be formed from
the constants and function symbols of the language.
The Herbrand base B of the language L or the formula F is the set of
ground atoms that can be formed from the predicate symbols in P and
terms in H.
A Herbrand interpretation IH for the language L is an interpretation
whose domain is the Herbrand universe H whose symbols are interpreted
to themselves:
If c C, IH (c) = c.
If f F, IH (f ) = f .
If f P, IH (p) = p.
A Herbrand model for a formula (set) F is a Herbrand interpretation
that satisfies F . A Herbrand model can be identified with a subset of the
Herbrand base, namely the subset for which
IH (p(t1 , . . . , tn )) = true.
Herbrands Theorem
Several remarkable results hold.
Theorem 1. Let F be a formula. F has a model iff it has a Herbrand
model.
Theorem 2 (Herbrands theorem (semantic form)). Let F be a formula
(set). F is unsatisfiable iff a formula built from a finite set of ground
instances of subformulae of F is unsatisfiable.
Theorem 3 (Herbrands theorem (syntactic form)). A formula F is provable iff a formula built from a finite set of ground instances of subformulas
of F is provable in propositional logic.
65
Herbrands theorem (semantic form) tells us that we can reduce the question 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 written in Conjunctive Normal Form (CNF).
To use Herbrands theorem in and propositional resolution, one would
need a similar transformation for predicate logic.
10.3
Q1 x1 . . . Qn xn M,
where Qi is a quantifier (either , ), for i = 1 . . . n, and M is a quantifierfree formula in CNF. Q1 x1 . . . Qn xn is called the prefix and M is called
the matrix.
A formula is closed iff it has no free variables (i.e. all variables are bound
by a quantifier).
A closed formula is in clausal form iff it is in PCNF and its prefix consists
only of universal quantifiers.
A clause is a disjunction of literals.
Example: The following formula is in clausal normal form:
xyz p(f (x))q(y, z) p(x)q(y, f (z))r(x, y) q(x, f (z))r(f (y), f (z)) .
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
Skolemization Algorithm
IN: closed formula F .
OUT: formula F 0 in clausal form such that F F 0 .
Running example:
x(p(x) q(x)) (xp(x) xq(x))
1: Rename the bound variables such that no variable appears in the scope of
two different quantifiers.
x(p(x) q(x)) (yp(y) zq(z))
2: Eliminate all the equivalence and implication connectives (, ).
x(p(x) q(x)) (yp(y) zq(z))
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].
x(p(x) q(x)) yp(y) zq(z)
4: Extract the quantifiers from the matrix. Since the variables have been renamed, 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
, .
xyz((p(x) q(x)) p(y) q(z))
67
10.4
68
11
11.1
Resolution
Ground Resolution
11.2
Substitution
{x1 t1 , . . . , xn tn }
where, for i = 1 . . . n, xi are distinct variables, ti are terms such that
xi and ti are distinct. Substitutions will be denoted by lowercase greek
letters (, , ,). The empty substitution is denoted by .
An expression is a term or formula (in particular literal, clause, or set
of clauses).
Let E be an expression, = {x1 t1 , . . . , xn tn }. An instance of
E (or the result of applying to E), E is the expression obtained by
simultaneously replacing every occurrence of xi in E by ti .
Example: let E = p(x) q(f (y)), = {x y, y f (a)}. Then
69
Example: let
11.3
Unification
Unifiers
Consider two nonground literals: p(f (x), g(y)) and p(f (f (a)), g(z)):
the substitution
{x f (a), y f (g(a)), z f (g(a))}
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}.
Given a set of literals, a unifier is a substitution that makes the atoms
of the set identical. A most general unifier (mgu) is a unifier such
that any other unifier can be obtained from by a further substitution
such that = .
Note that not all literals are unifiable: if the predicate symbols are different, the literals cannot be unified. Also, consider the case of p(x) and
p(f (x)). Since the substitution of the variable x has to be done in the same
time, the terms x and f (x) cannot be made identical, and the unification
will fail.
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
x = g(y)
x = g(z)
h(x) = w
y = z.
71
g(z) = g(y)
x = g(z)
h(g(z)) = w
y = z.
Apply rule 3 to the first equation
z=y
x = g(z)
h(g(z)) = w
y = z.
Apply rule 4 on the last equation to replace y by z in the first equation,
then erase the resulting z = z using rule 2:
x = g(z)
h(g(z)) = w
y = z.
Transform the second equation by rule 1:
x = g(z)
w = h(g(z))
y = z.
The algorithm terminates successfully. The resulting substitution
{x g(z), w h(g(z)), y z}
is the most general unifier of the initial set of equations.
Theorem 6 (Correctness of the unification algorithm). The unification algorithm terminates. If the algorithm terminates with the answer not unifiable,
there is no unifier for the set of term equations. If it terminates successfully,
the resulting set of equations is in solved form and it defines an mgu
= {x1 t1 , . . . , xn tn }
of the set of equations
Proof. See [Ben-Ari, 2001], pp. 158.
11.4
Resolution
72
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:
q(f (a), z) q(f (a), g(z)).
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.
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.
Example 9 (Resolution refutation, from [Ben-Ari, 2001]).
Lines 1-7 contain
the initial clause set. The rest of the lines represent the execution of the
resolution algorithm. On each line we have the resolvent, mgu and the
number of parent clauses (clashing clauses that were resolved).
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
q(a)
q(a) s(f (a))
s(f (a))
q(a) r(a, f (a))
r(a, f (a))
t(f (a))
s(f (a))
xa
xa
3, 6
2.4
8, 9
xa
1, 4
8.11
y f (a) 5, 12
x f (a) 7, 13
10, 14
p(x, y) p(y, x)
p(x, y) p(y, z) p(x, z)
p(x, f (x))
p(x, x)
p(x0 , f (x0 ))
p(f (x), x)
p(x00 , f (x00 ))
p(f (x), z) p(x, z)
p(f (x000 ), x000 )
p(x, x)
p(x0000 , x0000 )
74
Rename 3.
1, 30
Rename 3
2 = {y f (x), x00 x}
2, 300
Rename 5
3 = {z x, x000 x}
6, 5000
Rename 4
4 = {x0000 x}
7, 40000
1 = {y f (x), x0 x}
11.5
75
12
12.1
Logic Programming
Formulas as programs
1.
2.
3.
4.
5.
x substr(x, x)
xyz ((substr(x, y) suf f ix(y, z)) substr(x, z))
xy suf f ix(x, y x)
xyz ((substr(x, y) pref ix(y, z)) substr(x, z))
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.
The clausal form of these axioms is:
1.
2.
3.
4.
5.
substr(x, x)
substr(x, y) suf f ix(y, z) substr(x, z)
suf f ix(x, y x)
substr(x, y) pref ix(y, z) substr(x, z)
pref ix(x, x y)
6.
7.
8.
9.
10.
11.
substr(a b c, a a b c c)
substr(a b c, y1) suf f ix(y1, a a b c c) 6, 2
substr(a b c, a b c c)
7, 3
substr(a b c, y2) pref ix(y2, a b c c)
8, 4
substr(a b c, a b c)
9, 5
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:
Axioms (wsubstring(w, a a b c c)).
But this is
Axioms w(substring(w, a a b c c))
which can be written in a straightforward manner into clausal form (and
resolution is applicable).
A resolution refutation works with the substitution {w abc}: not only
was the logical consequence proved, but a value for w was computed such
that substring(w, a a b c c) is true. In this context, the string axiom
constitute a program that computes answers to questions. However,
the program is highly nondeterministic. Choices that can be made during
the execution of the program (by resolution) influence the result and even
the answer.
The nondeterministic formalism can be turned into a practical logic programming language by specifying rules for making choices.
12.2
Horn Clauses
77
in imperative programming the control of the program is given explicitly as part of the code by the programmer,
in logic programming the programmer writes declarative formulae
that describe the relationship between the input and the output, and
resolution together with the search and computation rules supply an
uniform control structure.
As a consequence of the uniform control structure, there are cases when
logic programs will not be as efficient as special handcrafted control structures for specific computations.
q(x, y):-p(x, y)
q(x, y):-p(x, z), q(z, y)
3.
4.
5.
6.
7.
8.
9.
10.
p(b, a)
p(c, a)
p(d, b)
p(e, b)
p(f, b)
p(h, g)
p(i, h)
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).
12.3
SLD Resolution
=
=
=
=
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).
Let P be a set of program clauses, R a computation rule and G a foal
clause. All possible SLD-derivations can be displayed on an SLD-tree,
constructed in the following manner:
Te root is labeled with the goal clause G.
Given a node n labeled with a goal clause Gn , create a child ni for
each new goal clause Gni that can be obtained by resolving the literal
chosen by R with the head of a clause from P.
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)
p(y, b)
(5)
(3)
(10)
(6)
q(a, b)
(1)
p(a, b)
...
q(h, b)
(2)
p(a, z 0 ), q(z 0 , b)
..
.
(1)
p(h, j)
(2)
p(h, z 00 ), q(z 00 , j)
..
.
Theorem 26.
Let P be a program and G be a goal clause. Then every SLD-tree for P
and G has infinitely many success branches, or they all have the same
finite number of success branches.
Proof. Not given here.
Definition 27.
A search rule is a procedure for searching an SLD-tree for a refutation.
A SLD-refutation procedure is the SLD-resolution algorithm together
with the specification of a computation rule and a search rule.
Some comments on the completeness of SLD resolution
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
12.4
References
[Ben-Ari, 2001] Ben-Ari, M. (2001). Mathematical Logic for Computer Science.
Springer Verlag, London, 2nd edition.
[Brna, 1988] Brna, P. (1988). Prolog Programming A First Course. copyright
Paul Brna.
82
83