【问题标题】:Prolog Call, Exit and Redo not matching specified rulesProlog Call、Exit 和 Redo 与指定规则不匹配
【发布时间】:2017-03-20 14:36:02
【问题描述】:

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

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应该执行兄弟和(父亲和母亲)?为什么它直接给了我一个出口,即 Warren 是 Jerry 的父母?

提前致谢!

【问题讨论】:

  • 您有语法错误。 female(ann) 之后需要一个句号。

标签: prolog rules


【解决方案1】:

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) ).

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

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

female(ann)
brother(jerry,stuart).

您可能忽略了该错误。但是没有句号,Prolog 会忽略以上两个事实,然后给你你看到的结果。


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

【讨论】:

  • 我看到了,但是在 X = maryalice Y = jerry 之后;对,对于第三个,我得到 X = 沃伦 Y = 凯瑟。我不知道为什么它跳过了斯图尔特,因为兄弟(杰瑞,斯图尔特)的事实是在凯瑟之前宣布的。让我更新跟踪日志。
  • @Fyndy 你的第一个事实是warrenjerrymaryalicejerry,它首先发现了这两个,按预期的顺序。它找到的下一个是warren & stuart 使用规则。当您说“它跳过斯图尔特”时,我不知道您的意思。看我的踪迹。我直接运行了你的代码。因此,如果您为第三个解决方案获得 warrenkather,则说明您没有运行您发布的代码。
  • 我试图通过读取它来追踪它,因为 2780 是 2781 的父级。2865 是 2781 的兄弟。但是在出口处,我怎么知道 2865 是 jerry 而 2781 是凯瑟?我更新了我的跟踪日志,并且我已经重新运行了几次,但我仍然得到了凯瑟。
  • @Fyndy 这些数字只对应于匿名变量名,在实例化之前它们只是变量。所以数字直接对应你的原子。它们只是用于区分它们的变量的任意数字。你用的是什么Prolog? SWI?还有什么?什么版本?我完全按照您在 SWI 中的问题中显示的方式运行了代码,并且得到了答案中显示的结果。因此,请仔细检查您实际使用的代码。
  • @Fyndy 我想我可能知道问题所在。您在female(ann) 中留下句号时出现语法错误。结果,Prolog 没有认识到这个事实,也没有认识到下面的事实,brother(jerry,stuart).。我在运行您的代码时已修复该错误,因此我没有观察到与您相同的结果。
猜你喜欢
  • 1970-01-01
  • 2015-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
相关资源
最近更新 更多