Prolog: a person is a sibling of himself?

眉间皱痕 提交于 2019-11-26 12:33:09

This is because of the way unification works. If you put difference first the values of X and Y are not yet unified to any values. Consider the trace:

 goal list: [sibling(bob, Z)]
 goal: sibling(bob, Z).
 X-> bob, Y -> Z
 goal list: [difference(bob, Y), mother(M, bob), mother(M, Y), father(F, bob), father(F, Y).]
 goal: difference(bob, Y) --SUCCESS
 goal list: [mother(M, bob), mother(M, Y), father(F, bob), father(F, Y).]
 goal: mother(M, bob)
 ...

When you put the difference call last, both X and Y have been unified and difference will fail if they are the same value. Then backtracking will occur.

Use the trace feature of your prolog environment to see what happens step by step during the execution.

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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!