Prolog Call、Exit 和 Redo 不匹配指定的规则

Prolog Call, Exit and Redo not matching specified rules

我在尝试跟踪序言时遇到了一些问题。跟踪日志如下:

parent_of(X,Y).
Call: (6) parent_of(_G2780, _G2781) ? creep
Exit: (6) parent_of(warren, jerry) ? creep
X = warren
Y = jerry ;
Redo: (6) parent_of(_G2780, _G2781) ? creep
Exit: (6) parent_of(maryalice, jerry) ? creep
X = maryalice
Y = jerry ;
Redo: (6) parent_of(_G2780, _G2781) ? creep
Call: (7) brother(_G2865, _G2781) ? creep
Exit: (7) brother(jerry, kather) ? creep
Call: (7) father(_G2780, jerry) ? creep
Call: (8) parent_of(_G2780, jerry) ? creep
Exit: (8) parent_of(warren, jerry) ? creep
Call: (8) male(warren) ? creep
Exit: (8) male(warren) ? creep
Exit: (7) father(warren, jerry) ? creep
Exit: (6) parent_of(warren, kather) ? creep

但是,我声明我的事实和规则如下:

male(jerry).
male(stuart).
male(warren).
male(peter).
female(kather).
female(maryalice).
female(ann)
brother(jerry,stuart).
brother(jerry,kather).
brother(peter, warren).
sister(ann, maryalice).
sister(kather,jerry).
parent_of(warren,jerry).
parent_of(maryalice,jerry).

parent_of(X,Z):- brother(Y,Z),(father(X,Y);mother(X,Y)).
father(X,Y) :-  parent_of(X,Y), male(X).
mother(X,Y) :-  parent_of(X,Y), female(X).

我以为第一个Call按理应该处死哥哥和(爸爸妈妈)?怎么马上给了我 Exit 是 Warren 是 Jerry 的parent?

提前致谢!

Prolog 按照声明的顺序查找事实和规则。由于您在规则 parent_of/2 之前声明了一些事实 parent_of/2,因此首先会找到这些事实。你没有显示你的完整踪迹,但它找到事实后,它追踪到规则:

[trace]  ?- parent_of(X,Y).
   Call: (7) parent_of(_G1353, _G1354) ? creep
   Exit: (7) parent_of(warren, jerry) ? creep
X = warren,
Y = jerry ;
   Redo: (7) parent_of(_G1353, _G1354) ? creep
   Exit: (7) parent_of(maryalice, jerry) ? creep
X = maryalice,
Y = jerry ;
   Redo: (7) parent_of(_G1353, _G1354) ? creep
   Call: (8) brother(_G1444, _G1354) ? creep
   Exit: (8) brother(jerry, stuart) ? creep
   Call: (8) father(_G1353, jerry) ? creep
   Call: (9) parent_of(_G1353, jerry) ? creep
   Exit: (9) parent_of(warren, jerry) ? creep
   Call: (9) male(warren) ? creep
   Exit: (9) male(warren) ? creep
   Exit: (8) father(warren, jerry) ? creep
   Exit: (7) parent_of(warren, stuart) ? creep
X = warren,
Y = stuart ;
   Redo: (9) parent_of(_G1353, jerry) ? creep
   Exit: (9) parent_of(maryalice, jerry) ? creep
   Call: (9) male(maryalice) ? creep
   Fail: (9) male(maryalice) ? creep
   Redo: (9) parent_of(_G1353, jerry) ? creep
   Call: (10) brother(_G1444, jerry) ? creep
   Fail: (10) brother(_G1444, jerry) ? creep
   Fail: (9) parent_of(_G1353, jerry) ? creep
   Fail: (8) father(_G1353, jerry) ? creep
   Redo: (7) parent_of(_G1353, stuart) ? creep
   Call: (8) mother(_G1353, jerry) ? creep
   Call: (9) parent_of(_G1353, jerry) ? creep
   Exit: (9) parent_of(warren, jerry) ? creep
   Call: (9) female(warren) ? creep
   Fail: (9) female(warren) ? creep
   Redo: (9) parent_of(_G1353, jerry) ? creep
   Exit: (9) parent_of(maryalice, jerry) ? creep
   Call: (9) female(maryalice) ? creep
   Exit: (9) female(maryalice) ? creep
   Exit: (8) mother(maryalice, jerry) ? creep
   Exit: (7) parent_of(maryalice, stuart) ? creep
X = maryalice,
Y = stuart
...

不过,我建议您将规则名称设为不同于事实名称。所以我会做类似的事情:

parent(warren,jerry).
parent(maryalice,jerry).

然后:

parent_of(X,Z) :-
    parent(X, Z).
parent_of(X,Z) :-
    brother(Y,Z),
    ( father(X,Y); mother(X,Y) ).

但也要注意多余的事实。看起来您的 parent 关系可能已经由涉及 father/2mother/2 的事实定义。所以不清楚你为什么需要 parent/2 事实。

请注意,您的代码在此处存在语法错误:

female(ann)
brother(jerry,stuart).

您可能忽略了这个错误。但是如果没有句点,Prolog 将忽略以上两个事实,然后给出您所看到的结果。


另一方面,您的代码有很多不好的循环逻辑。 parent_of/2 依赖于 father/2mother/2 然后 father/2mother/2 调用 parent_of/2。这是将事实与谓词分开的另一个重要原因。