Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
221 views
in Technique[技术] by (71.8m points)

Prolog: a person is a sibling of himself?

I'm having some trouble understanding why my code in prolog does something based on the order I put my rules in.

Here is my database:

parent(tom, bob).
parent(tom, liz).
parent(mary, bob).
parent(mary, liz).

male(tom).
male(bob).
female(mary).
female(liz).

And here are the rules:

%difference(X, Y) ==> Predicate to check if two people X and Y are not the same person.
difference(X, Y) :- ==(X, Y).
father(X, Y) :- male(X), parent(X, Y), difference(X, Y).
mother(X, Y) :- female(X), parent(X, Y), difference(X, Y).
sibling(X, Y) :-
    difference(X, Y),
    mother(M, X), mother(M, Y),
    father(F, X), father(F, Y).

The problem is that when I do this,

?- sibling(bob, X).

I get

X = bob ;
X = liz ;
false.

But when I change the ordering (I put difference(X, Y) at the last part)

sibling(X, Y) :-
    mother(M, X), mother(M, Y),
    father(F, X), father(F, Y),
    difference(X, Y).

and I call

?- sibling(bob, X).

I get

X = liz;
false.

which is what I want.

So far, I've only seen that the ordering of the rules matter when doing recursion. So I don't understand how bob is still a sibling of himself just because I put the difference check first.

Thanks for any help!

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The actual reason for your problem is (==)/2 within different/2. It succeeds simply too often. Replace it with dif/2 and you will get the expected behavior. dif/2 is available in many Prolog systems like SICStus, YAP, B, SWI. You can also define a safe approximation in ISO-Prolog like so:

iso_dif(X, Y) :-
   X == Y,
   ( X = Y -> true
   ; throw(error(instantiation_error,iso_dif/2))
   ).

Now, should the arguments be not sufficiently instantiated, you will get an Instantiation Error. Prolog aborts the computation and says: I have no idea! Which is far better than pretending it does have an idea while it has none.

Using iso_dif/2 you will still have to place it at the end of the rule. But this time, Prolog will keep an eye on its correct usage.

| ?- iso_dif(a,b).

yes
| ?- iso_dif([a,_],[b,_]).

(8 ms) yes
| ?- iso_dif([a,X],[X,b]).

yes
| ?- iso_dif([a,X],[a,X]).

no
| ?- iso_dif([a,X],[X,X]).
uncaught exception: error(instantiation_error,iso_dif/2)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...