Prolog

advertisement
A review of Prolog
• will be our choice of a shell implementation language because
(i) KBS facts and rules are directly encoded as Prolog statements
(ii) Prolog has built within it an inference engine
• Prolog: programming in logic
• a declarative language: program code are human-oriented descriptions of
what is being computed, and not how it is to be computed
- compare with imperative languages (Pascal, C,...) which encode the
computational procedure
• Note: a competitor is Lisp, which is a functional language
B. Ross Cosc 4f79
1
Logic
• 1st order predicate logic: a mathematical theory which models the world with
sentences denoting truth
eg.
Either it rains or it does not rain.
Every number different than 0 is the successor of another number.
If Jack is the parent of Fred, then Jack is the father of Fred, or
Jack is the mother of Fred.
If Jack is the parent of Fred, and Jack is male, then Jack is the
father of Fred.
There exists someone who is a parent of Fred.
• predicate logic is concerned with:
- formally representing facts with a formal grammar ('Predicate logic")
- determining ways of deducing logical truths from these sentences
"deduction"
B. Ross Cosc 4f79
2
Logic
Rules for connectives:
~W
is true
if and only if
W is false
W1 & W2 is true
if and only if
W1 is true and W2 is true
W1 or W2 is true
if and only if
either W1 is true or W2 is true
W1 if W2
is false
if and only if
W1 is false and W2 is true
W1 iff W2
is true
if and only if
either both W1 and W2 are true
or both W1 and W2 are false
Rules for Quantifiers:
( ∀ X ) W is true if and only if W is true for every substitution of a
domain object for X within W
( ∃ X ) W is true if and only if W is true for at least one substitution of a
domain object for X
B. Ross Cosc 4f79
3
Logic
• If a sentence contains quantifiers and variables, in order to determine
the truth of the sentence, you need to define a domain from which
objects will be selected.
eg. (∀ X ∃ Y) likes(X, Y)
--> need to determine what X and Y are representing:
ie. people? Food? integers?...
• whether the sentence is really true depends on the model you define
• the pairs of objects in which "likes(X,Y)" is defined by a relation
• a relation is a set of tuples that are deemed to be true
eg. if domain is { john, joe, mary, jane }
then the relation for likes in our model might be:
likes= { (john, joe), (mary, john), (jane, jane)}
So likes(X,Y) is true for likes(john, joe), likes(mary, john), likes(jane, jane)
B. Ross Cosc 4f79
4
Logic
• if a given sentence is true for at least one model, then it is satisfiable
otherwise it is unsatisfiable
eg. (∀ X ∃ Y) likes (X, Y) iff ~likes(X,Y)
is unsatisfiable
• some sentences are always true: tautologies
eg. (∀ X)
p(X) & p(X) iff p(X)
• existential quantification makes logic complex: there is no automatic
means for finding the object which satisfy an existential equation
- you can have an infinite set of objects to consider, so it would require
exhaustively searching the set
B. Ross Cosc 4f79
5
Logical deduction
•
S1 ⊨ S2
eg.
•
- S2 is a logical consequence of sentence(s) S1
(∀ X) likes(chris, X) ⊨ likes(chris, mum)
S1 ⊢ S2
eg.
- S3 is derivable from S1
(∀ X,Y) likes(X,Y) or true ⊢ true
• the useful part of logic is that it is possible to apply syntactic
transformations of sentences which preserve their truth in the
model being represented by the sentence
denoted:
∀ P, Q
P ⊨ Q iff P ⊢ Q
• there are many procedures for deriving new sentences, and hence new
statements of truth
• automatic theorem proving is concerned with proving a sentence is
true, by applying syntactic transformations to it
B. Ross Cosc 4f79
6
Logical deduction
• logic programming technique:
(a) convert statements of logic into Horn clauses
(exists an algorithm to do that)
(∀ X's)
p(X's) if q1(X's) & ... & qn(X's)
(∀ X's)
p(X's)
note: can have terms as arguments in predicate tuples (WFF's)
• logic programming languages use the following deduction rule
(called modus ponens):
{ ~A, (A if B) } ⊢ ~B
{ ~A, A }
⊢ false
• this rule preserves soundness ie. truth is maintained.
B. Ross Cosc 4f79
7
Logic Programming
• logic programming languages use the following notation:
(∀ X's)
p(X's) if q1(X's) & ... & qn(X's)
(∀ X's)
p(X's)
p(X's) :- q1(X's), ... , qn(X's).
<-- called a "rule"
p(X's).
<-- called a "fact"
• This restricted notation is just as computationally powerful as
full predicate logic
B. Ross Cosc 4f79
8
Syntax
Constants: name specific objects
i) atoms: constants or symbolic terms
- constants begin with lower-case letter
eg. bob, x25, aDog,
- symbols are such things as =, +, ...
(might be predefined in implementation, eg. :- )
ii) integers: 0, 25, -5
Variables: are generic place-holders of constants
- begin with upper-case letter
- eg. Answer, L, My_List, A3
- anonymous variable: the underscore _ , used when you
don't need to use that variable anywhere else
B. Ross Cosc 4f79
9
Syntax (cont)
Structures : basic data structure term
constant(arg 1, arg 2, ..., arg k)
k •1
- eg. bob(25), age(old), age(X), tree(left(X), right(L)), *(4), ...
illegal: B(bob)
- there are useful buiiltin structures, for example...
lists
[] - empty list , short for '.'()
[H|T] - list with first element H and tail list T,
eg. [a,b,c],
[25],
[ _ ],
'.'(H,T)
[ t(a,b), t(X,Y), Z]
• Term: a constant, variable, or structure
B. Ross Cosc 4f79
10
Prolog Statements
• Three basic kinds of statements
1. facts:
parent(john, P).
bank_account(36569483, smith, john, 25.66).
finished.
2. rules:
parent(X,Y) :- father(X,Y).
grandparent(X,Y) :- parent(X,Z), parent(Z,Y).
op_sys :- input(Job), run(Job,Res), cleanup(Res).
3. query:
:- parent(jane,W).
:- parent(X,Y), parent(Y,Z).
B. Ross Cosc 4f79
11
Logic Programming
• real example:
fact or assertion
rule
append([ ], X, X).
append([A|X], Y, [A|Z] ) :- append(X, Y, Z).
head
body
• each fact or rule is called a clause
• all the clauses with the same head name and # of arguments is a predicate
(akin to a procedure)
B. Ross Cosc 4f79
12
Program structure
• predicate: all the clauses having the same identifier and number of arguments is
- akin to a procedure
• eg.
parent(X,Y) :- father(X,Y).
parent(X,Y) :- mother(X,Y).
parent(adam).
father(john, tim).
father(john, jane).
mother(jane, jill).
grandparent(X,Y) :- parent(X,Z), parent(Z,Y).
grandparent(adam, _).
grandparent(eve, _).
human_being(_).
mother(john, tim).
B. Ross Cosc 4f79
13
Prog. structure (cont)
Good programming practices:
- group all clauses of a predicate together in program file
- be careful using same predicate identifier with different # args
- never put more than one clause per line.
- For large rules, put one goal per line also.
eg.
B. Ross Cosc 4f79
grandfather(X,Y) :male(X),
parent(X,Z),
parent(Z,Y).
14
Unification
• Computing solutions: a powerful feature of logic programming systems is
their ability to substitute values into the variables found in clauses
- this lets the deduction compute values to a query
• unification: pattern matching technique in which two atoms are matched
together, and produces the most general substitution of variables that makes
the 2 atoms identical
• method:
(i) two variables always unify: X = Y
(ii) a variable always unifies with a non-variable term that does not
contain that variable:
X = s(Y, d(Q))
(iii) two non-var terms unify if their arguments unify :
s(W, Y) = s(X, c)
(because W = X and Y = c)
• when a variable unifies with a term, we say it is bound to that term
this binding is a data binding that holds forever ( until backtracking )
B. Ross Cosc 4f79
15
Unification examples
• c = c --> result: 'true'
• X=Y
(where X, Y are uninstantiated)
--> result: X <- Y
(they are matched together)
• X = d --> result: X <- d
• s(X) = s(Y,c) --> fail
• t(c) = t(Z) --> result: Z <- x
• apples = oranges --> fail
• apples = Apples --> result: Apples <- apples
• a(b,C,d(e,F,g(h(i,J)))) = a(B,c,d(E,f,g(H)))
--> result: B <- b, C <- c, E <- e, F <- f, H <- h(i,J)
B. Ross Cosc 4f79
16
Unification (cont)
• Note: unification can produce infinite terms, or even never terminate,
under some conditions
- this happens when the same variable occurs in both expressions
eg.
Y = father(Y)
--> result: Y <- father(father(father(..... )))
– this usually only happens by accident in buggy programs
B. Ross Cosc 4f79
17
Substitutions
• the computed result from unification procedure
• Also called bindings or computed answer substitutions
• have form: Ω = { X1 <- t1,... Xk <- tk } ( k •0 )
where Xi's are variables
and ti's are terms (constants, structures, variables)
• each variable Xi is distinct
To apply a substitution to a term:
• simultaneously substitute all terms ti for the Xi in the term
eg.
let term W = p(U, g(V), Y)
Ω = {U <- a, V <- Y, Y <- c}
then
W Ω = p(a, g(c), c)
Note: it can simplify things to apply Y <- c for V in ž
B. Ross Cosc 4f79
18
Unification algorithm
Input: two terms T1 and T2 to be unified
Output: the answer substitution set Ω, or FAIL
Initialize: Ω := empty
Algorithm:
1. If T1 (or T2) is a variable:
(a) If variable T1 (or T2) occurs in expression T2 (or T1) then FAIL
(b) else add T1 <- T2 (or T2 <- T1) to Ω, and reset T1 everywhere else
2. if either expression is a constant, and the other expression is a
different constant or structured term, then FAIL
3. If both expressions are structured terms:
(a) if they have different identifiers OR different # arguments then FAIL
(b) else apply unification recursively to their arguments, unifying
then by their corresponding ordered positions
B. Ross Cosc 4f79
19
More examples
1) s(X, t(T ,X), Z) = s(a, t(b, c), W)
2)
[ a, f(B), C, d, e, f ] = [ First, Second, Third | Rest ]
B. Ross Cosc 4f79
20
Resolution
• basic computation technique in logic programming
• given a query :- G1, G2,...,Gk
and a set of program clauses of form H :- B1, B2,..., Bj. (j≥0)
1. select a goal Gi (1 ≤ i ≤ k) in the query
2. find a clause Hn whose head unifies Gi resulting in a set of
unification bindings Ω (might be empty)
3. replace Gi by the body of Hn, and apply žto new query
ie.
G1,...,G(i-1),Gi, G(i+1),...,Gk.
Hn :- B1n,B2n,...,Bmn.
(G1,...,G(i-1), B1n,B2n,...,Bmn, G(i+1),...,Gk.)ž
4. Repeat until an empty query is obtained; all the Ω 's collected will give
the solution to the computation
B. Ross Cosc 4f79
21
Resolution trees
• Note that there are many ways to select a goal in the query to process next,
and many ways to select a candidate clause in the program
• The computation can be represented by a tree:
:- Q1
Hi
Hj
:- Q2
:- Q2
:- Q3
Hm
Hl
Hr
:- Q5
:- Q4
Hn
Hk
Ho
Hp
Hq
(fail)
(success)
B. Ross Cosc 4f79
22
Logic Programming
• example deduction using resolution:
Program P:
C1:
C2:
C3:
C4:
C5:
C6:
C7:
A :B :B :D :D.
E.
F.
B.
C.
D, F.
E.
Query: ?- A. (notation for queries)
(1)
apply C1:
apply C3:
apply C7:
apply C4:
apply C6:
?- A.
?- B.
?- D, F.
?- D.
?- E.
?- nil. --> thus ~A is false, or A is true.
(2)
apply C1:
apply C3:
apply C5:
apply C7:
?- A.
?- B.
?- D, F.
?- F.
?- nil
--> ditto.
B. Ross Cosc 4f79
23
Prolog's Control
• from previous examples, note that deduction proof 2 is shorter.
Issues: (1) which clause to apply?
(2) which goal in query to reduce?
• Unfortunately, there is no automatic means of deciding this.
• logic programming interpreters will use some sort of arbitary scheme
• Prolog's Standard depth-first left-to-right control:
a) control rule: always pick left-most goal to reduce
b) search rule: always pick first clause that matches
c) when there is no clause to apply, then go back to where you had a
choice of clauses to choose from, and choose the next one
--> "backtracking"
• (c) above lets the interpreter find multiple solutions to a query
• advantage: It's easy to learn, and efficient to implement
• disadvantage: it is unfair, and tree searches can be nonterminating
(contrast with breadth-first control)
B. Ross Cosc 4f79
24
Backtracking
• refers to searching for multiple solutions
• a by-product of searching more than one clausewhen computing a goal
1:
plan_date(Guy, Gal, Food) :- likes(Guy, Food), likes(Gal, Food).
2:
3:
4:
5:
6:
likes(tom, sushi).
likes(tom, pasta).
likes(tom, bbq).
likes(sue, pasta).
likes(sue, bbq).
?- plan_date(tom, sue, Food)
1
?- likes(tom,Food), likes(sue, Food)
2
?- likes(sue, sushi)
3
?- likes(sue, pasta)
5
B. Ross Cosc 4f79
{Food <- pasta }
4
?- likes(sue, bbq)
6
{ Food <- bbq }
25
Backtracking
• Variables are unique within each clause.
• when recursion occurs, rename variables in the clause so that
they don't clash with those in the current goal
eg.
grandparent(A,B) :- parent(A,X), parent(X,B).
parent(X,Y) :- father(X,Y).
parent(X,Y) :- mother(X,Y).
?- grandparent(X, tom).
( grandparent(A,B) :- parent(A, X' ) , parent(X' , B).
)
ž= { X <- A, B <- tom }
?- parent(A, X'), parent(X', tom).
B. Ross Cosc 4f79
26
Some possible program behaviors
- no solutions:
eg.
output --> "no"
?- pet(cat).
pet(dog).
- a finite number of solutions
eg. ?- pet(X).
pet(cat).
pet(dog).
- an infinite number of solutions
eg. ?- pet(Y).
pet(dog).
pet(X) :- pet(X).
- non-termination, and eventually memory overflow
eg. ?- pet(X).
pet(Y) :- pet(Y).
- computation error: bad use of builtin predicates
B. Ross Cosc 4f79
27
Real Prolog
• Real prolog implementations add extra-logical features so that practical
programming can be done. Some examples from Clocksin & Mellish are:
(1) Input-Output:
read\1, write \1 - read and write terms
get\1, pur\1 - read and write characters
nl - write a new line
(2) Files
see(X) - opens file X for input
tell(X) - opens file X for output
(3) Negation
not G - succeeds if goal G fails, and fails if G succeeds
(3) Equality
X = Y - unifies X and Y, or fails if they don't unify
X \= Y - opposite of X = Y, ie. not (X = Y)
X == Y - like X=Y, except that all variables have to be the same too; == does
not instantiate any variables
B. Ross Cosc 4f79
28
Real prolog
3. equality (cont)
X \== Y - same as: not X == Y
4. integer relations: < > >=
=< =
\=
eg. X < Y - succeeds if value in X < Y. Note that X and Y can't be
uninstantiated
5. arithmetic:
X is Expr
- where Expr is an arithmetic expression
using +, - , *, /, mod, ...
- (i)Y op Z is evaluated,; (ii) if X is not set, it is set to expr's value,
or (iii) if X has a value, then it is compared with expression value.
- Note that arithmetic expressions must use instantiated variables, else ERROR.
6. program database manipulation
asserta(G), assertz(G) - adds clause G to the program database
retract(G) - matches G with a clause, and removes it if found
retractall(H) - retracts all clauses whose heads match with H
B. Ross Cosc 4f79
29
Real Prolog
7. control
repeat - always succeeds
fail - always fails
eg. loop :- repeat, write('hi!'), nl, fail.
7. structure manipulation
S =.. List - Structure S is decomposed into List, or List is converted to S
eg.
A =.. [stock, macintosh, 128k]
stock(pc2, 640k, mouse) =.. L
: A <- stock(macintosh, 128k)
: L <- [stock, pc2, 640k, mouse]
eg. Testing the name of an atom
checkname(Struct, Ident) :- Struct =.. [Ident| _ ].
?- checkname(stock(pc2,64K,...), A).
A = stock.
B. Ross Cosc 4f79
30
Real Prolog
8. Variable inspection
var(X) - succeeds if X is an uninstantated variable
nonvar(X) - suceeds if X is not instantiated
integer(X) - succeeds if X is an integer
9. program inspection
clause(H,B) - matches head H and body B with a clause in database
(facts have 'true' set for body)
10. atom inspection
name(A,L)
- breaks name A into a list L of integer ascii values
eg. name(apple,L)
: L <- [97, 112, 112, 108, 100]
And Much More
B. Ross Cosc 4f79
31
The Cut:
!
• Used to permit more control over search. It deletes or 'cuts' parts of the
computation tree.
(1)
p(X) :- q(X,Y).
(2)
p(X) :- r(X,Y), !, s(Y).
(3)
p(X) :- t(Y).
?- p(X).
i) All the solutions from (1) are used.
ii) If r(X,Y) succeeds, then ! is activated:
- during backtracking, if s(Y) fails, then the whole clause fails
- also, solutions from (3) will be ignored
iii) if r(X,Y) fails, then (2) fails, and computation proceeds to (3)
Note that s(Y) can still return multiple solutions
B. Ross Cosc 4f79
32
Cut (cont)
• Common use of cuts:
p(X) :- G1, ..., Gk, !.
: this means that, if clause succeeds, it will only
return 1 solution
eg. make member only return 1 solution
member(X, [X| _ ]) :- !.
member(X, [_ |Y]) :- member(X,Y).
• possible to create cleaner control constructions with the cut
eg.
once(P) :- call(P), !.
or
once(P) :- P, !.
eg.
if_then_else(P, Q, R) :- P, !, Q.
if_then_else(P, Q, R) :- R.
( could be :
if_then_else(P, Q, R) :- P, Q.
if_then_else(P, Q, R) :- (not P), R.
except that test P might be expensive. )
B. Ross Cosc 4f79
33
Meta-interpreters
• meta-interpreter: interpreter for a language written in the language
itself
• Prolog is ideally suited for this:
solve(true).
solve(not(A)) :- not solve(A).
solve((A,B)) :- solve(A), solve(B).
goals in Prolog are stored as:
A, (B, (C, D))
ie. "," is right-associative
solve(A) :- clause(A,B), solve(B).
builtin predicate which gets a clause which
unifies with head A, and has body B
B. Ross Cosc 4f79
34
Defining operators
• Prolog lets you define your own operators (or override builtin ones)
• useful for writing customized programs, especially meta-interpreters
eg.
?- op(300, yfx, ^).
executed goal!
right-associative infix: 2^3^4 --> 2^(3^4)
relative precedence
• to set precedence, you need the precedence settings of the system
your using
• see Clocksin & Mellish for explanation of op definitions
B. Ross Cosc 4f79
35
Disjunction, if-then-else
• disjunction (logical OR):
parent(Parent, Child) :- mother(Parent, Child) ; father(Parent, Child).
- can also do:
p(X, Y) :- ( a(X, Z), b(Z, Y)) ; c(Y).
- whenever you see a ";", you can convert the clause into multiple clauses
• If - then :
parent(X, Y) :- person(X) -> mother(X, Y).
- behaves almost like parent(X,Y) :- person(X), mother(X, Y).
except that person only returns one solution (no backtracking when
mother fails)
• If - then - else: parent(X, Y) :- male(X) -> father(X, Y) ; mother(X, Y).
- if male(X) true, then father executed, else mother executed
B. Ross Cosc 4f79
36
If-then-else
• if-then-else can often be used instead of cuts
• implemented as:
parent(X, Y) :- male(X), !, father(X, Y).
parent(X, Y) :- mother(X, Y).
• trick:
once(P) :- call(P), !.
eg. once(member(apple, L))
B. Ross Cosc 4f79
<-- this saves putting cuts in lots of clauses
<- don't need a "member" that has a cut in it
37
Debugging Prolog
• interpreter's trace facility is very useful
• standard debugging features:
spy - set a breakpoint on a procedure
trace - manually control execution
skip - call a goal, and return control when goal finished
creep - trace into the goal call
redo - call goal again
fail - force goal to fail
• Beware! If you change the database (assert, retract), be sure to clean it
up if necessary. Otherwise, you'll get side effects (doubly asserted clauses,
etc)
B. Ross Cosc 4f79
38
Example Prolog programs
•
•
•
•
•
Lists
graph searching
graph searching with cycle checking
bubble sort
sorted binary tree
B. Ross Cosc 4f79
39
Example 1: appending lists
append( [ ], L, L).
append( [X | R] S, [X | T]) :- append(R, S, T).
?- append([ a, b, c], [1, 2, 3], L).
L = [a, b, c, 1, 2, 3] .
?- append( Y, [1, 2, 3], [a, b, c, 1, 2, 3]).
Y = [a, b, c]
?- append(X, Y, [1,2,3]).
X=[ ], Y = [1, 2, 3] ;
X=[1], Y = [2, 3] ;
X=[1,2], Y = [3] ;
X = [1,2,3], Y = [ ];
no
?- append([_|_], [Y|_], [1, 2, 3]).
Y = 1; Y = 2; Y = 3; no
B. Ross Cosc 4f79
% a way to use append like ‘member’!
40
Example: sorted binary trees
nil : empty branch/tree
tree(Left_branch, Key, Right_branch) : tree node with data
– hence tree(tree(nil,2,nil), 4, tree(tree(nil,5,nil), 6, nil)) represents:
4
2
6
5
B. Ross Cosc 4f79
41
Binary tree (cont)
add_bintree(Key, nil, tree(nil, Key, nil).
add_bintree(Key, tree(L, Key, R), tree(L, Key, R)).
add_bintree(Key, tree(L, K, R), tree(L2, K,R)) :Key < K,
add_bintree(Key, L, L2).
add_bintree(Key, tree(L, K, R), tree(L, K, R2) :Key > K,
add_bintree(Key, R, R2).
B. Ross Cosc 4f79
42
Example: graph search
i
a
j
f
g
k
b
e
h
l
c
d
5. Representing directed graphs as program clauses
edge(d, c).
edge(b, c).
edge(b, f).
edge(a, b).
edge(e, f).
B. Ross Cosc 4f79
edge(f, e).
edge(f, i).
edge(i, j).
edge(j, k).
edge(k, g).
edge(h, l).
edge(l, k).
edge(g, f).
edge(g, h).
43
Graphs
•
Graphs (cont)
– Can then search for connections within the graph:
path(A, B) :- edge(A,B).
path(A,B) :- edge(A,C), path(C,B).
note similarity with ‘ancestor’:
ancestor(A,B) :- parent(A,B).
ancestor(A,B) :- parent(A,C), ancestor(C,B).
– However, unlike family relationships, graphs can have loops
– using Prolog’s backtracking, it can easily get sidetracked into a
loop
– eg. ?- path(j,a) will go thru: j - k - g - f - i - j - etc
B. Ross Cosc 4f79
44
Graphs
• Graphs: another approach: use a list structure
[v(Node1, Nodelist1), v(Node2, Nodelist2), ...]
then
graph([ v(a, [b, f]), v(b, [c,f]), v(d, [f]), v(f, [e,i]), v(g, [f,h]),
v(i, [j]), v(j, [k]), v(k, [g]), v(l, [k]), v(h, [l]) ] ).
•
Can write a ‘path’ routine which keeps track of places it has
already been to; if it has been to a place already, then don’t go
there again!
(can also do this with the other representation)
B. Ross Cosc 4f79
45
Graphs
path(Start, Finish) :- graph(G), smart_path(Start, Finish, G, [ ]).
smart_path(A, B, G, _) :member(v(A,L), G),
member(B, L).
smart_path(A, B, G, Previous) :member(v(A,L), G),
member(C, G),
not member(C, Previous),
smart_path(C, B, G, [A | Previous]).
B. Ross Cosc 4f79
46
Bubble Sort
bubble(L, S) :append(X, {A,B|Y], L),
B < A,
!,
append(X, [B, A | Y], M),
bubble(M, S).
bubble(L, L).
B. Ross Cosc 4f79
47
Download