View
7
Download
0
Category
Preview:
Citation preview
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
Recommended