无法理解为什么序言会无限循环
Can't understand why is prolog looping infinitly
来自 Bratko 的书,Prolog Programming for Artificial Intelligence (4th Edition)
我们有以下不起作用的代码 -
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
anc4(X,Z):-
parent(X,Z).
书中第 55 页的图 2.15 显示 parent(Y,Z)
一直调用,直到堆栈内存不足。
我不明白的是 prolog 对 anc4(X,Y) 进行递归调用,而不是首先对父级 (Y,Z) 进行递归调用。为什么 prolog 不一遍又一遍地转到 第一行 、anc4(X,Y)
,而是转到第二行?
能否请您详细说明为什么一直调用 parent(Y,Z)
行?
谢谢。
如果没有 tabling 机制,Prolog 默认无法处理左递归。只有一些 Prolog 系统支持制表,通常您需要显式声明哪些谓词被制表。
如果您使用的是XSB、YAP 或 SWI-Prolog,尝试在包含 anc4/2
谓词定义的源文件顶部添加以下指令:
:- table(anc4/2).
然后重试您的查询。制表机制检测查询何时调用自身的 variant (*) 并暂停执行该分支,直到找到查询答案并尝试另一个分支(在您的案例中由第二条)。如果发生这种情况,将使用该答案恢复执行。
(*)这里的变体是指两个项在变量重命名时相等。
您的 'problem'(即目标顺序)的起源深深植根于语言的基础。
Prolog基于简单高效的时间顺序回溯策略,实现了SLD resolution,左递归子句,如anc4/2
,导致无限递归。
实际上,逗号运算符 (,)/2
代表
evaluate the right expression only if the left expression holds
因此,子句中目标的顺序实际上是程序的重要组成部分。
对于您的具体案例,
... , parent(Y,Z).
如果
则无法调用
anc4(X,Y),
不成立。
目标顺序的对应项是子句顺序。
即从句交换后整个程序的语义不同:
anc4(X,Z):-
parent(X,Z).
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
为了更好地理解问题,我认为也值得尝试这个定义。
来自 Bratko 的书,Prolog Programming for Artificial Intelligence (4th Edition) 我们有以下不起作用的代码 -
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
anc4(X,Z):-
parent(X,Z).
书中第 55 页的图 2.15 显示 parent(Y,Z)
一直调用,直到堆栈内存不足。
我不明白的是 prolog 对 anc4(X,Y) 进行递归调用,而不是首先对父级 (Y,Z) 进行递归调用。为什么 prolog 不一遍又一遍地转到 第一行 、anc4(X,Y)
,而是转到第二行?
能否请您详细说明为什么一直调用 parent(Y,Z)
行?
谢谢。
如果没有 tabling 机制,Prolog 默认无法处理左递归。只有一些 Prolog 系统支持制表,通常您需要显式声明哪些谓词被制表。
如果您使用的是XSB、YAP 或 SWI-Prolog,尝试在包含 anc4/2
谓词定义的源文件顶部添加以下指令:
:- table(anc4/2).
然后重试您的查询。制表机制检测查询何时调用自身的 variant (*) 并暂停执行该分支,直到找到查询答案并尝试另一个分支(在您的案例中由第二条)。如果发生这种情况,将使用该答案恢复执行。
(*)这里的变体是指两个项在变量重命名时相等。
您的 'problem'(即目标顺序)的起源深深植根于语言的基础。
Prolog基于简单高效的时间顺序回溯策略,实现了SLD resolution,左递归子句,如anc4/2
,导致无限递归。
实际上,逗号运算符 (,)/2
代表
evaluate the right expression only if the left expression holds
因此,子句中目标的顺序实际上是程序的重要组成部分。
对于您的具体案例,
... , parent(Y,Z).
如果
则无法调用anc4(X,Y),
不成立。
目标顺序的对应项是子句顺序。
即从句交换后整个程序的语义不同:
anc4(X,Z):-
parent(X,Z).
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
为了更好地理解问题,我认为也值得尝试这个定义。