无法理解为什么prolog无限循环

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法理解为什么prolog无限循环相关的知识,希望对你有一定的参考价值。

从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)进行recursiv调用,而不是父对象(Y,Z)。为什么prolog不会反复到第一行,anc4(X,Y),而是转到第二行?

你能详细说明为什么parent(Y,Z)这条线被称为?

谢谢。

答案

你的“问题”(即目标顺序)的起源深深植根于语言的基础。

Prolog基于时间顺序回溯的简单而有效的策略,实现SLD resolution,并且像anc4/2一样留下递归子句,导致无限递归。实际上,逗号运算符(,)/2代表

仅当左表达式成立时才评估正确的表达式

因此,条款中的目标顺序实际上是该计划的重要部分。

对于你的具体案例,

... , parent(Y,Z).

如果不能被调用

anc4(X,Y), 

不成立。

目标顺序的对应物是子句顺序。

也就是说,在交换子句之后,整个程序具有不同的语义:

anc4(X,Z):-
    parent(X,Z).
anc4(X,Z):-
    anc4(X,Y),
    parent(Y,Z).

为了更好地理解这个问题,我认为也值得尝试这个定义。

另一答案

没有表格机制,Prolog默认不能处理左递归。只有一些Prolog系统支持表格,通常你需要明确声明哪些谓词被列表。

如果你正在使用例如XSB,YAP或SWI-Prolog,尝试在包含anc4/2谓词定义的源文件之上添加以下指令:

:- table(anc4/2).

并重试您的查询。 tabling机制检测查询何时调用自身的变量(*)并暂停执行该分支,直到找到查询答案并尝试替代分支(在第二个子句的情况下提供)。如果发生这种情况,则使用该答案恢复执行。

(*)这里的变量意味着在变量重命名时两个术语相等。

以上是关于无法理解为什么prolog无限循环的主要内容,如果未能解决你的问题,请参考以下文章

超出堆栈限制(0.2Gb)...可能无限递归(循环):

为啥for循环在c中无限进行

Knight's Tour 代码陷入无限循环,无法解决

Prolog 如何通过交错将列表列表构造成单个列表?

Prolog Eliza 实现 - 循环和递归

为啥这个回调会产生无限循环