47
B. Ross Cosc 4f79 1 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: pro gramming in log ic a declarative language: program code are human-oriented descriptions o what is being computed, and not how it is to be computed compare with imperative languages (Pascal, C,...) which encode the computational procedure te: a competitor is Lisp, which is a functional language

B. Ross Cosc 4f79 1 A review of Prolog will be our choice of a shell implementation language because (i) KBS facts and rules are directly encoded as Prolog

Embed Size (px)

Citation preview

B. Ross Cosc 4f79 1

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 2

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 3

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 4

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 5

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 6

Logical deduction• S1 ⊨ S2 - S2 is a logical consequence of sentence(s) S1

eg. (∀ X) likes(chris, X) ⊨ likes(chris, mum)

• S1 ⊢ S2 - S3 is derivable from S1

eg. (∀ 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 7

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 8

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 9

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 10

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, '.'(H,T)

eg. [a,b,c], [25], [ _ ], [ t(a,b), t(X,Y), Z]

• Term: a constant, variable, or structure

B. Ross Cosc 4f79 11

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 12

Logic Programming

• real example:

append([ ], X, X).

append([A|X], Y, [A|Z] ) :- append(X, Y, Z).

fact or assertion

rule

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 13

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 14

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. grandfather(X,Y) :- male(X), parent(X,Z), parent(Z,Y).

B. Ross Cosc 4f79 15

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 16

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 17

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 18

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 19

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 20

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 21

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 22

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

:- Q2 :- Q2 :- Q3

:- Q4 :- Q5

HiHj

Hk

HlHm

HnHo

Hp Hq

Hr

(fail)

(success)

B. Ross Cosc 4f79 23

Logic Programming

• example deduction using resolution:

Program P: C1: A :- B. Query: ?- A. (notation for queries) C2: B :- C. C3: B :- D, F. C4: D :- E. C5: D . C6: E. C7: F.

(1) ?- A.apply C1: ?- B.apply C3: ?- D, F.apply C7: ?- D.apply C4: ?- E.apply C6: ?- nil. --> thus ~A is false, or A is true.

(2) ?- A.apply C1: ?- B.apply C3: ?- D, F.apply C5: ?- F.apply C7: ?- nil --> ditto.

B. Ross Cosc 4f79 24

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 25

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: likes(tom, sushi).3: likes(tom, pasta).4: likes(tom, bbq).5: likes(sue, pasta).6: likes(sue, bbq).

?- plan_date(tom, sue, Food)

?- likes(tom,Food), likes(sue, Food)

?- likes(sue, sushi) ?- likes(sue, pasta) ?- likes(sue, bbq)

1

2 3 4

5 6

{Food <- pasta } { Food <- bbq }

B. Ross Cosc 4f79 26

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). )

?- parent(A, X'), parent(X', tom).

ž = { X <- A, B <- tom }

B. Ross Cosc 4f79 27

Some possible program behaviors

- no solutions: output --> "no"

eg. ?- 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 28

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 29

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 30

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] : A <- stock(macintosh, 128k) stock(pc2, 640k, mouse) =.. L : 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 31

Real Prolog8. 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 MoreAnd Much More

B. Ross Cosc 4f79 32

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 33

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 34

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).

solve(A) :- clause(A,B), solve(B).

builtin predicate which gets a clause whichunifies with head A, and has body B

goals in Prolog are stored as: A, (B, (C, D)) ie. "," is right-associative

B. Ross Cosc 4f79 35

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, ^).

relative precedenceright-associative infix: 2^3^4 --> 2^(3^4)

• to set precedence, you need the precedence settings of the system your using

• see Clocksin & Mellish for explanation of op definitions

executed goal!

B. Ross Cosc 4f79 36

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 37

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), !. <-- this saves putting cuts in lots of clauses

eg. once(member(apple, L)) <- don't need a "member" that has a cut in it

B. Ross Cosc 4f79 38

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 39

Example Prolog programs

• Lists

• graph searching

• graph searching with cycle checking

• bubble sort

• sorted binary tree

B. Ross Cosc 4f79 40

Example 1: appending listsappend( [ ], 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]). % a way to use append like ‘member’!

Y = 1; Y = 2; Y = 3; no

B. Ross Cosc 4f79 41

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 42

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 43

Example: graph search

5. Representing directed graphs as program clausesedge(d, c). edge(f, e). edge(h, l).

edge(b, c). edge(f, i). edge(l, k).

edge(b, f). edge(i, j). edge(g, f).

edge(a, b). edge(j, k). edge(g, h).

edge(e, f). edge(k, g).

a

b

c

d

f

e

g

hl

k

j

i

B. Ross Cosc 4f79 44

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 45

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 46

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 47

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).