Prolog 查询未终止

Prolog query not terminating

这是一个非常基本的查询,但我是 prolog 的新手,无法找到此查询不终止的原因:

% fact 
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).


% rule
progeny(X, Y) :- progeny(X, Z), progeny(Z, Y).

查询progeny(dexter, X)给出了mark、bill和lisa,但没有终止。
而查询 progeny(Y, lisa) 给出了 bill 和 dexter 并且没有终止(这个查询答案也没有提到标记)。
应该注意的是,我对事实和规则使用相同的名称来测试某些值。
非常感谢对此问题的任何帮助或澄清。

您需要定义另一个谓词作为传递关系。下面的代码工作得很好(注意谓词 progenyt 是实际的传递关系)。

progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).

progenyt(X, Y) :- progeny(X, Y).
progenyt(X, Y) :- progeny(X, Z), progenyt(Z, Y).

澄清

当你写 progeny(X, Y) :- progeny(X, Z), progeny(Z, Y). 时,你会在某个时候让 prolog 尝试匹配 progeny(dexter, Y) :- progeny(dexter, lisa), progeny(lisa, Y).,这是 prolog 得到 'confused'.

的时刻

即,它将尝试将 progeny(lisa, Y) 与某些事实匹配,这对所有条目都将失败。然后,prolog 将尝试规则 progeny(lisa, Y) :- progeny(lisa, Z), progeny(Z, Y).,它要求评估 progeny(lisa, Z)。在这里你会遇到 stack overflow,因为要让 progeny(lisa, Y) 成功,progeny(lisa, Z) 也必须成功,这会导致某种无限循环,这就是为什么您的查询永远不会终止。

在我发布的解决方案中,这永远不会发生,因为 progenyt(lisa, Y) 要成功,progeny(lisa, Z) 必须成功,而这永远不会发生(所有事实都失败了)。因此,它只会产生这三个结果,然后会立即终止。

请注意,如果在最后一行交换 progenyprogenyt,查询也会 运行 进入与之前相同的问题(对于 progenyt(lisa, Y)要成功,progenyt(lisa, Z)也必须先成功,会导致无限循环)。

您也可以使用tabling。阅读我链接的文档以了解背景、解释和详细信息。

要修复程序,只需为谓词 progeny/2 添加一个 table 指令。

:- table progeny/2.

% fact
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).


% rule
progeny(X, Y) :- progeny(X, Z), progeny(Z, Y).

您现在应该得到:

?- [progeny].
true.

?- progeny(dexter, X).
X = bill ;
X = mark ;
X = lisa. % query terminates

?- progeny(Y, lisa).
Y = bill ;
Y = dexter ;
Y = mark. % no missing solutions, query terminates.