CSC324 Logic & Relational Programming Illustrated in Prologafsaneh/csc324w13/prolog-partII.pdf ·...

Post on 24-Jul-2020

4 views 0 download

Transcript of CSC324 Logic & Relational Programming Illustrated in Prologafsaneh/csc324w13/prolog-partII.pdf ·...

CSC324 — Logic & Relational ProgrammingIllustrated in Prolog

Afsaneh Fazly1

Winter 2013

1with many thanks to Anya Tafliovich, Gerald Penn and Sheila McIlraith.1

admin notes

• Please check your marks for A1, A2, Midterm on CDF. Emailme if any of the marks is recorded incorrectly.

• Remember that there will be a lecture/tutorial on FridayMarch 8, 2–3pm, BA 1190 (by the instructor).

2

Execution of Prolog Programs

• Unification: variable bindings.

• Backward Chaining/Top-Down Reasoning/Goal-Directed Reasoning:Reduces a goal to one or more subgoals.

• Backtracking:Systematically searches for all possible solutions that can beobtained via unification and backchaining.

3

Unification: Overview

• A number/atom unifies only with itself.

• An uninstantiated variable unifies with any value ⇒ thevariable gets instantiated to that value.

• Two uninstantiated variables unify ⇒ the two variables shareor co-refer, i.e., as soon as one gets instantiated, so is theother one (to the same value).

• A term unifies with another term with the same functor, ifthey have the same number of arguments and allcorresponding arguments unify.

4

Backward Chaining

This is how Prolog satisfies a goal (query):

1. Search the database for a unifying clause.

2. If not found, search fails.

3. Otherwise, mark the place in the database where the unifyingclause is found.

4. If unifying clause is a fact ⇒ instantiate variables (if any).

5. If unifying clause is a rule, instantiate variables, and try tosatisfy the subgoals, in order, from left to right.

5

Example

Given the database:

male(charlie). parent(charlie, bob).

male(bob). parent(eve,bob).

female(alice). parent(charlie,alice).

female(eve). parent(eve,alice).

and the query:

?- male(charlie).

The unifying clause is a fact; no variables ⇒ returns true.

with the query

?- male(X).

The unifying clause is a fact, with variable X ⇒ instantiates X tocharlie.

6

Example

Given the database & rules:

male(charlie). parent(charlie, bob).

male(bob). parent(eve,bob).

female(alice). parent(charlie,alice).

female(eve). parent(eve,alice).

sibling(X, Y) :- parent(P, X), parent(P, Y).

with the query

?- sibling(S, bob).

The unifying clause is a rule ⇒(1) instantiate Y to bob, and X to S (i.e., X and S co-refer),(2) try to satisfy parent(P, S), and then parent(P, bob).

7

Backtracking

If an attempt to satisfy a goal fails, or if we ask for more answers,Prolog tries to re-satisfy the goal by backtracking, as follows:

1. Move back along the search path to where the unifying clausewas found.

2. Un-instantiate any variables that have been instantiatedduring the search process.

3. Start another search for another unifying clause from wherethe current unifying clause was found (the place marked in thedatabase).

8

Example

male(charlie). parent(charlie, bob).

male(bob). parent(eve,bob).

female(alice). parent(charlie,alice).

female(eve). parent(eve,alice).

female(nikki). parent(alice,nikki).

grandparent(X, Z) :- parent(X, Y), parent(Y, Z).

?- grandparent(G, nikki).

9

Example

?- grandparent(G, nikki).

1. X = G, Z = nikki.

2. satisfy parent(G, Y) ⇒ (2.1) G = charlie, Y = bob.

3. satisfy parent(Y=bob, nikki) ⇒ (3.1) bob = alice. fail

4. uninstantiate G and Y.

5. re-satisfy parent(G, Y) ⇒ (5.1) G = eve, Y = bob.

6. re-satisfy parent(Y=bob, nikki) ⇒ (6.1) bob = alice.fail

7. re-satisfy parent(G, Y) ⇒ (7.1) G = charlie, Y = alice.

8. re-satisfy parent(Y=alice, nikki) ⇒ (8.1) alice = alice.success

10

Prolog Search Trees

Encapsulate unification, backward chaining, and backtracking.

• Internal nodes are ordered list of subgoals.

• Leaves are success nodes or failures, where computation canproceed no further.

• Edges are labeled with variable bindings that occur byunification.

Describe all possible computation paths.

• There can be many success nodes.

• There can be infinite branches.

11

Prolog Search Trees

1) male(charlie). 5) parent(charlie,bob).

2) male(bob). 6) parent(eve,bob).

3) female(alice). 7) parent(charlie,alice).

4) female(eve). 8) parent(eve,alice).

9) sibling(X, Y) :- parent(P, X), parent(P, Y).

?- sibling(alice, Who).

Who = bob ;

Who = alice ;

Who = bob ;

Who = alice.

12

Prolog Search Trees

Trace it by hand

13

Prolog Search Trees

?- trace.

Unknown message: query(yes)

[trace] ?- sibling(alice, Who).

Call: (8) sibling(alice, _G306) ?

Call: (9) parent(_L195, alice) ?

Exit: (9) parent(charlie, alice) ?

Call: (9) parent(charlie, _G306) ?

Exit: (9) parent(charlie, bob) ?

Exit: (8) sibling(alice, bob) ?

Who = bob ;

Redo: (9) parent(charlie, _G306) ?

Exit: (9) parent(charlie, alice) ?

Exit: (8) sibling(alice, alice) ?

Who = alice ;

14

Prolog Search Trees

Redo: (9) parent(_L195, alice) ?

Exit: (9) parent(eve, alice) ?

Call: (9) parent(eve, _G306) ?

Exit: (9) parent(eve, bob) ?

Exit: (8) sibling(alice, bob) ?

Who = bob ;

Redo: (9) parent(eve, _G306) ?

Exit: (9) parent(eve, alice) ?

Exit: (8) sibling(alice, alice) ?

Who = alice.

Notice the recursion in this algorithm: “find” calls “find”. Thisreasoning is recursively applied until we reach rules that are facts.

15

Logic Programming vs. Prolog

Logic Programming: nondeterministic:

• Arbitrarily choose rule to expand first.• Arbitrarily choose subgoal to explore first.• Results don’t depend on rule and subgoal

ordering.

Prolog: deterministic:

• Expand first rule first.• Explore first subgoal first.• Results may depend on rule and subgoal

ordering.

16

Lists in Prolog

An n-element list in Prolog is:

[ e1, e2, . . . , en ]

Egs: [a, b, c]

[]

[a, [b, c], d, [], e]

[a, X, c, d]

or, equivalently,[ e1 | [ e2 | [ . . . en ]]]

Egs: [a | Rest]

[a | [b, c]] stands for [a, b, c]

⇒ Remember cons in Scheme, and :: in ML.

17

Lists in Prolog

List Unification: two lists unify iff they have the same structureand the corresponding elements unify.

?- [X, Y, Z] = [john, likes, fish].

?- [cat] = [X|Y].

?- [1,2] = [X|Y].

18

Lists in Prolog

?- [a,b,c] = [X|Y].

?- [a,b|Z]=[X|Y].

?- [X,abc,Y]=[X,abc|Y].

?- [[the|Y]|Z] = [[X,there] | [is,here]].

19

Some Notation

We write mem/2 to specify a predicate mem with 2 arguments.

We specify preconditions on arguments using the followingnotation:

+ArgName means ArgName must be instantiated-ArgName means ArgName must be not instantiated?ArgName means ArgName may or may not be instantiated.

E.g., mem(?X, ?List) is a predicate with 2 arguments, both mayor may not be instantiated when called.

Note: the notation is for documentation / clarification purposes,and not a part of Prolog syntax.

20

Lists in Prolog

% mem(?X,?List) iff X is an element of List

In English: mem(X,List) holds iff• X is the first element of List,

or

• X is a member of the rest of List.

In Prolog:

mem(X,[X|_]).

mem(X,[_|Rest]) :- mem(X,Rest).

21

Lists in Prolog

% mem(?X,?List) iff X is an element of List

mem(X,[X|_]).

mem(X,[_|Rest]) :- mem(X,Rest).

?- mem(a, [a,b,c]).

true.

?- mem(b, [a,c]).

false.

?- mem(X, [a,b,c]).

X = a ;

X = b ;

X = c ;

false.

22

Lists in Prolog

?- mem(a, X).

X = [a|_G236] ;

X = [_G235, a|_G239] ;

X = [_G235, _G238, a|_G242] ;

X = [_G235, _G238, _G241, a|_G245] ;

X = [_G235, _G238, _G241, _G244, a|_G248].

23

Lists in Prolog

?- trace.

[trace] ?- mem(c,[a,b,c,d]).

Call: (7) mem(c, [a, b, c, d]) ?

Call: (8) mem(c, [b, c, d]) ?

Call: (9) mem(c, [c, d]) ?

Exit: (9) mem(c, [c, d]) ?

Exit: (8) mem(c, [b, c, d]) ?

Exit: (7) mem(c, [a, b, c, d]) ?

true

24

Lists in Prolog

[trace] ?- mem(X,[a,b,c,d]).

Call: (7) mem(_G314, [a, b, c, d]) ?

Exit: (7) mem(a, [a, b, c, d]) ?

X = a ;

Redo: (7) mem(_G314, [a, b, c, d]) ?

Call: (8) mem(_G314, [b, c, d]) ?

Exit: (8) mem(b, [b, c, d]) ?

Exit: (7) mem(b, [a, b, c, d]) ?

X = b ;

Redo: (8) mem(_G314, [b, c, d]) ?

Call: (9) mem(_G314, [c, d]) ?

Exit: (9) mem(c, [c, d]) ?

Exit: (8) mem(c, [b, c, d]) ?

Exit: (7) mem(c, [a, b, c, d]) ?

25

Lists in Prolog

X = c ;

Redo: (9) mem(_G314, [c, d]) ?

Call: (10) mem(_G314, [d]) ?

Exit: (10) mem(d, [d]) ?

Exit: (9) mem(d, [c, d]) ?

Exit: (8) mem(d, [b, c, d]) ?

Exit: (7) mem(d, [a, b, c, d]) ?

X = d ;

Redo: (10) mem(_G314, [d]) ?

Call: (11) mem(_G314, []) ?

Fail: (11) mem(_G314, []) ?

false.

26

Lists in Prolog

% myappend(?X,?Y,?Z) iff Z is the result of

% appending list Y to list X

myappend(X,Y,Z) holds iff:• X is empty list ([]), and Z = Y,

or

• Z is a list containing the first element of X, followed by theresult of appending Y to the rest of X.

27

Lists in Prolog

% myappend(?X,?Y,?Z) iff Z is the result of ...

myappend([],Y,Y).

myappend([H|T],Y,[H|Z]) :- myappend(T,Y,Z).

?- myappend([a],[b,c],Y).

Y = [a, b, c].

?- myappend(X,[b,c],[a,b,c]).

X = [a] ;

false

?- myappend(X,Y,[a,b,c]).

X = [], Y = [a, b, c] ;

X = [a], Y = [b, c] ;

X = [a, b], Y = [c] ;

X = [a, b, c], Y = [] ;

false

28

Lists in Prolog

[trace] ?- myappend([a,b,c],[d,e],Z).

Call: (7) myappend([a, b, c], [d, e], _G319) ?

Call: (8) myappend([b, c], [d, e], _G385) ?

Call: (9) myappend([c], [d, e], _G388) ?

Call: (10) myappend([], [d, e], _G391) ?

Exit: (10) myappend([], [d, e], [d, e]) ?

Exit: (9) myappend([c], [d, e], [c, d, e]) ?

Exit: (8) myappend([b, c], [d, e], [b, c, d, e]) ?

Exit: (7) myappend([a, b, c], [d, e], [a, b, c, d, e]) ?

Z = [a, b, c, d, e].

29

Lists in Prolog

% mylength(?L,?N) iff N is the length of list L

mylength(L,N) holds iff:• L = [] and N = 0,

or

• length of rest of L = N - 1.

30

Lists in Prolog

% mylength(?L,?N) iff N is the length of list L

mylength([],0).

mylength([_|T],N) :- mylength(T,N-1).

?- mylength([a,b,c],3).

false.

Why doesn’t this work?Let’s trace it.

31

Lists in Prolog

[trace] ?- mylength([a,b,c],3).

Call: (7) mylength([a, b, c], 3) ?

Call: (8) mylength([b, c], 3-1) ?

Call: (9) mylength([c], 3-1-1) ?

Call: (10) mylength([], 3-1-1-1) ?

Fail: (10) mylength([], 3-1-1-1) ?

Fail: (9) mylength([c], 3-1-1) ?

Fail: (8) mylength([b, c], 3-1) ?

Fail: (7) mylength([a, b, c], 3) ?

false.

Do you see what’s happening here?

32

Lists in Prolog

[trace] ?- mylength([a,b,c],3).

Call: (7) mylength([a, b, c], 3) ?

Call: (8) mylength([b, c], 3-1) ?

Call: (9) mylength([c], 3-1-1) ?

Call: (10) mylength([], 3-1-1-1) ?

Fail: (10) mylength([], 3-1-1-1) ?

Fail: (9) mylength([c], 3-1-1) ?

Fail: (8) mylength([b, c], 3-1) ?

Fail: (7) mylength([a, b, c], 3) ?

false.

Do you see what’s happening here?

• Prolog looks for a unifying clause for ’3-1-1-1’, which isequivalent to the term ’-(-(-(3,1),1),1)’.

• need to explicitly tell Prolog to evaluate this term as anarithmetic expression.

33

Arithmetic in Prolog

What is the result of these queries:

?- X = 97-65.

?- X = 97-65, Y = 32-0, X = Y.

?- X = 97-65, Y = 67, Z = 95-Y, X = Z.

34

Arithmetic in Prolog

What is the result of these queries:

?- X = 97-65.

?- X = 97-65, Y = 32-0, X = Y.

?- X = 97-65, Y = 67, Z = 95-Y, X = Z.

Notes:

• Recall that the symbol = stands for unification:X = Y holds iff X and Y unify.

• Another useful symbol in Prolog is \=:X \= Y holds iff X cannot unify with Y.

35

Arithmetic in Prolog

To evaluate arithmetic expressions in Prolog, use:

• expr1 is expr2, where expr2 is fully instantiated.• if expr1 is instantiated, Prolog evaluates the term ⇒ returnstrue or false.

• if expr1 is a variable, it is bound to the result of evaluatingexpr2.

• expr1 < expr2, expr1 > expr2, expr1 =< expr2, orexpr1 => expr2, where both expr1 and expr2 areinstantiated.

• note the symbols =< and => for greater/less than or equal.

36

Arithmetic in Prolog

?- 5 is 2+3.

true.

?- X is 2+3.

X = 5.

?- 5 < 6.

true.

?- 2+3 < 3+3.

true.

37

Arithmetic in Prolog

% mylength(?L,?N) iff N is the length of list L

mylength([],0).

mylength([_|T],N) :- N is NT+1, mylength(T,NT).

38

Arithmetic in Prolog

% mylength(?L,?N) iff N is the length of list L

mylength([],0).

mylength([_|T],N) :- N is NT+1, mylength(T,NT).

?- mylength([a,b,c],3).

ERROR: is/2:

Arguments are not sufficiently instantiated

Why?

[trace] ?- mylength([a,b,c],3).

Call: (7) mylength([a, b, c], 3) ?

^ Call: (8) 3 is _G358+1 ?

ERROR: is/2: Arguments are not sufficiently instantiated

^ Exception: (8) 3 is _G358+1 ?

Exception: (7) mylength([a, b, c], 3) ?

39

Arithmetic in Prolog

% mylength(?L,?N) iff N is the length of list L

mylength([],0).

mylength([_|T],N) :- mylength(T,NT), N is NT+1.

?- mylength([a,b,c],3).

true

Notes:• This ordering ensures that NT+1 is instantiated when Prolog

tries to assign it to N (in N is NT+1).

• In general, the ordering of subgoals in a rule may matter!

40

Lists in Prolog

How?

[trace] ?- mylength([a,b,c],3).

Call: (8) mylength([a, b, c], 3) ?

Call: (9) mylength([b, c], _L193) ?

Call: (10) mylength([c], _L212) ?

Call: (11) mylength([], _L231) ?

Exit: (11) mylength([], 0) ?

^ Call: (11) _L212 is 0+1 ?

^ Exit: (11) 1 is 0+1 ?

Exit: (10) mylength([c], 1) ?

^ Call: (10) _L193 is 1+1 ?

^ Exit: (10) 2 is 1+1 ?

Exit: (9) mylength([b, c], 2) ?

^ Call: (9) 3 is 2+1 ?

^ Exit: (9) 3 is 2+1 ?

Exit: (8) mylength([a, b, c], 3) ?

true

41

Lists in Prolog

% mylength(?L,?N) iff N is the length of list L

mylength([],0).

mylength([_|T],N) :- mylength(T,NT), N is NT+1.

?- mylength([a,b,c], L).

L = 3.

?- mylength([X,Y], L).

L = 2.

?- mylength(X, 1).

X = [_G226] ; <-- infinite run

42

Lists in Prolog

[trace] ?- mylength(X, 1).

...

X = [_G373] ;

Redo: (9) mylength(_G374, _L196) ?

Call: (10) mylength(_G377, _L215) ?

Exit: (10) mylength([], 0) ?

^ Call: (10) _L196 is 0+1 ?

^ Exit: (10) 1 is 0+1 ?

Exit: (9) mylength([_G376], 1) ?

^ Call: (9) 1 is 1+1 ?

^ Fail: (9) 1 is 1+1 ?

43

Lists in Prolog

Redo: (10) mylength(_G377, _L215) ?

Call: (11) mylength(_G380, _L227) ?

Exit: (11) mylength([], 0) ?

^ Call: (11) _L215 is 0+1 ?

^ Exit: (11) 1 is 0+1 ?

Exit: (10) mylength([_G379], 1) ?

^ Call: (10) _L196 is 1+1 ?

^ Exit: (10) 2 is 1+1 ?

Exit: (9) mylength([_G376, _G379], 2) ?

^ Call: (9) 1 is 2+1 ?

^ Fail: (9) 1 is 2+1 ?

Redo: (11) mylength(_G380, _L227) ?

...

44

Logic Programming vs. Prolog

What happens if we change the order of rules:

% mylength(?L,?N) iff N is the length of list L

mylength([_|T],N) :- mylength(T,NT), N is NT+1.

mylength([],0).

?- mylength([a,b,c], 3).

true.

?- mylength([a,b,c], N).

N = 3.

?- mylength(X, 2).

ERROR: Out of local stack

45

Classifying Terms in Prolog

We may wish to enforce some preconditions on the arguments of apredicate, e.g., to prevent mylength from running forever.

Here are a few predicates we can use to classify terms:

• var(X) succeeds if X is an uninstantiated variable.

• atom(X) succeeds if X stands for a Prolog atom.

• number(X) succeeds if X stands for a number.

Exercise: use var or nonvar(X) to fix mylength.

mylength([],0).

mylength(L,N) :- \+ var(L), L=[_|T], mylength(T,NT), N is NT+1.

46

Example: Trip Planning

A database of facts to deal with trips:

plane(X,Y) % there is a direct flight from X to Y

boat(X,Y) % there is a direct boat trip from X to Y

Predicates to compute certain things about the trips:

a) cruise(X,Y) -- there’s a possible boat journey from X to Y.

b) trip(X,Y) -- there’s a possible journey

(using plane or boat) from X to Y.

c) stopover(X,Y,S) -- there’s a trip from X to Y with stop in S.

d) plane_cruise(X,Y) -- there’s a trip from X to Y that has

at least one plane leg, and at least one boat leg.

e) cost(X,Y,C) -- there’s a trip from X to Y with cost < C.

47

Example: Trip Planning

An example database:

plane(toronto, rochester). boat(toronto, rochester).

plane(toronto, montreal). boat(montreal, rochester).

...

Predicates:

a) cruise(X,Y) :- boat(X,Y).

cruise(X,Y) :- boat(X,Z), cruise(Z,Y).

b) leg(X,Y) :- plane(X,Y).

leg(X,Y) :- boat(X,Y).

trip(X,Y) :- leg(X,Y).

trip(X,Y) :- leg(X,Z), trip(Z,Y).

48

Example: Trip Planning

c) stopover(X,Y,S).

First, assume that neither X nor Y can equal S.

stopover(X,Y,S) :- trip(X,S), trip(S,Y).

Now, assume S could be X or Y (or even both):

hop(X,X).

hop(X,Y) :- trip(X,Y).

stopover(X,Y,S) :- hop(X,S), hop(S,Y).

d) plane_cruise(X,Y) :- plane(X,Z), boat(Z,Y).

plane_cruise(X,Y) :- boat(X,Z), plane(Z,Y).

plane_cruise(X,Y) :- leg(X,Z), plane_cruise(Z,Y).

plane_cruise(X,Y) :- leg(Z,Y), plane_cruise(X,Z).

49

Example: Trip Planning

Why do we need to have the second rule of plane cruise be

plane_cruise(X,Y) :- leg(Z,Y), plane_cruise(X,Z).

Instead of:

plane_cruise(X,Y) :- plane_cruise(X,Z), leg(Z,Y).

?

• The latter, while may be more intuitive, gives an infiniterecursion!

• You must avoid left-recursion because of the way Prologsearches through a database.

50

Example: Trip Planning

d) cost(X,Y,C)

We need to add costs to each of the plane and boat predicates,e.g., plane(toronto, rochester, 300), and redefine trip:

leg(X,Y,C) :- plane(X,Y,C).

leg(X,Y,C) :- boat(X,Y,C).

trip(X,Y,C) :- leg(X,Y,C).

trip(X,Y,C) :- leg(X,Z,C1), trip(Z,Y,C2), C is C1 + C2.

Now cost is simple, because trip is doing the addition for us:

cost(X,Y,C) :- trip(X,Y,C_trip), C_trip < C.

51

Let’s Write Some Predicateswith Arithmetic & Lists

1. factorial(N, Ans).

2. sumlist(List, Total).

3. prefix(Pre, N, List).

52

Factorial

factorial(0,1).

factorial(N,F) :- N1 is N-1,

factorial(N1,F1),

F is N*F1.

?- factorial(3,F).

F = 6 ;

ERROR: user://3:62:

Out of local stack

Question: What is the problem? Any preconditions?

Exercise: Write a more efficient factorial using an accumulator.

53

Sum of List

sumlist([],0).

sumlist([X|Rest],Ans) :- sumlist(Rest,Partial),

Ans is Partial + X.

Question: Why is left-recursion not problematic here?

54

Arithmetic Predicatesmay not be Invertible

We may not be able to “invert” a predicate that involvesarithmetic, e.g., compare:

?- sumlist([1,2,3,4], A).

A = 10.

?- sumlist(L, 10).

ERROR: user://1:24:

is/2: Arguments are not sufficiently instantiated

Tip: Every time you use is, you must be sure that the expressionon the right will be fully instantiated before is is executed.

If necessary, put a precondition on your predicate.

55

Prefix of a List

prefix(Pre, N, List) :- append(Pre, _, List),

length(Pre, N).

?- prefix(Pre, 3, [1,2,3,4,5,6]).

Pre = [1, 2, 3] ;

false.

?- prefix([1,2], 3, [1,2,3,4,5]).

false.

?- prefix([1,2,3], 3, L).

L = [1, 2, 3|_G599].

56

Negation as Failure

No equivalent of logical negation in Prolog:

• Prolog can only assert that something is true.

• Prolog cannot assert that something is false.

• Prolog can assert that the given facts and rules do not allowsomething to be proven true.

Assuming that something unprovable is false is called negation asfailure.

(Based on a closed world assumption.)

57

Negation as Failure

The goal \+(G) (or not G) succeeds whenever the goal G fails.

?- member(b, [a,b,c]).

true

?- \+ member(b, [a,b,c]).

false.

?- not(member(b, [a,b,c])).

false.

?- not(member(b, [a,c])).

true.

58

Negation as Failure: Disjoint Sets

overlap(S1,S2) :- member(X,S1),member(X,S2).

disjoint(S1,S2) :- \+(overlap(S1,S2)).

?- overlap([a,b,c],[c,d,e]).

true

?- overlap([a,b,c],[d,e,f]).

false

?- disjoint([a,b,c],[c,d,e]).

false

?- disjoint([a,b,c],[d,e,f]).

true

?- disjoint([a,b,c],X).

false %<---------Not what we wanted

59

Negation as Failure

overlap(S1,S2) :- member(X,S1),member(X,S2).

disjoint(S1,S2) :- \+(overlap(S1,S2)).

[trace] ?- disjoint([a,b,c],X).

Call: (7) disjoint([a, b, c], _G293) ? creep

Call: (8) overlap([a, b, c], _G293) ? creep

Call: (9) lists:member(_L230, [a, b, c]) ? creep

Exit: (9) lists:member(a, [a, b, c]) ? creep

Call: (9) lists:member(a, _G293) ? creep

Exit: (9) lists:member(a, [a|_G352]) ? creep

Exit: (8) overlap([a, b, c], [a|_G352]) ? creep

Fail: (7) disjoint([a, b, c], _G293) ? creep

false

60

Proper Use of Negation as Failure

not(G) works properly only in the following cases:

1. When G is fully instantiated at the time prolog processes thegoal not(G).

(In this case, not(G) is interpreted to mean “goal G does notsucceed”.)

2. When all variables in G are unique to G, i.e., they don’t appearelsewhere in the same clause.

(In this case, not(G(X,Y)) is interpreted to mean “There isno values of X, Y that will make G(X,Y) succeed”.)

61

Negation as Failure

woman(jane).

woman(marilyn).

famous(marilyn).

loves(john,X) :- woman(X), famous(X).

hates(john,X) :- \+ loves(john,X).

There are infinitely many women that John hates, not just Jane:

?- hates(john,jane).

true

?- hates(john,susan).

true

?- hates(john,betty).

true

...

62

Negation as Failure

woman(jane).

woman(marilyn).

famous(marilyn).

loves(john,X) :- woman(X), famous(X).

hates(john,X) :- \+ loves(john,X).

Plus John hates many things:

?- hates(john,pizza).

?- hates(john,john).

We say that the rule hates is not safe. Solution:

hates(john,X) :- woman(X), \+ loves(john,X).

woman(X) is called a guard — it protects from making unwantedinferences.

63