如果您想深入研究终止属性,使用后继算法的程序是一个理想的研究对象:您先验地知道它们应该描述什么,因此您可以专注于更多技术细节。您将需要了解几个概念。
通用端接
解释它的最简单方法是考虑Goal, false
. 这终止了当且仅当Goal
普遍终止。那就是:查看跟踪器是最无效的方法 - 它们只会向您显示单个执行路径。但是您需要一次了解所有这些!当您想要通用终止时,也永远不要看答案,它们只会分散您的注意力。你已经在上面看到了:你得到了三个简洁而正确的答案,然后你的程序才循环。所以更好的“关闭”答案false
。这消除了所有的干扰。
故障切片
您需要的下一个概念是故障切片。取一个纯单调逻辑程序并输入一些目标false
。如果生成的故障片没有终止(普遍地),那么原始程序也不会终止。在您的示例中,请考虑:
产品(0,M,0):-假。
产品(s(N),M,P):-
产品(N,M,K),假,
总和(K,M,P)。
这些false
目标有助于删除程序中不相关的修饰:剩余部分清楚地向您展示,为什么prod(X,Y,s(s(s(s(s(s(0))))))).
不终止。它不会终止,因为那个片段根本不关心P
!您希望第三个参数有助于prod/3
终止,但该片段向您显示这一切都是徒劳的,因为P
不会出现在任何目标中。不需要健谈的示踪剂。
通常,要找到最小的故障片并不容易。但是一旦你找到了一个,确定它的终止或非终止属性几乎是微不足道的。一段时间后,你可以用你的直觉想象一个切片,然后你可以用你的理由来检查那个切片是否相关。
失败片的概念如此引人注目的地方在于:如果你想改进程序,你必须在上面片段中可见的部分修改你的程序!只要你不改变它,问题就会一直存在。因此,故障片是程序中非常相关的部分。
终止推断
这是您需要的最后一件事:像cTI这样的终止推断器(或分析器)将帮助您快速识别终止条件。看看推断的终止条件prod/3
和改进的prod2/3
这里!
编辑:由于这是一个家庭作业问题,我没有发布最终解决方案。但为了清楚起见,这里是迄今为止获得的终止条件:
prod(A,B,C)terminates_if b(A),b(B)。
prod2(A,B,C)terminates_if b(A),b(B); b(A),b(C)。
所以新prod2/3
的严格比原来的程序好!
现在,由您决定最终程序。其终止条件为:
prod3(A,B,C) 终止_如果 b(A),b(B);b(C)。
首先,尝试找到prod2(A,B,s(s(s(s(s(s(0)))))))
! 我们预计它会终止,但它仍然没有。所以采取程序并手动添加false
目标!剩下的部分会告诉你关键!
最后提示:您需要添加一个额外的目标和一个事实。
编辑:根据要求,这里是失败切片prod2(A,B,s(s(s(s(s(s(0)))))))
:
prod2(0,_,0) :-假。
产品 2(s(N),M,P):-
总和(M,K,P),
产品 2(N,M,K),假。
总和(0,M,M)。
sum(s(N), M, s(K)) :- false ,
sum(N,M,K)。
请注意显着简化的定义sum/3
。它只说:0加上任何东西就是任何东西。不再。因此,即使是更专业的也会在优雅地终止prod2(A,0,s(s(s(s(s(s(0)))))))
时循环......prod2(0,X,Y)