序言 - 无限规则

时间:2011-06-24 18:08:19

标签: prolog successor-arithmetics

我有下一个规则

% Signature: natural_number(N)/1
% Purpose: N is a natural number.
natural_number(0).
natural_number(s(X)) :-
   natural_number(X).

ackermann(0, N, s(N)). % rule 1
ackermann(s(M),0,Result):-
   ackermann(M,s(0),Result). % rule 2
ackermann(s(M),s(N),Result):-
   ackermann(M,Result1,Result),
   ackermann(s(M),N,Result1). % rule 3

查询为:ackermann (M,N,s(s(0)))

现在,据我所知,在第三次计算中,我们得到了一个无限的搜索(失败分支)。我检查一下,我得到了一个有限的搜索(失败分支)。

我将解释:在第一个中,我们得到了M = 0,N = s(0)的替换(规则1 - 成功!)。在第二个中,我们得到M = s(0)的替换,N = 0(规则2 - 成功!)。但现在呢?我尝试匹配M = s(s(0))N = 0,但它有一个有限搜索 - 失败分支。编译器为什么不写“失败”。

谢谢。

2 个答案:

答案 0 :(得分:8)

答案 1 :(得分:5)

让我重新解释一下你的问题:查询ackermann(M,N,s(s(0))).找到两个解决方案然后循环。理想情况下,它会在这两个解决方案之后终止,因为没有其他NM的值为s(s(0))

那为什么查询不会普遍终止?理解这一点可能非常复杂,最好的建议是尝试理解精确的执行机制。有一个非常简单的原因:Prolog的执行机制结果是复杂的,如果你试图通过代码来理解它,你很容易误解它。

相反,您可以尝试以下操作:在程序中的任何位置插入目标false。如果生成的程序没有终止,那么原始程序也不会终止。

在你的情况下:

ackermann(0, N, s(N)) :- false.
ackermann(s(M),0,Result):- false,
   ackermann(M,s(0),Result).
ackermann(s(M),s(N),Result):-
   ackermann(M,Result1,Result), false,
   ackermann(s(M),N,Result1).

我们现在可以删除第一条和第二条规则。在第三条规则中,我们可以在错误后删除目标。因此,如果以下片段没有终止,原始程序也不会终止。

ackermann(s(M),s(N),Result):-ackermann(M,Result1,Result), false.

此程序现在仅在第一个参数已知时终止。但在我们的情况下它是免费的......

即:通过考虑程序的一小部分,我们已经能够推断出整个程序的属性。有关详细信息,请参阅网站上的this paper和其他人。

不幸的是,这种推理仅适用于非终止案件。对于终止,事情更复杂。最好的方法是尝试像cTI这样的工具,它可以推断终止条件,并试图证明它们的最优性。我已经输入你的程序,所以尝试修改if和看到效果!

如果我们在这里:这个小片段还告诉我们第二个参数不会影响终止 1 。这意味着,像ackermann(s(s(0)),s(s(0)),R).这样的查询会 也不会终止。交换目标,看看差异......


1确切地说,不与s(_)统一的术语将影响终止。想想0。但任何s(0)s(s(0)),......都不会影响终止。