Prolog Coding
Prolog Coding
4 Arithmetic and
Nondeterminism
Prolog arithmetic can be a little surprising; you need to be
aware of modes. Sometimes nondeterminism needs to be
managed.
1. Arithmetic
2. Operators
3. Modes and Arithmetic
4. Expressions
5. Managing Nondeterminism
6. Arithmetic and Lists
85
:-
4.1 Arithmetic
In most languages 3 + 4 is an expression that has a value
In Prolog, 3 + 4 is just a term whose functor is + and
arguments are 3 and 4
Its not code, its data
The Prolog builtin = just unies (matches) two terms, it
does not evaluate expressions
?- X = 3 + 4.
X = 3+4 ;
No
86
:-
Arithmetic (2)
Use the built in is/2 predicate to compute the value of an
arithmetic expression:
?- is(X, 3+4).
X = 7 ;
No
is(X, Y) holds when X is a number and Y is an arithmetic
expression and X is the value of Y
87
:-
4.2 Operators
is is actually an inx operator in Prolog
This means that instead of writing is(X,3+4) we could also
have written X is 3+4
This is easier to read, so it preferred, although both work
Similarly, + is an operator; 3+4 is the same as +(3,4)
Operators in Prolog are not exclusively for arithmetic, they
are part of Prologs syntax
Prolog has many other standard operators; some we have
already seen, including :- , ; mod
Operators only aect syntax, not meaning
You can dene your own operators
88
:-
4.2.1 Precedence and Associativity
Operators have precedence and associativity
Use parentheses for grouping
E.g. * and / have higher precedence than + and -; they all
associate to the left
?- X is 3 + 4 * 5, Y is (3 + 4) * 5.
X = 23
Y = 35
Yes
?- X is 5 - 3 - 1, Y is 5 - (3 - 1).
X = 1
Y = 3
Yes
89
:-
4.2.2 Display
The built-in predicate display/1 is useful for understanding
how your input will be parsed when it includes operators
display/1 prints a term as Prolog understands it, using
only the standard form with the functor rst, and
arguments between parentheses
?- display(3 + 4 * 5), nl, display((3 + 4) * 5).
+(3, *(4, 5))
*(+(3, 4), 5)
Yes
?- display(5 - 3 - 1), nl, display(5 - (3 - 1)).
-(-(5, 3), 1)
-(5, -(3, 1))
Yes
90
:-
4.3 Modes and Arithmetic
We could code a predicate to compute a square like this:
square(N, N2) :- N2 is N * N.
?- square(5, X).
X = 25 ;
No
?- square(X, 25).
ERROR: Arguments are not sufficiently instantiated
We cant use this denition to compute a square root!
91
:-
Modes and Arithmetic (2)
Unfortunately, is/2 only works when the second argument
is ground
The rst argument can be unbound or bound to a number
?- X is 3 + Y.
ERROR: Arguments are not sufficiently instantiated
?- 7 is 3 + 4.
Yes
?- 9 is 3 + 4.
No
?- 2 + 5 is 3 + 4.
No
92
:-
4.4 Expressions
Some arithmetic expressions understood by is/2:
E1 + E2 addition float(E1) oat equivalent of E1
E1 - E2 subtraction E1 << E2 left shift
E1 * E2 multiplication E1 >> E2 right shift
E1 / E2 division E1 /\ E2 bitwise and
E1 // E2 integer division E1 \/ E2 bitwise or
E1 mod E2 modulo (sign of E1) \ E1 bitwise complement
-E1 unary minus min(E1, E2) minimum
abs(E1) absolute value max(E1, E2) maximum
integer(E1) truncate toward 0
93
:-
Expressions (2)
Some useful arithmetic predicates:
E1 < E2 less than
E1 =< E2 equal or less Danger : not <= !!!
E1 >= E2 greater or equal
E1 > E2 greater than
E1 =:= E2 equal (only numbers)
E1 =\= E2 not equal (only numbers)
All of these take ground arithmetic expressions as both
arguments
94
:-
4.5 Managing Nondeterminism
A common Prolog programming error is treating multiple
clauses as if they formed an if-then-else construct
This is an erroneous denition of absolute_value:
absolute_value(X, X) :- X >= 0.
absolute_value(X, Y) :- Y is -X.
?- absolute_value(-3, V).
V = 3 ;
No
?- absolute_value(42, V).
V = 42 ;
V = -42 ;
No
Why do +ve numbers have two absolute values, one of
them -ve?
95
:-
Managing Nondeterminism (2)
The problem is that the second clause promises that
[n[ = n
for any n, regardless of its sign
The correct denition:
absolute_value(X, X) :- X >= 0.
absolute_value(X, Y) :- X < 0, Y is -X.
?- absolute_value(-3, V).
V = 3 ;
No
?- absolute_value(42, V).
V = 42 ;
No
96
:-
Exercise
Dene a Prolog predicate maximum(X,Y,Z) such that Z is the
larger of X and Y
97
:-
4.5.1 Fibonacci numbers
Fibonacci numbers: 1, 1, 2, 3, 5, 8, 13, . . .
fib(0, 1).
fib(1, 1).
fib(N, F) :-
N > 1,
N1 is N - 1,
N2 is N - 2,
fib(N1, F1),
fib(N2, F2),
F is F1 + F2.
What if we change the order of goals? What if we do F is
F1 + F2 rst?
Note: each call makes two recursive calls. Are there better
ways to compute Fibonacci numbers?
98
:-
4.6 Lists and Arithmetic
Summing a list combines arithmetic with list processing:
sumlist([], 0). % sum([]) = 0
sumlist([X[Xs], Sum) :- % sum([X[Xs]) = Sum if
sumlist(Xs, Sum1), % sum(Xs) = Sum1 and
Sum is Sum1 + X. % Sum = Sum1 + X
This can be done more eciently:
sumlist([], Sum, Sum). % sum([]) + Sum = Sum
sumlist([X[Xs], Sum0, Sum):-% sum([X[Xs]) + Sum0 = Sum if
Sum1 is Sum0 + X, % Sum1 = Sum0 + X, and
sumlist(Xs, Sum1, Sum).% sum(Xs) + Sum1 = Sum
See the lecture on eciency for more on this
99
:-
4.6.1 List Maximum
Compute the maximum element of a list
maxlist([X], X).
maxlist([X[Xs], Max) :-
maxlist(Xs, Max1),
maximum(Max1, X, Max).
Note: no clause for []! Base case is singleton list because
[] has no maximum
100
:-
4.6.2 List Length
The length/2 built-in relates a list to its length
?- length([a,b,c], 3).
Yes
?- length([a,b,c], N).
N = 3 ;
No
?- length(L, 3).
L = [_G263, _G266, _G269] ;
No
?- length(L, N).
L = []
N = 0 ;
L = [_G278]
N = 1
Yes
It is not straightforward to implement length/2 with
exible modes; covered later
101
:-
4.6.3 List Handling
Many other list predicates can be dened using append,
length.
member/2 could be dened just in terms of append:
member(X, L) :- % X is a member of L, if L of form
append(_, [X|_], L). % any list ++ [X] ++ any list
E is the N
th
element of list L (counting from 0):
element(N, L, E) :- % E is the Nth element of L
append(F, [E|_], L), % if exists F where L = F ++ [E] ++ any
length(F, N). % and the length of F is N
102
:-
List Handling (2)
T is a list taking the rst N elements of L:
take(N, L, T) :- % T is the first N elements of L
append(T, _, L), % if L = T ++ any list
length(T, N). % and the length of T in N
T is what is left after removing the rst N elements of L:
drop(N, L, T) :- % T is the first N elements of L
append(F, T, L), % if L = T ++ any list
length(F, N). % and the length of T in N
L is a list all of whose elements are E:
listof([], _). % [] is a list of anything
listof([E|Es], E) :- % [E|Es] is a list of Es if
listof(Es, E). % Es is
103
104
105
106
107
108
:-
5 Coding in Prolog
We work through examples to illustrate how to write
Prolog code
Our goal: support code for a computerized card game
1. Data and Representation
2. Generating a deck of cards
3. Shuing
4. Dealing
109
:-
5.1 Data
For any language, rst determine:
what data we manipulate,
how they are related,
what are their attributes, and
what are their primitive operations
We need to represent a (partial) deck of cards, a hand,
individual cards, suits, ranks
Assume we dont need jokers for this game
110
:-
Data (2)
Suits and Ranks have no attributes
Their primitive operations are only distinguishing them and
possibly enumerating them
A card comprises a suit and a rank those are its
attributes
Constructing a card from rank and suit, and nding a
cards rank and suit are its only primitive operations
A deck is just an (ordered) sequence of cards
Primitive operations include removing the top card or
adding a card on top; all other operations can be
implemented in terms of those
111
:-
5.2 Representation
Simplest Prolog representations for types without attributes
are atoms and numbers, e.g., hearts, jack, 10, etc
Good idea to write a predicate for each type to specify
what are members of the type
Same code can enumerate values
suit(clubs). suit(diamonds).
suit(hearts). suit(spades).
rank(2). rank(3). rank(4).
rank(5). rank(6). rank(7).
rank(8). rank(9). rank(10).
rank(jack). rank(queen).
rank(king). rank(ace).
112
:-
Representation (2)
Simplest Prolog representation for type with attributes is
compound term, one argument for each attribute
For playing card: card(R, S), where R is a rank and S is a
suit
card(card(R,S)) :-
suit(S),
rank(R).
Since rank and suit will enumerate the ranks and suits, this
code will enumerate the cards of a deck
113
:-
Representation (3)
Deck is just a sequence of any number of cards
Prolog has good support for lists good representation
for sequences
List is a deck if each element is a card, i.e., if empty, or if
rst element is a card and rest is a deck
deck([]).
deck([C|Cs]) :-
card(C),
deck(Cs).
This representation does not ensure a full deck, nor that
there are no repeated cards
114
:-
Exercise: Bridge Hand Evaluation
In Bridge, a hand has 4 high card points for each ace, 3,
for each king, 2 for each queen, and 1 for each jack.
Write a predicate to determine how many high card points
a hand has.
115
:-
5.3 Generating a Full Deck of Cards
deck predicate holds for any deck; we need a full deck
card predicate generates all cards in a deck:
?- card(C).
C = card(2, clubs) ;
C = card(3, clubs) ;
C = card(4, clubs) ;
C = card(5, clubs) ;
C = card(6, clubs) ;
C = card(7, clubs)
Just need a way to collect all solutions to a query
116
:-
5.3.1 All Solutions Predicates
Prolog has built-in predicates for collecting solutions
findall(T, G, L) L is a list of all terms T that satisfy
goal G in the order solutions are found; variables in G are
left uninstantiated; deterministic
setof(T, G, L) L is a non-empty list of all terms T that
satisfy goal G; L is sorted with duplicates removed;
variables appearing only in G can be instantiated; can be
nondeterministic (with dierent variable instantiations)
bagof(T, G, L) like setof/3 but without the sorting
NB: Template term T is left uninstantiated by all of these
predicates
117
:-
All Solutions Predicates (2)
?- bagof(C, card(C), Deck).
C = _G151
Deck = [card(2, clubs), card(3, clubs), card(4, clubs),
card(5, clubs), card(6, clubs), card(7, clubs),
card(8, clubs), card(9, clubs), card(..., ...)|...]
?- setof(C, card(C), Deck).
C = _G151
Deck = [card(2, clubs), card(2, diamonds), card(2, hearts),
card(2, spades), card(3, clubs), card(3, diamonds),
card(3, hearts), card(3, spades), card(..., ...)|...]
findall/3 has the same solution: no variables occur only in
G and the list of solutions is not empty
118
:-
All Solutions Predicates (3)
We dont care about order, and card predicate generates
each card exactly once, so either will work
Use bagof: no point sorting if not needed
new_deck(Deck) :-
bagof(C, card(C), Deck).
Call it new deck because it only holds for lists of all 52 cards
in the order of a brand new deck
NB: setof and bagof fail if goal G has no solutions you
dont get the empty list
119
:-
All Solutions Predicates (4)
NB: When goal G includes some variables not appearing in
template T, setof and bagof generate a dierent list L for
each distinct binding of those variables
?- setof(S, borders(State,S), Neighbors).
S = _G152
State = vic
Neighbors = [nsw, sa] ;
S = _G152
State = act
Neighbors = [nsw] ;
S = _G152
State = qld
Neighbors = [nsw, nt, sa]
To just get a list of states that border any state, use
State^borders(State,S) for G
120
:-
5.4 Coding Tips
Prolog lists are very exible, used for many things
Can do a lot with just length/2 and append/3
When writing list processing predicates, often have one
clause for [] and one for [X|Xs]
It is often easier to write a predicate if you pretend all
arguments are inputs
Think of it as checking correctness of output, rather than
generating output
Then consider whether your code will work in the modes
you want
121
:-
Exercise: Selecting the n
th
Element
Implement select nth1(N, List, Elt, Rest) such that Elt is
the N
th
element of List, and Rest is all the other elements
of List in order. It need only work when N is bound.
122
:-
5.5 Shuing
Dont want to faithfully simulate real shuing would
not be random
Shuing really means randomly permute list order
Simple method: repeatedly randomly select one card from
deck as next card until all cards selected
shuffle([], []).
shuffle(Deck0, [C|Deck]) :-
random_element(Deck0, C, Deck1),
shuffle(Deck1, Deck).
Important: random element must fail for empty deck
NB: Cannot work in reverse mode!
123
:-
5.5.1 Selecting a Random Card
Need to know size of deck to know probability of selecting
any one card
Then we can pick a random number n where 1 n length
and remove element n of the deck
Must give back remainder of deck as well as random card,
since we cannot destructively remove card from deck
random_element(List, Elt, Rest) :-
length(List, Len),
Len > 0,
random(1, Len, Rand),
select_nth1(Rand, List, Elt, Rest).
124
:-
5.5.2 Random Numbers
No such thing as a random number ; its how the number is
selected that is random
No standard random number predicate in Prolog
Good practice: dene reasonable interface, then look in
manual for built-ins or libraries to implement it
This makes maintenance easier
SWI denes random/1 function (not really a function!)
random(Lo, Hi, Rand) :-
Rand is Lo+random(Hi-Lo+1).
125
:-
5.6 Dealing
Interface for dealing:
deal(Deck, Numhands, Numcards, Hands, Rest)
Hands is a list of Numhands lists, each with Numcards cards
All cards come from the front of Deck; Rest is leftover cards
126
:-
Dealing (2)
Easiest solution: take rst Numcards cards from Deck for
rst player, next Numcards for next player, etc
Use append and length to take top (front) of Deck
deal(Deck, 0, _, [], Deck).
deal(Deck, N, Numcards, [H|Hs], Rest) :-
N > 0,
length(H, Numcards),
append(H, Deck1, Deck),
N1 is N - 1,
deal(Deck1, N1, Numcards, Hs, Rest).
127
128
129
130
131
132
:-
6 Determinism
Deterministic Prolog code is much more ecient than
nondeterministic code. It can make the dierence between
running quickly and running out of stack space or time.
1. Prolog implementation
2. Determinacy
3. If-then-else
4. Indexing
133
:-
6.1 Prolog implementation
Actual implementation of Prolog predicates is stack-based
a :- b, c.
b :- d, e.
b :- e.
c :- fail.
d :- e.
e.
To execute a, we invoke b, then c
While executing b, we must remember to go on to c; Like
most languages, Prolog uses a call stack
While executing rst clause of b, we must remember if we
fail, we should try the second
Prolog implements this with a separate stack, the
choicepoint stack
When a choicepoint is created, the call stack must be
frozen: cannot overwrite current call stack entries because
they may be needed after choicepoint is popped
134
:-
6.1.1 Stack Example
call
stack
choicepoint
stack
10
11
12
0
1
2
3
a :
b,
c.
b :
d,
b :
d :
4
5
6
7
8
9
e.
e.
e.
c :
fail.
e.
2
135
:-
Stack Example (2)
call
stack
choicepoint
stack
10
11
12
0
1
2
3
a :
b,
c.
b :
d,
b :
d :
4
5
6
7
8
9
e.
e.
e.
c :
fail.
e.
2 6
5
136
:-
Stack Example (3)
call
stack
choicepoint
stack
10
11
12
0
1
2
3
a :
b,
c.
b :
d,
b :
d :
4
5
6
7
8
9
e.
e.
e.
c :
fail.
e.
2 6
NB: call stack not popped!
137
:-
Stack Example (4)
call
stack
choicepoint
stack
10
11
12
0
1
2
3
a :
b,
c.
b :
d,
b :
d :
4
5
6
7
8
9
e.
e.
e.
c :
fail.
e.
138
:-
6.2 Determinacy
Pushing a choicepoint causes current call stack to be
frozen
We cant write over frozen part of call stack, so it must be
kept around indenitely
One choicepoint can freeze a large amount of stack space
So avoiding choicepoints is important to eciency
A predicate with multiple solutions should leave a
choicepoint
A predicate with only one solution should not
139
:-
6.3 Indexing
Indexing makes Prolog programs more deterministic than
you might expect them to be
Indexing takes a sequence of adjacent clauses whose
rst argument is bound and constructs an index to
quickly select the right clause(s)
When a goal has a non-variable rst argument, indexing
allows Prolog to immediately choose the clause(s) whose
rst argument matches the goals rst argument
Other clauses are not even considered
Indices are constructed automatically; no special action
needed
You can ask SWI Prolog to index on arguments other than
the rst using the index or hash declarations
140
:-
6.3.1 Indexing Example
For example, for the code
capital(tas, hobart). capital(vic, melbourne).
capital(nsw, sydney). capital(sa, adelaide).
capital(act, canberra). capital(qld, brisbane).
capital(nt, darwin). capital(wa, perth).
and the goal
?- capital(vic, X)
Prolog will jump immediately to the second clause
More importantly, after trying the second clause, Prolog
will know no other clause can possibly match, so will not
leave a choicepoint
For a goal such as capital(X, Y), the index will not be
used; Prolog will try every clause
141
:-
6.3.2 Indexing for Determinism
When possible, use indexing to avoid unnecessary
choicepoints
On most Prolog systems, only the outermost constructor
of the rst argument is indexed, e.g. with code:
foo(bar(a), 1). foo(bar(b), 2). foo(bar(c), 3).
foo(bar(b), X) would still leave a choicepoint
For eciency, rewrite to get indexing:
foo(bar(X), N) :- foobar(X, N).
foobar(a, 1). foobar(b, 2). foobar(c, 3).
142
:-
Indexing for Determinism (2)
Indexing is used even on predicates with only two clauses:
it allows many predicates to avoid choicepoints
append([], L, L).
append([J|K], L, [J|KL]) :-
append(K, L, KL).
Indexing allows append never to leave a choicepoint when
the rst argument is bound
143
:-
6.4 If-Then-Else
Our denition of absolute_value/2 from slide 96 was a bit
unsatisfying because both clauses compare X to 0:
absolute_value(X, X) :- X >= 0.
absolute_value(X, Y) :- X < 0, Y is -X.
Prolog actually performs the comparison twice
Arithmetic comparisons are cheap, but suppose the test
were something time consuming: we would not want to do
it twice
Conventional programming languages provide an
if-then-else construct which evaluates the condition only
once
144
:-
If-Then-Else (2)
Prolog also has an if-then-else construct, whose syntax is
( A -> B ; C )
This means: execute A; if it succeeds, then execute B;
otherwise, execute C instead
It also commits to the rst solution to A; see caution
below!
A form of negation dened in Prolog:
% "not provable"
\+ G :- (G -> fail ; true).
% a form of inequality: "not unifiable"
X \= Y :- \+ X=Y.
145
:-
If-Then-Else (3)
Dening absolute_value/2 with only one comparison:
absolute_value(X, Y) :-
( X < 0 ->
Y is -X
; Y = X
).
One clause which lls the role of both clauses in prev. defn.
?- absolute_value(-3, V).
V = 3 ;
No
?- absolute_value(42, V).
V = 42 ;
No
146
:-
If-Then-Else (4)
If-then-elses can be nested to give an if-then-elseif-else
structure.
comparison(X, Y, Rel) :-
( X < Y -> Rel = less
; X = Y -> Rel = equal
; Rel = greater
).
?- comparison(3, 4, X).
X = less ;
No
?- comparison(4, 3, X).
X = greater ;
No
?- comparison(4, 4, X).
X = equal ;
No
147
:-
6.4.1 Caution
If-then-else commits to the rst solution to the
condition goal, eliminating any other solutions
If-then-else works by removing choicepoints
This may limit the modes that code can be used in
This may cause code to simply be wrong
Use if-then-else with caution!
148
:-
6.4.2 Cautionary Example
Example: list_end(List, Sublist, End) holds when Sublist
is the End end of List, and End is front or back
Buggy implementation:
list_end(List, Sublist, End) :-
( append(Sublist, _, List) ->
End = front
; append(_, Sublist, List) ->
End = back
).
Note no else part; this is equivalent to an else part of fail
149
:-
Cautionary Example (2)
This code works in simple cases:
?- list_end([a,b,c,d], [a,b], End).
End = front ;
No
?- list_end([a,b,c,d], [d], End).
End = back ;
No
but gets it wrong when Sublist is found at both ends of
List
?- list_end([a,b,c,a,b], [a,b], End).
End = front ;
No
The use of if-then-else means that the code will never
admit that the sublist is at both ends of the list
150
:-
Cautionary Example (3)
There is a bigger aw: the if-then-else commits to the rst
solution of append
In many modes this is completely wrong
?- list_end([a,b,c], Sublist, End).
Sublist = []
End = front ;
No
?- list_end([a,b,c], Sublist, back).
No
151
:-
Cautionary Example (4)
Correct implementation does not use if-then-else at all
list_end(List, Sublist, front) :- append(Sublist, _, List).
list_end(List, Sublist, back) :- append(_, Sublist, List).
?- list_end([a,b], Sublist, End).
Sublist = []
End = front ;
Sublist = [a]
End = front ;
Sublist = [a, b]
End = front ;
Sublist = [a, b]
End = back ;
Sublist = [b]
End = back ;
Sublist = []
End = back ;
No
152
:-
6.4.3 Removing Unnecessary Choicepoints
Suppose a ground list L represents a set
member(foo,L) checks if fooL, but leaves a choicepoint
because there may be more than 1 way to prove foo l
( member(foo, L) -> true ; fail )
is equivalent, but will not leave a choicepoint
If we want to know whether there exists any X such that
foo(X) l, and we do not care about what X is, then
( member(foo(_), L) -> true ; fail )
will stop after rst match, removing choicepoint
Caution: only correct when L is ground
153
:-
6.4.4 When to Use If-Then-Else
Its safe to use if-then-else when:
The semantics (a b) (a c) is what you want; and
The condition is always ground when it is executed (be
careful!)
More generally, when:
The semantics (v
1
v
2
. . . (a b)) (v
1
v
2
. . . a c) is
what you want; and
v
1
, v
2
, . . . are all the variables in a when it is executed
(careful!); and
the condition is deterministic
We will see later how if-then-else can be used to make
predicates work in more modes than they otherwise would
154
155
156
:-
7 Search
Prologs ecient built-in search mechanism makes it ideal
for solving many sorts of problems that are tricky in
conventional languages
1. Path Finding
2. Iterative Deepening
3. 8 Queens
4. Constraint Programming
157
:-
7.1 Path Finding
Many problems come down to searching for a path through
a graph
For example, we may want to know if a person alice is a
descendant of another person zachary
If we have a relation parent/2 that species who is a
parent of whom, then ancestor/2 is the transitive closure
of parent/2
Transitive closure follows this pattern:
ancestor(A, A).
ancestor(D, A) :-
parent(D, P),
ancestor(P, A).
158
:-
Path Finding (2)
Finding paths in a graph is nding the transitive closure of
the adjacency/edge relation of the graph
Suppose a predicate edge/2 denes a graph:
159
a d
b
c
e
f g
edge(a,b). edge(a,c).
edge(b,d). edge(c,d).
edge(d,e). edge(f,g).
160
connected(N, N).
connected(L, N) :- edge(L, M), connected(M, N).
161
:-
Path Finding (3)
A small change in the graph makes it go badly wrong:
a
d
b c
e
f
g
edge(a,b). edge(a,c).
edge(b,d). edge(c,d).
edge(d,e). edge(f,g).
The graph now has a cycle (cannot happen for
ancestors!)
There is nothing to stop the Prolog code exploring the
innite path
162
:-
Path Finding (4)
?- trace, connected(a,e).
Call: (8) connected(a, e) ? creep
Call: (9) edge(a, _G215) ? creep
Exit: (9) edge(a, b) ? creep
Call: (9) connected(b, e) ? creep
Call: (10) edge(b, _G215) ? creep
Exit: (10) edge(b, d) ? creep
Call: (10) connected(d, e) ? creep
Call: (11) edge(d, _G215) ? creep
Exit: (11) edge(d, c) ? creep
Call: (11) connected(c, e) ? creep
Call: (12) edge(c, _G215) ? creep
Exit: (12) edge(c, a) ? creep
Call: (12) connected(a, e) ? creep
Call: (13) edge(a, _G215) ? creep
Exit: (13) edge(a, b) ?
163
:-
Path Finding (5)
Solution: keep a list of nodes visited along a path, and
dont revisit a node already on the list
connected(M, N) :- connected(M, [M], N).
connected(N, _, N).
connected(L, Path, N) :-
edge(L, M),
\+ member(M, Path),
connected(M, [M|Path], N).
?- connected(a, e).
Yes
Remember: \+ is negation
Also note the algorithmic complexity of this code is O(2
N
)
164
:-
7.2 Word Paths
Sometimes the path is the desired output
Word game: transform one word into another of the same
length by repeatedly replacing one letter of the word with
another so that each step is a valid English word
E.g., tranform big to dog
big bag lag log dog
Here we dont just want to know if it can be done, we
want to know the steps
165
:-
Word Paths (2)
transform(Initial, Final, [Initial|Steps]) :-
word(Initial),
word(Final),
transform(Initial, [Initial], Final, Steps).
transform(Final, _, Final, []).
transform(Initial, History, Final, [Next|Steps]) :-
step(Initial, Next),
word(Next),
\+ member(Next, History),
transform(Next, [Next|History], Final, Steps).
The second argument of transform/4 is used to avoid loops
166
:-
Word Paths (3)
step([_|Rest], [_|Rest]). % all but the first is the same
step([C|Rest0], [C|Rest]) :- % the first is the same but
step(Rest0, Rest). % at most one letter differs in rest
word("bag"). word("big"). word("bog"). word("bug").
word("lag"). word("leg"). word("log"). word("lug").
word("dag"). word("dig"). word("dog"). word("dug").
Also load our strings module from slide 201 for readable
output
167
:-
Word Paths (4)
?- transform("big", "dog", Steps).
Steps = ["big", "dig", "dag", "bag", "lag",
"leg", "log", "bog", "dog"] ;
Steps = ["big", "dig", "dag", "bag", "lag",
"leg", "log", "bog", "bug"|...]
Yes
?- transform("big", "dog",
| ["big","bag","lag","log","dog"]).
Yes
Well see later how to get Prolog to print out lists of
character codes as strings
168
:-
7.3 Iterative Deepening
Often we dont want just any solution; we want a shortest
one
Even if we dont need a shortest solution, we may want to
avoid innite (or just huge) branches in the search space
One way to do this is breadth rst search:
1. Create a list of just a singleton list of the starting
point in it
[["big"]]
2. Repeatedly extend each element in the list with all
possible next elements
[["big","bag"], ["big","bog"], ["big","bug"], ["big","dig"]]
3. Terminate when one list is a solution
169
:-
Iterative Deepening (2)
Breadth rst search is often impractical due to its high
memory usage
Often Iterative Deepening is a simple, practical, ecient
alternative
Iterative deepening works by doing a depth rst search for
a short solution
If this works, great; if not, start over looking for a longer
solution
Repeat until a solution is found
Work is repeated, but often the cost of doing a depth n
search is much smaller than the cost of a depth n + 1
search, so the waste is relatively small
170
:-
7.3.1 Word Paths Again
We can implement a predicate to nd the shortest
solutions to the word game as follows:
First determine the length of the shortest solution
Then commit to that length and nd solutions of exactly
that length
shortest_transform(Word0, Word, Steps) :-
( length(Steps0, Len),
transform(Word0, Word, Steps0) ->
length(Steps, Len),
transform(Word0, Word, Steps)
; fail
).
171
:-
Word Paths Again (2)
?- time(shortest_transform("big","dog",X)).
% 100 inferences, 0.00 CPU in 0.00 seconds (0% CPU, Infinite Lips)
X = ["big", "dig", "dog"] ;
No
LIPS means logical inferences per second
One logical inference is dened to mean one predicate
call
This code is so fast because it never tries to build long
paths
172
:-
7.4 8 Queens
Classic puzzle: place 8 queens on a chess board such that
none attack any others.
Where to put the next queen?
173
:-
8 Queens (2)
The search space for this program is large: 64 choose
8 =
64!
56!
10
14
If we check 1 million candidates per second, it would
take 135 years to check them all
Search space can be signicantly reduced (as usual)
One queen in every row, one in every column
Right representation makes a big dierence in search
performance
Represent board as a list of integers indicating in
which column the queen in that row is placed
Now 8 choose 8 = 8! = 40320 candidates easy
174
:-
8 Queens (3)
To check if a queen attacks another queen, only need
to check the diagonals
Number rows bottom to top, columns left to right
Queens on the same NESW diagonal have same
column row
Queens on the same SENW diagonal have same
column + row
Queens row number is position in list
175
:-
8 Queens (4)
If rst queen attacks second, no point placing any more,
so: add queens to board one at a time, checking after each
addition
Sneaky trick: add new queen in rst row, sliding other
queens down
Another trick: number rows from 0, so column row =
column + row = column
Check if queen in row 0 attacks queens in rows 1 . . . n:
noattack(Q, Qs) :- noattack(Q, 1, Qs).
noattack(_, _, []).
noattack(Q0, Row, [Q|Qs]) :-
Q0 =\= Q + Row,
Q0 =\= Q - Row,
Row1 is Row + 1,
noattack(Q0, Row1, Qs).
176
:-
8 Queens (5)
The main body of the code chooses columns from a list of
all possible columns until all queens have been placed.
Note the the last two arguments of queens/3 are an
accumulator pair.
queens(N, Qs) :-
range(1, N, Columns), % Columns = 1..8
queens(Columns, [], Qs).
queens([], Qs, Qs). % no positions left, done
queens(Unplaced, Safe, Qs) :-
select(Q, Unplaced, Unplaced1), % choose an unused position
noattack(Q, Safe), % check doesnt attack earlier Q
queens(Unplaced1, [Q|Safe], Qs).% continue placing remainder
177
:-
8 Queens (6)
The necessary utility predicates
select(X, [X|Ys], Ys). % X is removed from list leaving Ys
select(X, [Y|Ys], [Y|Zs]) :- % leave first element Y in list and
select(X, Ys, Zs). % select from rest of list
range(Lo, Hi, L) :- % L is the list from Lo .. Hi
( Lo > Hi -> % if Lo > Hi this is
L = [] % the empty list
; L = [Lo|L1], % otherwise the list starts
Next is Lo + 1, % with Lo and then is
range(Next, Hi, L1) % the list Lo+1 .. Hi
).
178
:-
8 Queens (7)
Try it:
?- queens(8, L).
L = [4, 2, 7, 3, 6, 8, 5, 1] ;
L = [5, 2, 4, 7, 3, 8, 6, 1] ;
L = [3, 5, 2, 8, 6, 4, 7, 1]
Yes
?- time(queens(8, L)).
% 4,691 inferences in 0.01 seconds (469100 Lips)
L = [4, 2, 7, 3, 6, 8, 5, 1]
Yes
?- time(queens(20, L)).
% 35,489,394 inferences in 211.64 seconds (167688 Lips)
179
:-
7.5 Constraint Programming
Much better handled by constraint (logic)
programming.
CP can answer 1,000,000 queens!
Current code fails as soon as possible after generating
a bad position
Better: dont generate a bad position in the rst place
Rather than generate and test, employ constrain and
generate:
Add all the constraints rst!
Then search
180
:-
8 Eciency and I/O
Correctness is much more important than eciency, but
once your code is correct, you may want to make it fast.
You may also want to input or output data.
1. Tail Recursion
2. Accumulators
3. Dierence Pairs
181
:-
8.1 Tail Recursion
For eciency, when calling the last goal in a clause body,
Prolog jumps straight to that predicate without pushing
anything on the call stack
This is called last call optimization or tail recursion
optimization
tail recursive means the recursive call is the last goal in the
body
A tail recursive predicate is ecient, as it runs in constant
stack space; it behaves like a loop in a conventional
language
182
:-
8.2 Accumulators
The natural denition of factorial in Prolog:
% F is N factorial
factorial(0, 1).
factorial(N, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F is F1 * N.
This denition is not tail recursive because it performs
arithmetic after the recursive call.
183
:-
Accumulators (2)
We make factorial tail recursive by introducing an
accumulating parameter, or just an accumulator
This is an extra parameter to the predicate which holds a
partially computed result
Usually the base case for the recursion will specify that the
partially computed result is actually the result
The recursive clause usually computes more of the partially
computed result, and passes this in the recursive goal
The key to getting the implementation correct is specifying
what the accumulator means and how it relates to the nal
result
184
:-
8.2.1 Accumulator Example
A tail recursive denition of factorial using an
accumulator:
factorial(N, F) :- factorial(N, 1, F).
% F is A times the factorial of N
factorial(0, F, F).
factorial(N, A, F) :-
N > 0,
N1 is N - 1,
A1 is N * A,
factorial(N1, A1, F).
Typical structure of a predicate using an accumulator
185
:-
Accumulator Example (2)
To see how to add an accumulator, determine what is done
after the recursive call
Respecify the predicate so it performs this task, too
For factorial, we compute factorial(N1, F1), F is F1 * N,
so we want factorial to perform the multiplication for us
too
% F is A times the factorial of N
new_factorial(N, A, F) :-
factorial(N, FN),
F is FN * A.
186
:-
Accumulator Example (3)
Replace the call to
factorial(N, FN) by the
body: unfold
Simplifying arithmetic:
new_factorial(0, A, F) :-
F is 1 * A.
new_factorial(N, A, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F2 is F1 * N,
F is F2 * A.
new_factorial(0, F, F).
new_factorial(N, A, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F is (F1 * N) * A.
187
:-
Accumulator Example (4)
By associativity of
multiplication:
Replace the copy of the
denition of new factorial:
factorial(N1, F1), F is F1 * ?
by call to new_factorial:
fold
new_factorial(0, F, F).
new_factorial(N, A, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
NA is N * A,
F is F1 * NA.
new_factorial(0, F, F).
new_factorial(N, A, F) :-
N > 0,
N1 is N - 1,
NA is N * A,
new_factorial(N1, NA, F).
188
:-
Exercise
Rewrite the mult predicate from an earlier exercise to be
tail recursive. Here is the old code:
mult(0, , 0). % multiplying anything by 0 gives 0
mult(s(X), Y, Z) :-% Z = Y (X + 1) if
mult(X, Y, W), % W = XY
add(W, Y, Z). % and Z = W +Y
189
:-
8.3 Dierence Pairs
Accumulators can be even more useful for building up lists
Recall our rev/2 predicate:
rev([], []).
rev([A|BC], R) :-
rev(BC, CB),
append(CB, [A], R).
The same approach works for this example
First respecify rev to append a list to the result:
% rev(BC, A, CBA)
% CBA is BC reversed with A appended
% to the end
190
:-
8.3.1 Dierence Pairs Example
Next revise the denition of rev
rev(AB, BA) :- rev(AB, [], BA).
rev([], A, A).
rev([B|CD], A, DCBA) :-
rev(CD, [B|A], DCBA).
This denition is tail recursive
Much more importantly, it does not call append
If l is the length of the input list, the original version
performs about l
2
/2 steps, while the new one performs
about l steps
191
:-
Dierence Pairs Example (2)
When working with lists, using accumulators is very
common
Common to have an accumulator for each list being
constructed
Thus lists are often passed as a pair of arguments: one the
actual result, and the other the list to be appended to the
natural result to get the actual result
Can think of the natural result of the operation as the
actual result minus the accumulator argument
Such pairs of arguments are called dierence pairs or
dierence lists
Common to put such pairs in the opposite order,
accumulator second, to emphasize that the accumulator is
the tail end of the actual result
192
:-
Dierence Pairs Example (3)
% tree_list(Tree, List)
% List is a list of the elements of tree,
% in order
tree_list(Tree, List) :-
tree_list(Tree, List, []).
% tree_list(Tree, List, List0)
% List is a list of the elements of tree,
% in order, followed by the list List0
tree_list(empty, List, List).
tree_list(tree(L,V,R), List, List0) :-
tree_list(L, List, [V|List1]),
tree_list(R, List1, List0).
193
:-
8.4 Term I/O
?- write(hello).
hello
Yes
?- write(42).
42
Yes
?- write([a,b,c]).
[a, b, c]
Yes
?- write((3+(4*5)*6)).
3+4*5*6
Yes
write/1 writes any term in its normal format (considering
operators), with mimimal parentheses, to current output
stream.
194
:-
8.4.1 Read Example
?- read(X).
|: [a,b,c].
X = [a, b, c] ;
No
?- read(X).
|: foo(A,3,A /* repeated variable */).
X = foo(_G231, 3, _G231) ;
No
?- read(X).
|: 7
|: .
X = 7 ;
No
195
:-
8.5 Character I/O
An individual character can be written with the put/1
predicate
Prolog represents characters as integers character codes
Can specify character code for a character by preceding it
with 0 (no matching close quote)
?- put(65), nl.
A
Yes
?- put(0a), nl.
a
Yes
?- put(0a), put(0 ), put(0z).
a z
Yes
196
:-
8.5.1 Reading Characters
The built-in get0/1 predicate reads a single chararacter
from the current input stream as a character code
get0/1 returns -1 at end of le
?- get0(C1), get0(C2), get0(C3).
|: hi
C1 = 104
C2 = 105
C3 = 10 ;
No
197
:-
8.5.2 Dening I/O Predicates
A predicate to write a line of text as a list of character
codes:
write_line([]) :- nl.
write_line([C|Cs]) :- put(C), write_line(Cs).
198
:-
Exercise: Read a Line of Input
Write a predicate to read a line of input as a list of
character codes. read line(Line) should read a line from
the current input stream, binding Line to the list of
character codes read, without the terminating newline
character.
199
:-
8.5.3 String Notation
?- read_line(X), write_line(X).
|: hello world!
hello world!
X = [104, 101, 108, 108, 111, 32, 119, 111, 114|...] ;
No
Prolog has a special syntax for lists of character codes:
characters between double quotes
?- X = "hello, world!", write_line(X).
hello, world!
X = [104, 101, 108, 108, 111, 44, 32, 119, 111|...] ;
No
200
:-
8.6 print and portray
Query and debugger output is done with print/1
Mostly the same as writeq/1, but you can reprogram it by
dening predicate user:portray/1
:- multifile user:portray/1.
user:portray(Term) :-
ground(Term),
chars(Term),
!,
put(0"),
putchars(Term),
put(0").
chars([]).
chars([C|Cs]) :-
printable(C),
chars(Cs).
printable(C) :-
integer(C),
( code_type(C, graph)
; code_type(C, space)
).
putchars/1 is like write_line/1 without call to nl/0
Note: ! is called cut. It prevents backtracking to other
clauses (use -> instead if at all possible)
201
:-
print and portray (2)
With this code loaded, Prolog prints lists of character
codes as quoted strings.
Without portray code
?- print("abcd").
[97, 98, 99, 100]
Yes
?- X = "abcd".
X = [97, 98, 99, 100]
Yes
With portray code
?- print("abcd").
"abcd"
Yes
?- X = "abcd".
X = "abcd"
Yes
Code is available in strings.pl
202
:-
8.7 Order Sensitivity
Like arithmetic in Prolog, I/O predicates are sensitive to
the order in which they are executed
write(hello), write(world) always prints out helloworld,
and never worldhello, although conjunction is meant to be
commutative
Backtracking cannot undo I/O, e.g. get0(0a) reads a
character and fails if it is not an a, but does not put
back the character if it fails
Term output puts out a term as it is, so
?- write(foo(X)), X=bar.
foo(_G258)
X = bar ;
No
?- X=bar, write(foo(X)).
foo(bar)
X = bar ;
No
203
:-
8.7.1 Best Practice
Due to the procedural nature of Prolog I/O, it is usually
best to keep the I/O part of an application as isolated as
possible
E.g. write predicates that read in all input and build some
appropriate term to represent it, then write code that
processes the term
E.g. write predicates that build up output in some
appropriate term representation, then have separate code
to perform the actual output
This makes debugging easier: you cannot easily retry goals
that read input, as retry does not automatically rewind
input streams
204
:-
9 Parsing in Prolog
Prolog was originally developed for programming natural
language (French) parsing applications, so it is well-suited
for parsing
1. DCGs
2. DCG Translation
3. Tokenizing
4. Example
205
:-
9.1 DCGs
A parser is a program that reads in a sequence of
characters, constructing an internal representation
Prologs read/1 predicate is a parser that converts
Prologs syntax into Prolog terms
Prolog also has a built-in facility that allows you to
easily write a parser for another syntax (e.g., C or
French or student record cards)
These are called denite clause grammars or DCGs
DCGs are dened as a number of clauses, much like
predicates
DCG clauses use --> to separate head from body,
instead of :-
206
:-
9.1.1 Simple DCG
Could specify a number to be an optional minus sign, one
or more digits optionally followed by a decimal point and
some more digits, optionally followed by the letter e and
some more digits:
number -->
( "-"
; ""
),
digits,
( ".", digits
; ""
),
( "e", digits
; ""
).
number (-[)digits(. digits[)
(e digits[)
207
:-
Simple DCG (2)
Dene digits:
digits -->
( "0" ; "1" ; "2" ; "3" ; "4"
; "5" ; "6" ; "7" ; "8" ; "9"
),
( digits
; ""
).
digit 0[1[2[3[4[
5[6[7[8[9
digits digit digits[digit
A sequence of digits is one of the digit characters followed
by either a sequence of digits or nothing
208
:-
9.1.2 Using DCGs
Test a grammar with phrase(Grammar,Text) builtin, where
Grammar is the grammar element (called a nonterminal)
and Text is the text we wish to check
?- phrase(number, "3.14159").
Yes
?- phrase(number, "3.14159e0").
Yes
?- phrase(number, "3e7").
Yes
?- phrase(number, "37").
Yes
?- phrase(number, "37.").
No
?- phrase(number, "3.14.159").
No
209
:-
Using DCGs (2)
Its not enough to know that "3.14159" spells a number, we
also want to know what number it spells
Easy to add this to our grammar: add arguments to our
nonterminals
Can add actions to our grammar rules to let them do
computations
Actions are ordinary Prolog goals included inside braces {}
210
:-
9.1.3 DCGs with Actions
DCG returns a number N
number(N) -->
( "-" ->
{ Sign = -1 }
; { Sign = 1 }
),
digits(Whole),
( ".", frac(Frac),
{ Mantissa is Whole + Frac }
; { Mantissa = Whole }
),
( "e", digits(Exp),
{ N is Sign * Mantissa * (10 ** Exp) }
; { N is Sign * Mantissa }
).
211
:-
DCGs with Actions (2)
digits(N) -->
digits(0, N). % Accumulator
digits(N0, N) --> % N0 is number already read
[Char],
{ 00 =< Char },
{ Char =< 09 },
{ N1 is N0 * 10 + (Char - 00) },
( digits(N1, N)
; { N = N1 }
).
"c" syntax just denotes the list with 0c as its only member
The two comparison goals restrict Char to a digit
212
:-
DCGs with Actions (3)
frac(F) -->
frac(0, 0.1, F).
frac(F0, Mult, F) -->
[Char],
{ 00 =< Char },
{ Char =< 09 },
{ F1 is F0 + (Char - 00)*Mult },
{ Mult1 is Mult / 10 },
( frac(F1, Mult1, F)
; { F = F1 }
).
Multiplier argument keeps track of scaling of later digits.
Like digits, frac uses accumulator to be tail recursive.
213
:-
Exercise: Parsing Identiers
Write a DCG predicate to parse an identier as in C: a
string of characters beginning with a letter, and following
with zero or more letters, digits, and underscore
characters. Assume you already have DCG predicates
letter(L) and digit(D) to parse an individual letter or digit.
214
:-
9.2 DCG Translation
DCGs are just an alternative syntax for ordinary Prolog
clauses
After clauses are read in by Prolog, they may be
transformed by expand_term(Original,Final) where
Original is the clause as read, and Final is the clause
actually compiled
Clauses with --> as principal functor transformed by
adding two more arguments to the predicate and two
arguments to each call outside { curley braces }
expand_term/2 also calls a predicate term_expansion/2
which you can dene
This allows you to perform any sort of translation you
like on Prolog programs
215
:-
9.2.1 DCG Expansion
Added arguments form an accumulator pair, with the
accumulator threaded through the predicate.
nonterminal foo(X) is translated to foo(X,S,S0)
meaning that the string S minus the tail S0 represents
a foo(X).
A grammar rule a --> b, c is translated to
a(S, S0) :- b(S, S1), c(S1, S0).
[Arg] goals are transformed to calls to built in
predicate C(S, Arg, S1) where S and S1 are the
accumulator being threaded through the code.
C/3 dened as: C([X|Y], X, Y).
phrase(a(X), List) invokes a(X, List, [])
216
:-
9.2.2 DCG Expansion Example
For example, our digits/2 nonterminal is translated into a
digits/4 predicate:
digits(N0, N) -->
[Char],
{ 00 =< Char },
{ Char =< 09 },
{ N1 is N0*10
+ (Char-00) },
( digits(N1, N)
; "",
{ N = N1 }
).
digits(N0, N, S, S0) :-
C(S, Char, S1),
48 =< Char,
Char =< 57,
N1 is N0*10
+ (Char-48),
( digits(N1, N, S1, S0)
; N=N1,
S0=S1
).
(SWI Prologs translation is equivalent, but less clear.)
217
:-
9.3 Tokenizing
Parsing turns a linear sequence of things into a
structure.
Sometimes its best if these things are something
other than characters; such things are called tokens.
Tokens leave out things that are unimportant to the
grammar, such as whitespace and comments.
Tokens are represented in Prolog as terms; must
decide what terms represent which tokens.
218
:-
Tokenizing (2)
Suppose we want to write a parser for English
It is easier to parse words than characters, so we choose
words and punctuation symbols as our tokens
We will write a tokenizer that reads one character at a
time until a full sentence has been read, returning a list of
words and punctuation
219
:-
9.3.1 A Simple Tokenizer
sentence_tokens(Words) :-
get0(Ch),
sentence_tokens(Ch, Words).
sentence_tokens(Ch, Words) :-
( Ch = 10 -> %% end of line
Words = []
; alphabetic(Ch) ->
get_letters(Ch, Ch1, Letters),
atom_codes(Word, Letters),
Words = [Word|Words1],
sentence_tokens(Ch1, Words1)
; get0(Ch1),
sentence_tokens(Ch1, Words)
).
220
:-
A Simple Tokenizer (2)
alphabetic(Ch) :-
( Ch >= 0a, Ch =< 0z ->
true
; Ch >= 0A, Ch =< 0Z ->
true
).
get_letters(Ch0, Ch, Letters) :-
( alphabetic(Ch0) ->
Letters = [Ch0|Letters1],
get0(Ch1),
get_letters(Ch1, Ch, Letters1)
; Ch = Ch0,
Letters = []
).
221
:-
9.4 Parsing Example
Can write parser using standard approach to English
grammar
Many better approaches to parsing natural language
than we use here, this just gives the idea
An english sentence is usually a noun phrase followed
by a verb phrase, e.g. the boy carried the book
Noun phrase is the subject, verb phrase describes the
action and the object (if there is one)
Sentence may be an imperative: just a verb phrase,
e.g. walk the dog
222
:-
9.4.1 DCG Phrase Parser
sentence --> noun_phrase, verb_phrase.
sentence --> verb_phrase.
noun_phrase --> determiner, noun.
noun_phrase --> proper_noun.
verb_phrase --> verb, noun_phrase.
verb_phrase --> verb.
determiner --> word(determiner).
noun --> word(noun).
proper_noun --> word(proper_noun).
verb --> word(verb).
223
:-
9.4.2 Parsing for Meaning
Two problems:
1. no indication of the meaning of the sentence
2. no checking of agreement of number, person, etc
Solution to both is the same: make grammar rules
take arguments
Arguments give meaning
Unication can ensure agreement
224
:-
9.4.3 Parsing for Structure
sentence(action(Verb,Tense,Subject,Object)) -->
noun_phrase(Subject, Number, Person, nominative),
verb_phrase(Verb, Tense, Number, Person, Object).
sentence(action(Verb,Tense,imperative,Object)) -->
verb_phrase(Verb, Tense, _, second, Object).
noun_phrase(count(Thing,Definite,Number), Number, third, _) -->
determiner(Definite,Number),
noun(Thing, Number).
noun_phrase(Thing, Number, third, _) -->
proper_noun(Thing, Number).
noun_phrase(pro(Person,Number,Gender), Number, Person, Case) -->
pronoun(Person, Number, Case, Gender).
225
:-
Parsing for Structure (2)
verb_phrase(Verb, Tense, Number, Person, Object) -->
verb(Verb, Number, Person, Tense),
( noun_phrase(Object, _, _, objective)
; { Object = none }
).
determiner(Definite,Number) -->
word1(determiner(Definite,Number)).
noun(Thing, Number) -->
word1(noun(Thing,Number)).
proper_noun(Thing,Number) -->
word1(proper_noun(Thing,Number)).
pronoun(Person, Number, Case, Gender) -->
word1(pronoun(Person,Number,Case,Gender)).
verb(Verb,Number,Person,Tense) -->
word1(verb(Verb,Ending)),
{ verb_agrees(Ending, Number, Person, Tense) }.
226
:-
9.4.4 Parsing Examples
?- phrase(sentence(Meaning), [the,boy,carried,the,book]).
Meaning = action(carry,past,count(boy,definite,singular),
count(book,definite,singular)) ;
No
?- phrase(sentence(Meaning), [walk,the,dog]).
Meaning = action(walk,present,imperative,
count(dog,definite,singular)) ;
No
?- phrase(sentence(Meaning), [mary,walked]).
Meaning = action(walk, past, mary, none) ;
No
?- phrase(sentence(Meaning), [mary,walk]).
No
227
:-
9.4.5 Generation of Sentences
Carefully designed grammar can run backwards
generating text from meaning
?- phrase(sentence(action(carry, past,
count(boy,definite,singular),
count(book,definite,singular))), Sentence).
Sentence = [the, boy, carried, the, book] ;
No
?- phrase(sentence(action(walk, present,
pro(third,plural,masculine),
count(dog,definite,singular))), Sentence).
Sentence = [they, walk, the, dog] ;
No
?- phrase(sentence(action(walk, present,
count(dog,definite,singular),
pro(third,plural,masculine))), Sentence).
Sentence = [the, dog, walks, them] ;
No
228
:-
10 More on Terms
1. Handling Terms in General
2. Sorting
3. Term comparison
4. Variable and Type Testing
229
:-
10.1 Handling Terms in General
Sometimes it is useful to be able to write predicates that
will work on any kind of term
The =.. predicate, pronounced univ, turns a term into a
list
The rst element of the list is the terms functor; following
elements are the terms arguments, in order
?- p(1,q(3)) =.. X.
X = [p, 1, q(3)] ;
No
?- T =.. [p, 1, q(3)].
T = p(1, q(3)) ;
No
?- 1 =.. X.
X = [1] ;
No
?- [1,2,3] =.. X.
X = [., 1, [2, 3]] ;
No
230
:-
10.1.1 functor/3
Because univ builds a list that is typically not needed, it is
often better to use the separate builtin predicates
functor/3 and arg/3
functor(Term,Name,Arity) holds when the functor of Term is
Name and its arity is Arity
For atomic terms, the whole term is considered to be the
Name, and Arity is 0
Either the Term or both the Name and Arity must be bound,
otherwise functor throws an exception
231
:-
10.1.2 functor/3 in Action
?- functor(p(1,q(3)), F, A).
F = p
A = 2 ;
No
?- functor(T, p, 2).
T = p(_G280, _G281) ;
No
?- functor(1, F, A).
F = 1
A = 0 ;
No
?- functor(X, 42, 0).
X = 42 ;
No
232
:-
10.1.3 arg/3
arg/3 can be used to access the arguments of a term one
at a time
arg(N,Term,Arg) holds if Arg is the N
th
argument of Term
(counting from 1)
Term must be bound to a compound term
For most Prolog systems, N must be bound; SWI Prolog
will backtrack over all arguments of term
arg/3 is deterministic when rst two arguments are bound
233
:-
10.1.4 arg/3 in Action
?- arg(2, foo(a,b), Arg).
Arg = b ;
No
?- arg(N, foo(a,b), Arg).
N = 1
Arg = a ;
N = 2
Arg = b ;
No
?- arg(N, 3, 3).
ERROR: arg/3: Type error: compound expected, found 3
234
:-
10.1.5 Using functor and arg
Collect a list of all the functors appearing anywhere in a
ground term:
all_functors(Term, List) :- all_functors(Term, List, []).
all_functors(Term, List, List0) :-
functor(Term, Name, Arity),
( Arity > 0 ->
List = [Name|List1],
all_functors1(Arity, Term, List1, List0)
; List = List0
).
all_functors1(N, Term, List, List0) :-
( N =:= 0 ->
List = List0
; arg(N, Term, Arg),
all_functors(Arg, List1, List0),
N1 is N - 1,
all_functors1(N1, Term, List, List1)
).
235
:-
Using functor and arg (2)
?- all_functors(foo(bar([1,2],zip,baz(3)),bar(7)), L).
L = [foo, bar, ., ., baz, bar] ;
No
?- X=bar(42), all_functors(foo(X), L).
X = bar(42)
L = [foo, bar] ;
No
?- all_functors(foo(X), L), X=bar(42).
ERROR: Arguments are not sufficiently instantiated
Exception: (11) functor(_G342, _G448, _G449) ? creep
Since Name and Arity are not bound when functor/3 is
called, that goal causes an error if Term is not bound.
236
:-
10.2 Sorting
Our all_functors/2 predicate returns a list of functors
appearing, once for each time they appear
May want to produce a set, with each functor appearing
only once
Easiest way: produce the list and sort it, removing
duplicates
Built-in sort(List,Sorted) predicate holds when Sorted is a
sorted version of List, with duplicates removed
all_functors(Term, List) :-
all_functors(Term, List0, []),
sort(List0, List).
237
:-
10.2.1 keysort/2
keysort(List, Sorted) is like sort, except:
elements of List must be terms of the form Key-Value
only the Key parts of the terms are considered when
sorting
duplicates are not removed, keysort is a stable sort
?- sort([a,a,r,d,v,a,r,k], L).
L = [a, d, k, r, v] ;
No
?- keysort([a,a,r,d,v,a,r,k], L).
No
?- keysort([a-1,a-2,r-3,d-4,v-5,a-6,r-7,k-8], L).
L = [a-1, a-2, a-6, d-4, k-8, r-3, r-7, v-5] ;
No
238
:-
10.3 Term Comparison
The sorting predicates work on lists of any kinds of terms
Built on general term comparison predicates
The predicates @<, @=<, @>, @>=, == \== work like <, =<, >, >=,
=:= =\=, but they work on any terms
Atoms are compared lexicographically, numbers numerically
Compound terms are compared rst by arity, then by
functor, then by the arguments in order
Variables @< numbers @< atoms @< compound terms
Beware variables in terms being sorted!
== and \== check whether terms are identical without
binding any variables
239
:-
Exercise
Why should you beware variables in terms being sorted?
What could happen if you sort a non-ground list?
240
:-
10.4 Variable and Type Testing
Earlier we saw that the simple denition of rev used in the
backwards mode goes into an innite loop after nding
the correct answer
rev([], []).
rev([A|BC], R) :-
rev(BC, CB),
append(CB, [A], R).
Recursive call to rev produces longer and longer reversed
lists; once it has found the right length, no other length
will be correct
241
:-
10.4.1 Variable Testing Example
Can x this by exchanging the calls in the clause body
rev([], []).
rev([A|BC], R) :-
append(CB, [A], R),
rev(BC, CB).
In this order, when R is bound, the call to append/3 has
only one solution, so it solves the problem
But now rev/2 gets in trouble in the forwards mode
Once it nds the solution, asking for more solutions enters
an innite loop
242
:-
10.4.2 Variable Testing
To implement a reversible version of rev/2, we need to
decide which order to execute the goals based on which
arguments are bound.
Prolog has a built in predicate var/1 which succeeds if its
argument is an unbound variable, and fails if not.
?- var(_).
Yes
?- var(a).
No
243
:-
Exercise
Use the var builtin to implement a version of rev that will
work in any mode. Recall that only this version of rev:
rev([], []).
rev([A[BC], R) :- rev(BC, CB), append(CB, [A], R).
works when the second argument is unbound; otherwise
the goals in the body should be swapped
244
:-
10.4.3 Whats Wrong With var/1?
One of the most basic rules of logic is that conjunction is
commutative
p, q should behave exactly the same way as q, p (if they
terminate without error).
var/1 breaks that rule:
?- var(X), X = a.
X = a ;
No
?- X = a, var(X).
No
245
:-
10.4.4 When to use var/1
Irony: sometimes we can only write logical, reversible
predicates by using an extralogical predicate such as var/1
But we must be careful
For rev/2, the code is logically equivalent whether the
var/1 goal succeeds or fails; the only dierence is the order
of the goals
Sometimes we must have other dierence, such as having
X is Y + 1,
when Y is bound, and
Y is X - 1,
when X is.
A better answer for this is constraint programming
X = Y + 1
246
:-
10.4.5 Other Non-logical Builtins
All of the following have the same problem of potentially
making conjunction not commutative
nonvar(X) X is bound.
ground(X) X is bound, and every variable in the term it is
bound to is also ground.
atom(X) X is bound to an atom.
integer(X) X is bound to an integer.
float(X) X is bound to a oat.
number(X) X is bound to a number.
atomic(X) atom(X) ; number(X).
compound(X) X is bound to a compound term.
247
:-
10.4.6 Dening length/2
We can dene length/2 to work when the list is supplied:
len1([], 0).
len1([_|L], N) :-
len1(L, N1),
N is N1 + 1.
and when the length is supplied:
len2([], 0).
len2([_|L], N) :-
N > 0,
N1 is N - 1,
len2(L, N1).
248
:-
Dening length/2 (2)
A version that works in both modes:
len(L,N) :-
( var(N) ->
len1(L,N)
; len2(L,N)
).
NB: dont check if L is var: even if its not, its tail may be!
249
:-
Dening length/2 (3)
?- len(L, 4).
L = [_G242, _G248, _G254, _G260] ;
No
?- len([a,b,c], N).
N = 3 ;
No
?- len(L, N).
L = []
N = 0 ;
L = [_G257]
N = 1 ;
L = [_G257, _G260]
N = 2
Yes
250
251
252
:-
11 Metaprogramming
Prolog has powerful facilities for manipulating and
generating Prolog programs
1. Higher order programming
2. Interpreters
3. Prolog Interpreter
4. Generating Prolog code
253
:-
11.1 Higher order programming
One powerful feature of functional languages is
higher order programming: passing functions or
predicates as arguments
Prolog supports this, too
The built-in predicate call/1 takes a term as argument
and executes it as a goal
?- Goal = append([a,b,c],X,[a,b,c,d,e]),
| call(Goal).
Goal = append([a, b, c], [d, e], [a, b, c, d, e])
X = [d, e] ;
No
We can use any code we like to build goal term
254
:-
11.1.1 call/n
Some Prolog systems, including SWI, also support call of
higher arities
First argument is goal to execute
Extra arguments are given as arguments to the goal
?- Goal = append,
| call(Goal, [a,b,c], X, [a,b,c,d,e]).
Goal = append
X = [d, e] ;
No
Saves the eort of constructing the goal as a term before
calling it
255
:-
11.1.2 Closures
When the goal argument of call/n is a compound term,
later arguments of call are added to the goal
?- Goal = append([a,b,c]),
| call(Goal, X, [a,b,c,d,e]).
Goal = append([a, b, c])
X = [d, e] ;
No
The Goal in this case is a predicate with some, but not all,
of its arguments supplied; other arguments are given when
it is called
This is a closure
256
:-
11.1.3 map/3
Using call/n it is easy to implement the standard higher
order operations of functional languages, e.g.
map(_, [], []).
map(P, [X|Xs], [Y|Ys]) :-
call(P, X, Y),
map(P, Xs, Ys).
?- map(append([a,b]), [[c,d],[e,f,g],[h]], L).
L = [[a, b, c, d], [a, b, e, f, g], [a, b, h]] ;
No
?- map(append([a,b]), L,
[[a,b,c,d],[a,b,c],[a,b,w,x,y],[a,b]]).
L = [[c, d], [c], [w, x, y], []] ;
No
257
:-
Exercise: all/2
Write a predicate all/2 such that all(Pred,L) holds when
every element of L satises Pred. For example,
all(member(c), [[a,b,c],[a,e,i],[a,c]]]
fails, and
all(member(X), [[a,b,c],[a,e,i],[a,c]])
succeeds with X=a.
258
:-
11.2 Interpreters
Some programming problems are best solved by
dening a new minilanguage, a small language
targeted at one specic task
Consider the control of a robot vacuum cleaner
Programming this would be rather complex, involving
separate control of several motors, receiving input from
several sensors, etc.
This task would be far simpler to handle if we dened a
minilanguage for robot control, and then implemented an
interpreter for this language
259
:-
11.2.1 Robot Minilanguage
At the simplest level, we can consider primitive commands
to turn and move forward
These could be represented as Prolog terms:
advance(Distance)
left
right
260
:-
11.2.2 Interpreter Design
An interpreter (simulator) for this language would track
the robots position
Also needs to keep track of the robots heading,
represented as X and Y components, called H
x
and H
y
H
x
= 0
H
y
= 1
H
x
= 1
H
y
= 0
H
x
= 0
H
y
= 1
H
x
= 1
H
y
= 0
H
x
and H
y
are either -1, 0, or 1, and [H
x
[ +[H
y
[ = 1
On moving d units, x = dH
x
and y = dH
y
To turn clockwise (right): H
x
= H
y
, H
y
= H
x
,
anticlockwise (left): H
x
= H
y
, H
y
= H
x
261
:-
11.2.3 Interpreter
% sim(Cmd, X0, Y0, Hx0, Hy0, X, Y, Hx, Hy)
% Robot starts at position X0, Y0, with
% Heading Hx0, Hy0. After command Cmd,
% robot is at position X, Y, with heading
% Hx, Hy
sim(advance(Dist), X0, Y0, Hx, Hy, X, Y, Hx, Hy) :-
X is X0 + Hx * Dist,
Y is Y0 + Hy * Dist.
sim(right, X, Y, Hx0, Hy0, X, Y, Hx, Hy) :-
Hx = Hy0,
Hy is -Hx0.
sim(left, X, Y, Hx0, Hy0, X, Y, Hx, Hy) :-
Hx is -Hy0,
Hy = Hx0.
262
:-
11.2.4 Robot Programs
Construct a robot program as a list of commands:
sim([], X, Y, Hx, Hy, X, Y, Hx, Hy).
sim([C|Cs], X0, Y0, Hx0, Hy0, X, Y, Hx, Hy) :-
sim(C, X0, Y0, Hx0, Hy0, X1, Y1, Hx1, Hy1),
sim(Cs, X1, Y1, Hx1, Hy1, X, Y, Hx, Hy).
263
:-
11.2.5 Walls
The interpreter is simple, so it is easy to extend
Add walls to the room the robot operates in by preventing
X and Y from being less than 0 or more than room width
or height
Just need to replace one sim/9 clause and dene room
width and height
sim(advance(Dist), X0, Y0, Hx, Hy, X, Y, Hx, Hy) :-
room_width(Width),
room_height(Height),
X is max(0, min(Width, X0 + Hx * Dist)),
Y is max(0, min(Height, Y0 + Hy * Dist)).
room_width(400).
room_height(300).
264
:-
11.2.6 Other Possible Extensions
Keep track of minimum and maximum x and y
positions visited, by adding 8 more arguments for
previous and new min and max x and y
Allow robot to turn at angles other than 90
, by
adding a turn(Angle) command that uses trigonometry
to determine new real number H
x
and H
y
Add obstacles to room by dening predicate obstacle
that supplies shapes and positions of each obstacle,
and having advance command nd position of rst
obstacle encountered
265
:-
11.3 Prolog meta-interpreter
We can write an interpreter for any language we can
conceive, including Prolog itself
This is made much easier by the fact that Prolog goals are
ordinary Prolog terms
An interpreter for a language written in the language
itself is called a meta-interpreter
Prolog systems have a built-in interpreter invoked by the
call built-in predicates
Need access to the clauses of the program to be
interpreted; built-in predicate clause(Head,Body) gives this
Body is true for unit clauses
Generally you need to declare predicates dynamic:
:- dynamic foo/3.
266
:-
11.3.1 Simple meta-interpreter
% solve(Goal)
% interpret Goal, binding variables
% as needed.
solve(true).
solve((G1,G2)) :-
solve(G1),
solve(G2).
solve(Goal) :-
clause(Goal, Body),
solve(Body).
267
:-
Simple meta-interpreter (2)
Extend this to handle disjunction, if->then;else, negation:
solve((G1;G2)) :-
( G1 = (G1a->G1b) ->
( solve(G1a) ->
solve(G1b)
; solve(G2)
)
; solve(G1)
; solve(G2)
).
solve(\+(G)) :-
\+ solve(G).
268
:-
Simple meta-interpreter (3)
To handle Prolog builtins, modify the last clause on
slide 267:
solve(Goal) :-
( builtin(Goal) ->
call(Goal)
; clause(Goal, Body),
solve(Body)
).
builtin(_ = _).
builtin(_ is _).
builtin(append(_,_,_)).
.
.
.
269
:-
11.3.2 Extensions
Can modify interpreter to construct a proof
proof(Goal, Proof) :- proof1(Goal, Proof, []).
proof1(true, Proof, Proof).
proof1((G1,G2), Proof, Proof0) :-
proof1(G1, Proof, Proof1),
proof1(G2, Proof1, Proof0).
proof1(Goal, Proof, Proof0) :-
clause(Goal, Body),
proof1(Body, Proof,
[(Goal:-Body)|Proof0]).
.
.
.
Lots of other extensions, e.g. debuggers, other search
strategies
270
:-
11.4 Manipulating Prolog code
The fact that Prolog code is just a Prolog term also makes
it very easy to manipulate
To take advantage of this, the Prolog compiler
automatically calls a predicate term_expansion/2 (if it is
dened) for each term it reads
First argument of term_expansion/2 is a term Prolog read
from a source le; term_expansion/2 should bind the second
to a clause or list of clauses to use in place of what was
read
This is the same mechanism used to convert DCG clauses
into ordinary Prolog clauses
This feature allows programmers to easily write Prolog
code to generate or transform Prolog code
271
:-
11.4.1 Generating Accessor Predicates
Example: automatically generating accessor predicates
Suppose a student is represented as student(Name,Id) in a
large program
Everywhere the name is needed, the code might contain
Student = student(Name,_)
If we later need to also store degree code in student terms,
we must modify every student/2 term in the program
Programmers sometimes dene accessor predicates, e.g.:
student_name(student(Name, _), Name).
student_id(student(_, Id), Id).
then use student_name(Student, Name) instead of
Student = student(Name,_)
272
:-
Generating Accessor Predicates (2)
Using term_expansion, it is easy to write code to
automatically generate accessor predicates
We will transform a directive like
:- struct student(name,id).
into the clauses on the previous slide
:- op(1150, fx, (struct)).
term_expansion((:- struct Term), Clauses) :-
functor(Term, Name, Arity),
functor(Template, Name, Arity),
gen_clauses(Arity, Name, Term, Template, Clauses).
First line tells Prolog that struct is a prex operator
273
:-
Generating Accessor Predicates (3)
gen_clauses(N, Name, Term, Template, Clauses) :-
( N =:= 0 ->
Clauses = []
; arg(N, Term, Argname),
arg(N, Template, Arg),
atom_codes(Argname, Argcodes),
atom_codes(Name, Namecodes),
append(Namecodes, [0_|Argcodes], Codes),
atom_codes(Pred, Codes),
Clause =.. [Pred, Template, Arg],
Clauses = [Clause|Clauses1],
N1 is N - 1,
gen_clauses(N1, Name, Term, Template, Clauses1)
).
274
275
276
Q
12 Propositional Logic
introduce basic ideas of formal logic
dene truth tables for propositions
use of truth tables to establish tautologies,
equivalences
277
Q
Exercise: Knights and Knaves
On the island of Knights and Knaves, everyone is a knight
or knave. Knights always tell the truth. Knaves always lie.
You are a census taker, going from house to house. Fill in
what you know about each house.
house 1 Husband: We are both knaves.
house 2 Wife: At least one of us is a knave.
house 3 Husband: If I am a knight then so is my wife.
House 1 House 2 House 3
Husband Wife Husband Wife Husband Wife
278
Q
12.1 Logic and Reasoning
Logic is about reasoning
All humans have 2 legs
Jane is a human
Therefore Jane has 2 legs
key issue for (any) logic
FORM of an argument versus its MEANING
All dogs have 6 legs
Rex is a dog
Therefore Rex has 6 legs
279
Q
12.1.1 Arguments: Form and Meaning
form is determined by the syntax of the logic.
Both arguments above have correct form, HENCE
both arguments are (logically) correct.
truth depends on meaning relation to the world.
The rst argument has a true conclusion: its premises
are true and the argument is correct.
The second argument has a false conclusion: even
though the argument is correct, its premises are not
true.
280
Q
12.1.2 Propositions
A C this true
354
Q
15.2.1 Resolution Principle.
(Kelly Theorem 5.1, page 102)
If D is a resolvent of clauses C
1
and C
2
, then C
1
C
2
[= D
Proof by formalising the above key idea.
Another view: A B means A B
Remember: A B, B C [= A C
So if A B and B C, then A C must hold
355
Q
15.3 The Key to Refutations
A B
u
u
u
u
u
u
u
u
u
u
B C
s
s
s
s
s
s
s
s
s
s
both true
one false
A C this true
thisfalse
OO
if (A C) is false, then one of (A B) or (B C)
must be false.
(i.e. using the contrapositive of the observation before).
356
Q
15.3.1 Refutations
A B
u
u
u
u
u
u
u
u
u
u
B C
s
s
s
s
s
s
s
s
s
s
one false
A C
this false
OO
repeatedly cancel out B with B and seek (empty
clause).
if you reach , argue backwards to conclude the
starting formulae were inconsistent.
P . . .
h
h
h
h
h
h
h
h
Q. . . P . . .
u
u
u
u
u
u
u
u
u
u
u
u
u
u
u
u
u
u
u
Q. . .
x
x
x
x
x
x
x
x
P
t
t
t
t
t
t
t
t
t
t
P
s
s
s
s
s
s
s
s
s
s
357
Q
15.3.2 Deductions and Refutations (Kelly page
105)
A resolution deduction of clause C from a set S of
clauses is a sequence C
1
, C
2
, . . . , C
n
of clauses such that
C
n
= C and for each i, 1 i n,
C
i
is a member of S, or
C
i
is obtained, by resolution from C
j
and C
k
,
j, k i.
A resolution refutation of a set S of clauses is a
resolution deduction of from S.
358
Q
15.3.3 Resolution Theorem
Given a clause set S, R(S) is the set of all clauses derivable
from S by one resolution step
R
(S)
Proof. By induction, using the Resolution Principle.
359
Q
15.4 Establishing Validity With
Resolution
Algorithm for establishing formula A is valid
put A in conjunctive normal form
take set of conjuncts and apply resolution
repeatedly
if eventually you get then A unsatisable (so A
is valid); otherwise A is not valid
How can you be sure that this procedure terminates?
360
Q
15.5 Set Representation of Clauses
1 L W a L W
2 W b W
3 L 1,2 c L a,b
4 G W d H L
5 G 2,4 e H c,d
6 S G
7 S 5,6
365
Q
Exercise
Use resolution to show
||A, B, C, |A, |A, B, C, |A, B
is unsatisable. Show a resolution diagram.
366
Q
15.6.2 Important Results
Theorem. (Soundness of resolution)
If there is a resolution refutation of S, then S is
unsatisable.
Proof: straightforward induction.
Theorem. (Completeness of resolution)
If S is unsatisable, there is a resolution refutation of
S.
Proof: delicate induction, using the compactness
theorem to reduce the problem to a nite one.
367
Q
15.7 Summary: Propositional Logic so
Far
syntax: the shape of legal formulae
semantics: dened using truth tables. A valid i A
unsatisable
proof denitions - axioms, inference rules
notation
A B B is deducible from A
A [= B B is semantically entailed by A
techniques
truth tables
axioms and inference
resolution
key results: A i [= A i there is a resolution refutation of
A
368
Q
15.7.1 Discussion
Any problem that involves deciding amongst a nite
number of choices can be expressed in propositional
satisability.
resolution implementable easily, but no polynomial
time algorithm known (for this or any of the other
techniques)
the satisability problem (SAT) for propositional logic
is typical of a large class of dicult problems
so-called NP-complete problems for which there are
no known ecient algorithms.
however, by limiting expression to restricted forms of
formulae, resolution can lead to a practical
programming language Prolog
369
370
371
372
Q
16 Linear Resolution
present linear resolution a more ecient form of
resolution
show connections between linear (input) resolution and
Prolog
Introduce negation as failure
373
Q
Linear Resolution (2)
Linear resolution is a renement of resolution (restricts
the search space).
|A
g
g
g
g
g
g
g
g
g
g
|C, B
m
m
m
|B
|B
i
i
i
i
i
i
i
versus
Linear Resolution
|A, B |A
l
l
l
l
l
l
|B |C, B
l
l
l
l
|C |C
k
k
k
k
k
k
k
376
Q
16.1 Horn clauses and Prolog
conjunctive normal form = conjunction of clauses
clause |L
1
, . . . , L
n
represents
(A
1
A
2
A
m
B
1
B
k
) [n = m+k]
which, using DeMorgans laws, can be written
B
1
B
k
A
1
A
2
A
m
: B
1
, . . . , B
j
, . . . , B
k
t
t
t
t
t
t
t
t
t
head neck
body
378
Q
16.2 Propositional Logic Programs
a propositional logic program P is a collection of facts
and rules; typically, we want to know if some other
fact(s) are a logical consequence of P
Example:
mg : mgo, h2. i.e. h2 mgo mg
h20 : mgo, h2. h2 mgo h20
co2 : c, o2. c o2 co2
h2co3 : co2, h2o. co2 h2o h2co3
mgo. mgo
h2. h2
o2. o2
c. c
given these facts and rules, can you prove h2co3 is
generated?
379
Q
16.2.1 Clausal Form of Logic Program
A1 h2 mgo mg h2 mgo mg
A2 h2 mgo h20 h2 mg0 h20
A3 c o2 co2 ?
A4 co2 h2o h2co3 ?
A5 mgo mgo
A6 h2 h2
A7 o2 o2
A8 c c
A9 h2co3 h2co3
380
Q
16.2.2 Propositional Logic Programs and
Resolution
given a propositional logic program P to know if some
other fact(s) are a logical consequence of P
add the conjunction of the facts as the goal clause G
: h2co3
and, using resolution, show that P |G is unsatisable
remember, in clausal form : h2co3 is h2co3
i.e. adding the goal is just adding the negation of the
query
381
Q
16.3 Linear Input Resolution
i
is the
interpretation of t
i
under U and , and (t
1
, , t
n
) P
U
.
ex: Q(y, z) is true under U and since (2, 4) Q
U
.
ex: P(f(c), x) is not true under U and since
(7, 7) , P
U
.
425
x
18.1.3 Relation to Propositional Logic
Predicate logic has interpretations and valuations
Propositional logic just had assignments
Can think of a proposition as a niladic (0-arity)
predicate
Then an interpretation lls the role of an assignment
With no arguments, no terms and no variables
With no variables, no need for quantiers or valuations
426
x
18.2 Truth and Satisfaction
A formula A is satised by an interpretation U and some
valuation over that interpretation:
an atom is true or not according to the interpretation
U, after applying the valuation
connectives , , , , : as for Propositional Logic
xA: if for every value u in the domain of U, the
interpretation U and the valuation
= ( |x ) |x u satises A(x).
Alternatively A(u
1
) A(u
2
) A(u
N
) is satised
xA: if for some value u in the domain of U, the
interpretation U and the valuation
= ( |x ) |x u satises A(x).
Alternatively A(u
1
) A(u
2
) A(u
N
) is satised
427
x
18.2.1 Truth, Satisability, Validity
A(x) B(x)
xQ(x)
1.
A(x) B(x)
xQ(x)
xQ(x) x
A(x) B(x)
2.
A(x) B(x)
xQ(x)
xQ(x) x
A(x) B(x)
3a.
A(x) B(x)
xQ(x)
x Q(x) x
A(x) B(x)
3b.
A(x) B(x)
xQ(x)
xQ(x) x
A(x) B(x)
4.
A( w ) B( w )
xQ(x)
y Q( y ) z
A( z ) B( z )
5a. wx
A(w) B(w)
Q(x)
yz
Q(y)
A(z) B(z)
5b. wxyz
`
A(w) B(w)
Q(x)
6. wxyz
A(w) Q(x)
B(w) Q(x)
450
x
Exercise
Convert the following formula to prenex normal form:
x(P(x) ((yQ(x, y)) (yR(x, y))))
451
x
19.0.10 Skolemisation
Suggested by Thoralf Skolem
Aim: Get rid of quantiers
How: Introduce new constants and functions, not
already existing in the formula, to replace variables
corresponding to existentially quantied variables.
Result is the Skolemisation of the formula.
Denition:
outside : replace by new constant.
xyA(x, y) becomes yA(c, y).
inside : replace by new function with arguments
all variables in outside s.
yxzwA(x, y, z, w) B(y, w) becomes
yzA(f
1
(y), y, z, f
2
(y, z)) B(y, f
2
(y, z))
452
x
19.0.11 Intuition
If xyP(x, y) then there is some x that satises P(x, y)
for every y
But we dont know which x
So we make up a name: we create a new constant and
dene it to be some constant satisfying P
New constant will represent be the same thing as some
old constant, but thats OK
E.g., P(x, y) means y = x +y
Convert to yP(c, y)
c happens to be 0, but we dont need to know that
453
x
Intuition (2)
If yxP(x, y) then for each y there is some x that
satises P(x, y)
Now the x that satises P(x, y) depends on y: its a
function of y
So now we make up a function: for any y, we say that
f(y) satises P(f(y), y)
E.g., P(x, y) means x > y
convert to yP(f(y), y)
f(x) could be x + 1, but we dont care
454
x
19.0.12 Important Result
Theorem. Let A be a formula and A
its Skolemisation.
Then A is satisable i A
is satisable.
A and A
not occurring in A.
So the Skolemised formula (no quantiers) can be
used in resolution.
Prolog clauses do not allow existentially quantied
variables, so there is no Skolemisation to be done!
(Fortunate, since we generally dont want two distinct
constants representing the same thing in Prolog)
455
x
19.0.13 Clausal Form
To nd the clausal form of a formula:
1. Convert to Prenex normal form and then Skolemise.
2. Drop all quantiers.
3. Convert to clausal form as for Propositional Logic.
Once in Prenex normal form, all variables are
universally quantied and at the front of each clause
Order of same quantiers is unimportant
Drop them, then consider all variables implicitly
universally quantied
Simplies resolution algorithm
456
x
Exercise
Skolemize the following formula, then put it into clausal
form:
yx(P(y) Q(x, y))
457
x
An Example
Use resolution to prove that the following argument is valid.
All hungry animals are caterpillars.
All caterpillars have 42 legs.
Edward is a hungry caterpillar.
Therefore, Edward has 42 legs.
Translation to Logic:
x(H(x) C(x)) H(Edward) C(Edward)
x(C(x) L(x)) L(Edward)
458
x
Prenex Normal Form
x(H(x) C(x)) H(Edward) C(Edward)
x(C(x) L(x)) L(Edward)
Negate conclusion and convert to Prenex Normal Form:
x(H(x) C(x)) H(Edward)
x(C(x) L(x)) C(Edward)
L(Edward)
459
x
Clausal form
x(H(x) C(x)) H(Edward)
x(C(x) L(x)) C(Edward)
L(Edward)
Set of sets representation:
460
x
Resolution Refutation
8
>
>
<
>
>
:
{H(x), C(x)}, {H(Edward)},
{C(x), L(x)}, {C(Edward)},
{L(Edward)}
9
>
>
=
>
>
;
~C(x), L(x) ~L(Ed) C(Ed)
~C(Ed)
L
1
and L
2
are uniable if there exists a unier for L
1
and L
2
465
x
Unication (2)
1
and
L
2
, . . . ,
n1
unies L
1
1
n2
and L
n
. The unier
of S is
1
n1
.
Lemma. If a set S is uniable, then it has a most
general unier.
Lemma. A most general unier for a set S (if it
exists) is unique up to renaming of variables.
466
x
20.2.1 Examples
|P(x, a), P(b, c) is not uniable
|P(f(x), y), P(a, w) is not uniable.
|P(x, c), P(b, c) is uniable by |b/x.
|P(f(x), y), P(f(a), w) is uniable by = |a/x, w/y,
= |a/x, a/y, a/w, = |a/x, b/y, b/w
Note that is an m.g.u. and = where =
|P(x), P(f(x)) is not uniable. (c.f. occur check!)
467
x
20.2.2 Unication Algorithm
1. T
1
= L
1
; T
2
= L
2
;
0
= |; i = 0
2. If T
1
is identical to T
2
, terminate with
i
as the most
general unier.
3. Find the leftmost position where T
1
and T
2
dier. If
the two terms at this position are a variable v
i
and a
term t
i
such that v
i
does not occur in t
i
(the occurs
check), then
i+1
=
i
|t
i
/v
i
; T
1
= T
1
|t
i
/v
i
; T
2
= T
2
|t
i
/v
i
1
= |h(y)/x
T
1
= f(h(y), g(h(y))) T
2
= f(h(y), g(h(z)))
2
= |h(y)/x, y/z
T
1
= f(h(y), g(h(y))) T
2
= f(h(y), g(h(y)))
i.e.
2
is an m.g.u.
469
x
20.2.3 Results on Unication
Theorem. The unication algorithm is correct.
Remark. The occur check can be exponential in the
size of the original terms, so Prolog simply omits this
part of the algorithm.
Question. What does this mean for Prologs
correctness?
Question. What happens when you type the following
queries to Prolog?
?- X = f(X).
?- X = f(X), Y = f(Y), X=Y.
470
x
Exercise
Find the most general unier of the following pairs of
terms, if possible. (a, b are constants, x, y, z are variables.)
1. f(x, y, f(x, y)) f(b, z, z)
2. f(f(x, y), y) f(z, g(a))
471
x
20.3 Resolvents
Recall: For Propositional Logic:
Two literals are complementary if one is L and the
other is L.
The resolvent of two clauses containing
complementary literals L, L is their union
omitting L and L.
For Predicate Logic:
Two literals L and L
is uniable.
Let be an m.g.u. of complementary literals
|L, L
with L a literal in C
1
and L
a literal in C
2
.
Then the resolvent of C
1
and C
2
is the union of
C
1
and C
2
omitting L and L
.
472
x
20.4 Resolution Theorems
Resolution Principle
If D is a resolvent of clauses C
1
and C
2
, then C
1
C
2
[= D.
Resolution Theorem
A clause set S is unsatisable i R
(S), where R
(S) is
the set of all clauses obtainable after a nite number of
resolution steps, starting with S.
473
x
20.4.1 Example: The Miserable Tadpole
every shark eats a tadpole
x(S(x) y(T(y) E(x, y))) |S(x), T(f(x)), |S(x), E(x, f(x))
all large white sh are sharks
x(W(x) S(x)) |W(x), S(x)
colin is a large white sh living in deep water
W(colin) D(colin) |W(colin), |D(colin)
any tadpole eaten by a deep water sh is miserable
z(T(z) y(D(y) E(y, z) M(z)) |T(z), D(y), E(y, z), M(z)
negation of: some tadpoles are miserable
z(T(z) M(z)) |T(z), M(z)
474
x
20.4.2 Refutation
C1 S(x), T(f(x)) C2 S(x), E(x, f(x))
C3 W(x), S(x) C4 W(c)
C5 D(c) C6 T(z), D(y), E(y, z), M(z)
C7 T(z), M(z)
C8 S(c) C4, C3 |c/x
C9 T(f(c)) C8, C1 |c/x
C10 E(c, f(c)) C8, C2 |c/x
C11 D(y), E(y, f(c)), M(f(c)) C9, C6 |f(c)/z
C12 D(c), M(f(c)) C10, C11 |c/y
C13 M(f(c)) C5, C12
C14 T(f(c)) C7, C13 |f(c)/z
C15 C9, C14
So there is a miserable tadpole the one eaten by colin.
475
x
20.5 Horn Clauses and Prolog
Horn clause = clause with at most one positive literal.
e.g. |p(x), q(x, y), r(x, y)
represents p(x) q(x, y) r(x, y)
rewritten as p(x) (q(x, y) r(x, y))
rewritten as p(x) (q(x, y) r(x, y))
or, in Prolog notation p(X) :- q(X, Y), r(X, Y).
SLD-resolution is Robinsons approach restricted to
linear input resolution.
476
x
20.5.1 Example
Suppose C is the clause set
||q(x), p(x), s(x), |p(x), r(x), |r(a), |r(b), |s(b)
Does C [= q(b)?
check for unsatisability of C |q(b), i.e.
1. |q(x), p(x), s(x)
2. |p(x), r(x)
3. |r(a)
4. |r(b)
5. |s(b)
6. |q(b)
and (in a few steps of linear resolution) you derive
477
x
20.5.2 Linear Resolution Diagram
Example, continued using linear input resolution.
q(b) q(x), p(x), s(x)
p
p
p
p
p
p
p
p
p
p
p
s(b)
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
r
p(x), r(x)
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
t
r(b)
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
v
p(b), s(b)
p(b)
r(b)
478
x
Exercise
Draw a resolution diagram refuting this set of clauses:
|P(a, b) |P(x, y), Q(x, y) |P(x, y), Q(y, x) |Q(b, a)
479
x
20.5.3 (Abstract) Interpreter for Prolog
Input: A query Q and a logic program P
Output: yes if Q implied by P, no otherwise
Initialise current goal set to Q;
While the current goal is not empty do
Choose G from the current goal;
Choose instance of a rule G
:- B
1
, . . . , B
n
from P;
renaming all variables to new symbols giving G
:- B
1
, . . . , B
such that G and G
1
, . . . , B
n
in current goal set;
If current goal set is empty,
output yes;
else output no;
480
x
20.5.4 Prolog in Prolog
A basic Prolog interpreter in Prolog:
solve(true).
solve((G1,G2)) :-
solve(G1),
solve(G2).
solve(Goal) :-
clause(Goal, Body),
solve(Body).
Needs to be expanded to support built-ins, disjunction,
if-then-else, etc.
NB: Prolog takes care of backtracking and creating copies
of clauses with fresh variables for us!
481
x
20.5.5 SLD tree
q(b)
I
I
I
I
I
I
I
|b/x
1
p(b), s(b)
{
{
{
{
{
{
{
{
Y
Y
Y
Y
Y
Y
Y
Y
G
G
G
G
G
G
G
|b/x
2
r(b), s(b)
{
{
{
{
{
s
s
s
s
s
s
s
s(b)
P
()
494
x
Example
Take program P = |num(0), num(s(N)) : num(N)
T
1
P
() = |num(0)
(because body of clause is empty)
T
2
P
() = |num(0), num(s(0))
T
3
P
() = |num(0), num(s(0)), num(s(s(0)))
T
P
() =
|num(0), num(s(0)), num(s(s(0))), num(s(s(s(0)))), . . .
Meaning of most programs is innite
495
x
Exercise
Give the semantics of the following Prolog program:
p(a,b).
p(b,c).
p(c,d).
q(X,Y) :- p(X,Y).
q(X,Y) :- p(Y,X).
496
x
21.4 Why Study Semantics?
Programming (thinking about your code)
Verication (is it correct)
Debugging (the answer is wrong, but why)
Implementation
Language design
Philosophy
Hundreds of papers have been written on the semantics of
logic programs, many concerning negation
497
x
21.4.1 Verication and Debugging
Suppose each clause/predicate of a program is true
according to my intended interpretation
Then everything computed by the program (the meaning,
the set of logical consequences) is true
Correctness can be veried just by reasoning about
individual components
If the program computes something false, one of
clauses/predicates must be false
Declarative debugging systems use the intended
interpretation to nd which one
498
x
21.5 Approximating Meaning
Can also approximate meaning of a program: gives some
information about the program
Approximation can be made nite: can actually be
computed
Usual approach: replace data in program by an abstraction,
then compute meaning
Many interesting program properties are Boolean: use
propositional logic
E.g., parity (even/odd): abstract 0 by true
Abstract s(X) by x
499
x
Approximating Meaning (2)
Abstracted num predicate:
num(true)
num(x) num(x)
num(0)
num(s(X)) num(X)
T
1
P
() = |num(true)
T
2
P
() = |num(true), num(false)
T
3
P
() = |num(true), num(false)
Can stop here: further repetitions will not add anything
Result is nite
Says that both even and odd numbers satisfy num/1
500
x
Approximating Meaning (3)
Program:
plus(0, Y, Y).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).
Abstracted version:
plus(true, y, y) y can be either true or false
plus(x, y, z) plus(x, y, z)
T
1
P
() = |plus(true, true, true), plus(true, false, false)
T
2
P
() =
T
3
P
() =
501
x
Approximating Meaning (4)
This result is better shown as a table:
+ even odd
even even odd
odd odd even
Even such a simple analysis is able to discover interesting
properties of programs
502
x
Exercise
Use parity analysis to determine the possible parities of the
arguments of p/1 dened as:
p(0,s(0)).
p(s(X), s(s(Y))) :- p(X, Y).
503
x
21.6 Groundness Analysis
A more useful property for optimization of Prolog code is
groundness
Again, a Boolean property
append([], Y, Y).
append([U|X], Y, [U|Z]) :- append(X, Y, Z).
Abstracted version:
append(true, y, y)
append(u x, y, u z) append(x, y, z)
In second clause, u can be true or false, so:
append(true, y, y)
append(x, y, z) append(x, y, z)
append(false, y, false) append(x, y, z)
504
x
Groundness Analysis (2)
append(true, y, y)
append(x, y, z) append(x, y, z)
append(false, y, false) append(x, y, z)
T
1
P
() = |append(true, true, true), append(true, false, false)
T
2
P
() =
T
2
P
() =
505
x
Groundness Analysis (3)
A truth table will help us understand this:
x y z append(x, y, z) T
P
()
true true true true
true true false false
true false true false
true false false true
false true true false
false true false true
false false true false
false false false true
We see when append(x, y, z) is true, (x y) z
506
x
Groundness Analysis (4)
So after a call append(X,Y,Z), X and Y will be ground i Z is
We can use this result in analyzing predicates that call
append
rev([], []).
rev([U|X], Y) :-
rev(X, Z),
append(Z, [U], Y).
Abstracted version:
rev(true, true)
rev(u x, y) (rev(x, z) append(z, u, y))
507
x
Groundness Analysis (5)
Using what weve learned about append:
rev(true, true)
rev(u x, y) (rev(x, z) ((z u) y))
Since u can be either true or false:
rev(true, true)
rev(x, y) (rev(x, z) (z y))
rev(false, y) (rev(x, z) (false y))
Simplifying biimplications:
rev(true, true)
rev(x, y) rev(x, y)
rev(false, false) rev(x, z)
508
x
Groundness Analysis (6)
rev(true, true)
rev(x, y) rev(x, y)
rev(false, false) rev(x, z)
T
1
P
() = |rev(true, true)
T
2
P
() = |rev(true, true), rev(false, false)
T
3
P
() = |rev(true, true), rev(false, false)
509
x
Groundness Analysis (7)
So after rev(X,Y), X is ground i Y is: x y
This analysis gives quite precise results
Many other such abstractions have been proposed
This is an area of active research
510
22.1 Introduction
There are many programming languages, many
programming paradigms
All have a few things in common; programs:
Are nite
Take input
Produce output
Make decisions based on current input and possibly
earlier input
To facilitate recalling information about earlier inputs,
most languages allow state of computation to be changed
512
22.2.2 Output
FSMs can produce output
0 50
100 150
touch/+f1
touch/f1,f2
touch/+f1
touch/f1,+f2
Here +f1 means that lament 1 should be turned on, f2
means lament 2 should be turned o, etc.
516
22.2.3 Example
This FSM copies its input of binary numbers to its output,
stripping leading 0s:
q0 q1
1/1
0 1/1
0/0
The transition from the initial state for 0 leaves it in that
state without any output
States capture the history of the computation
Think of state q0 as meaning no 1s seen yet and q1 as
some 1s seen
517
Exercise
What output does the following FSM produce with input
aabbaaabbb?
q2
q0 q1
b/b
b/b
b/b
a
a/a
a/a
More generally, describe what it does.
518
Exercise
Design an FSM to recognize strings containing an even
number of as. The input can include both as and bs.
523
22.4 Formally
What does it take to dene a FSM?
Q a set of states
a set of input symbols, called the alphabet
species the state transitions
q
0
the initial state
F the set of accepting states
(assuming we do not need output).
So an FSM is a 5-tuple:
/Q, , , q
0
, F)
524
22.4.1
State transition is specied by a function
Given any state and any input, yields the state to
transition into
: (Q) Q
Can specify as a table (as we did for Prolog
implementation):
state s input i (s, i)
q0 a q1
q0 b q4
q0 c q4
q1 a q4
.
.
.
.
.
.
.
.
.
525
22.5 NFAs
What if state transition were specied by a relation rather
than a function?
Q Q
When is a function, only one next state given current
state and input
When is a relation, may be more than one next state
Such a FSM is called a Nondeterministic Finite Automaton
or NFA
If is a function: Deterministic Finite Automaton or DFA
An NFA accepts an input string if some selection of the
state transitions specied by leads to an accepting state
526
22.5.1 transitions
NFAs also often allow transitions to be specied
A transition is a spontaneous transition a transition in
response to no input at all
Specify this formally by pretending the input alphabet
contains an extra symbol , and there can be as many s
as you like between any two real symbols
Then, formally becomes a relation
Q( |) Q
527
22.5.2 Example
This NFA accepts all input that is either some as optionally
followed by some bs or some bs optionally followed by some
as:
b a
q4 q3
a b
q2 q1
q0 q5
a
b
a
b
b
a
528
Example (2)
Important result: any NFA can be converted into an
equivalent DFA
Intuition: state in new DFA corresponds to set of states in
NFA
This is an equivalent DFA to the previous NFA:
b a
q4 q3
a b
q2 q1
q0 q5
a
b
b
a
a
b
a,b
529
22.6 Power
FSMs cannot do everything real programs can do
FSMs can recognize ab or aabb or aaabbb:
q0 q1 q2
a
a a
q3
q3 q4 q5
b b b
q5
b b
b
a,b
a
a
a
a,b
This regular structure can be extended to recognize a
n
b
n
for n up to any xed limit
But its not possible to build a FSM to recognize a
n
b
n
for
any n
530
531
532
533
534
23 Turing Machines
1. Turing Machines
2. Nondeterministic Turing Machines
535
, y, d]
Transitions have three parts:
Change the state to q
, y, d]
Remember is a partial function.
Output is the result remaining on the tape.
Machine halts abnormally if the head moves o the
left end of the tape.
540
xq
j
yB means result of any nite number of
steps
542
Exercise
Modify the even length palindrome machine to accept odd
length palindromes too e.g. 101
q0
0/0 R
1/1 R
q1
B/B R 0/B R
1/B R
0/0 R
1/1 R
q2
q3
q4
q5
B/B L
B/B L
0/B L
q6
0/0 L
1/1 L
1/B L
B/B R
547
Main Code
run(Input, Output, State) :-
initial(State0),
tape_list_position(Tape0, Input, 0),
run(State0, Tape0, State, Tape),
tape_list_position(Tape, Output, _).
recognize(Input) :-
run(Input, _, State),
accepting(State).
549
State Transition
run(State0, Tape0, State, Tape) :-
( step(State0, Tape0, State1, Tape1) ->
run(State1, Tape1, State, Tape)
; State = State0,
Tape = Tape0
).
step(State0, Tape0, State, Tape) :-
replace_tape_symbol(Tape0, Sym0, Tape1, Sym1),
delta(State0, Sym0, State, Sym1, Direction),
move_tape(Direction, Tape1, Tape).
550
Example
q0 q1
B/B R c/c R
c/c L
q2
q3
q4
q5
a/a R
b/b L
b/b R
q6
a/a L
a/a R
b/b R
c/c R
A machine which accepts strings of as, bs and cs where
there is a c followed by or preceded by ab.
553
Example (2)
Trace1 Trace2 Trace3
q
0
BacabB q
0
BacabB q
0
BacabB
Bq
1
acabB Bq
1
acabB Bq
1
acabB
Baq
1
cabB Baq
1
cabB Baq
1
cabB
Bacq
1
abB Bacq
2
abB Bq
3
acabB
Bacaq
1
bB Bacaq
4
bB
Bacabq
1
B Bacabq
6
B
First and third do not accept, but second does
Thats good enough: the machine accepts
554
555
556
557
558
24 Undecidability
Are there some programs that cannot be written?
How many kinds of innity are there?
559
Exercise
Suppose Prolog had a builtin predicate halt(Goal) that
succeeds if Goal would eventually terminate, and fails
otherwise. Write a Prolog predicate contra/0 that calls
halt/1 in such a way that halt/1 cannot possibly work.
567
24.4 Reducability
A decision problem P is (Turing) reducible to a
problem P
if:
there is a Turing machine M which maps input p to
p
such that p P i p
) where M
is a machine which:
takes a blank tape as input
writes s on tape
then executes machine M on tape
571
24.5 Countability
There are innitely many natural numbers |0, 1, 2, . . .
Are there more integers |. . . , 2, 1, 0, 1, 2, . . . than
natural numbers?
Two sets have the same cardinality (size) if we can
match each element of one set to a dierent element
of the other, and vice versa
A set that is either nite or has the same cardinality as
the natural numbers is countable
Are all sets countable?
573
24.5.1 Integers
The integers are countable:
0 1 2 3 4 5 6
321 0 2 3 1
Match nonnegative integers p with natural number 2p
Match negative integers n with natural number 2n 1
574
24.5.2 Rationals
Rational numbers are numbers that can be expressed
as n/d for integers n and d
The rational numbers are countable
All rationals appear in this:
0
4
3 2 1 1 2 3
4 4 4 4 4 4
0
3
3 2 1 1 2 3
3 3 3 3 3 3
0
2
3 2 1 1 2 3
2 2 2 2 2 2
0
1 1 1 1 1 1 1
3 2 1 1 2 3
Can match rationals with
naturals:
0
4
3 2 1 1 2 3
4 4 4 4 4 4
0
3
3 2 1 1 2 3
3 3 3 3 3 3
0
2
3 2 1 1 2 3
2 2 2 2 2 2
0
1 1 1 1 1 1 1
3 2 1 1 2 3
575
24.5.3 Reals
Real numbers include rationals and irrational numbers
Irrationals include e, ,
2, etc.
The real numbers are not countable
Proof by Georg Cantor (diagonal argument)
Assume reals are countable
Then reals between 0 and 1 are countable
576
Exercise
Is the set of integer intervals, e.g. from 1 to 10, or from 0
to 99, or from -78 to -42, countable? Why or why not?
578
579
580
581
582
25 Complexity
1. What is Complexity?
2. Rates of Growth
3. Tractable Problems
4. NP Problems
583
25.4.1 SAT
Example: propositional satisability
Given a set of propositional clauses, guess a valuation for
all the truth values. Evaluate F under this valuation. If true
answer yes! Given a propositional formula in clausal form
Nondeterministically guess a truth assignment for each
variable
Check whether it makes the clauses true
For each clause, is there a true literal in the clause
O(n) where n is the size of the formula
597
25.4.2 P and NP
A problem is in the class P if it is (deterministic)
polynomial time
A problem is in the class NP if it is non-deterministic
polynomial time
P NP
P = NP one of the most important problems in
Computer Science. Everyone believes that P ,= NP!
598
25.4.3 A problem in P
Solution of propositional horn clauses is O(n)
Algorithm
For each clause x x
0
, . . . x
n
set count = n
place all clauses with count 0 in queue
Remove rst from queue, set lhs to true
Subtract 1 from the count of all clauses that
contain lhs
Add new clauses with count 0 to queue.
continue until queue empty
599
25.4.6 NP completeness
Thousands of problems have been shown to be NP
complete!
edge cover, Hamiltonian path, graph coloring
scheduling, rostering, register allocation
Constraint programming concentrates on solving just
these kind of problems
602
25.5 Summary
Church Turing thesis: eective procedures
Turing Machines
Halting problem is undecidable
Validity problem for predicate logic is semidecidable
Satisability/Validity problem for propositional logic
(SAT) is NP-complete
Tractable and Intractable problems
Solution of predicate Horn clauses is undecidable
Solution of propositional Horn clauses is O(n)
603
604
605
606
26 Review
Cannot cover the whole semester in one lecture, but well
try. . . .
1. Propositional Logic
2. Predicate Logic
3. Automata
607
26.1.2 Arguments
Argument is a sequence of propositions ending in a
conclusion, e.g.:
When interest rates rise, share prices fall.
Interest rates are rising. Therefore, share prices
will fall.
Conclusion is claimed to follow from premises
To check correctness, see if conjunction of premises imply
conclusion, e.g. ((R S) R) S
R S R S (R S) R ((R S) R) S
T T T T T
T F F F T
F T T F T
F F T F T
All rows of truth table are true, so argument is valid
611
26.1.5 Resolution
Clausal form: CNF written as set of sets
Complementary literals: e.g. A and A
Resolvent of 2 clauses with complementary literals is
union of 2 clauses with complementary literals removed
E.g. resolvent of |A, B, C and |A, B, D is
|A, C, D
Horn clause has at most 1 positive literal
616
Resolution (2)
Resolution
~B
~A, B
A, B ~A, ~B A, ~B
B
Resolve any 2
clauses
Linear Resolution
~A, B
A, B
B
A
A, ~B
~A, ~B
~B B
Resolve result of
last step with any
other clause
Linear Input
Resolution
~p, ~s
~r, ~s r
~s s
p, ~r
q, ~p, ~s ~q
Resolve result of
last step with
clause from
program
All are sound. All are complete, except L.I. Resolution:
complete only for Horn clauses
617
26.2.1 Quantiers
xF means F is true for every x in the domain of
discourse
xF means F is true for some x in the domain
xyF not the same as yxF
xyF is the same as yxF
xF not the same as xF
xF is the same as xF
Quantier applies to single immediately following
formula, e.g. in xP(x) Q(x), the quantier only
applies to P(x)
619
26.2.5 Resolution
Herbrand interpretation: interpretation mapping every
constant, function and predicate symbol to that
symbol (identity interpretation)
Herbrand Universe: set of all ground terms that can be
created from the function and constant symbols of the
program
Herbrand: Set of clauses is unsatisable i a nite
subset of ground instances is
Robinson: Resolution is sound and complete for
predicate logic
Resolution same as for propositional logic, except that
unication is used to match complementary literals
624
26.2.6 Unication
Substitution species terms to substitute for some
variables in a term or atom; other variables are left
unchanged
E.g., given substitution = |a/x, f(x)/y and term
T = g(x, y, z), T = g(a, f(x), z) (note new x not
replaced by a)
Simplied algorithm to unify a and b:
1. If a is a variable not appearing anywhere in b, add a
substitution b/a
2. If b is a variable not appearing anywhere in a, add a
substitution a/b
3. If both are terms with the same function and arity,
recursively unify the arguments pairwise
4. otherwise, fail
625
|A(c, v, v), |A(f(u, x), y, f(u, z)), A(x, y, z), |A(f(a, c), f(a, c), v)
626
26.3 Automata
Finite Automata (Finite State Machine) handles a
sequence of input symbols from input alphabet set
Machines reaction to input symbol depends on current
state, an element of Q
Reaction to input specied by function : Q Q
Machine must also specify initial state q
0
Machine may act as a recognizer ; then must also
specify a set of states F; when input runs out, if state
of machine F then input is accepted by machine
Machine may produce output; then may also specify
an output symbol to produce for given state and input
Nondeterministic Finite Automaton (NFA) is FA where
is a relation rather than a function; Any NFA can be
rewritten as a DFA
627
Exercise
Often drawn as diagram with circles representing states
and arcs labeled by input symbols representing transitions
( function)
What input does this FSM accept?
b c c
q1
q3
q4
q2 q0
a
a,b
a, b, c
b c
a, b
a
c
628
Exercise
Which of these inputs does the following machine accept?
More generally, what inputs will the machine accept?
a/a R
x/x R
b/b R
x/x R
a/a L
b/b L
x/x L
x/x R
q0 q1
B/B R
q2
q3
q4
q5
b/x R
B/B R
c/x L
q6
a/B R
B/B R
x/x R B/B R
abaca
abc
aabbcccc
aaabbbccc
631
26.3.3 Undecidability
Church-Turing Thesis: there is an eective procedure
to decide a problem i a Turing machine can do so
Cannot be proved, but has stood the test of time
Halting problem (will a turing machine M ever halt if
given input s) is undecidable can never be
implemented on any TM
Halting problem is semidecidable can built TM SH
that will accept when M will halt for input s; if it
wont, SH will not terminate
Problem P is reducible to Q if input for P can be
rewritten to input for Q
If P is reducible to Q and Q is decidable, so is P; if P
is undecidable, so is Q
Satisability of predicate logic formulae is undecidable
632
26.3.4 Countability
Two set are same cardinality if some function maps
every element of one to a unique element of the other
A set is countable if it has same cardinality as the
natural numbers
Integers are countable: e.g., map even naturals n to
n/2 and odd to (n + 1)/2
Rational numbers are countable
Real numbers are not: Cantor diagonal argument
633
26.3.5 Complexity
Complexity measures worst case time or space usage
of algorithm depending on size of input
Complexity of problem measures complexity of best
possible algorithm
Algorithm of order f(n) O(f(n)) means f(n)
dominates complexity of algorithm
Complexity depends on computation model: e.g.,
RAM can test palindrome in O(n), TM O(n
2
)
Problem is in NP if some Nondeterministic TM can
solve problem in polynomial time (O(n
c
) for some c)
Problem is NP-hard if every problem in NP can be
reduced to it in polynomial time; NP-complete if in
NP and NP-hard
Many problems are NP-complete, including SAT:
634
determining satisability of propositional logic formulae
635
636