我开始学习序言和第一次了解继任符号。
而这正是我了解在序言写皮亚诺公理。
参见第12页PDF :
sum(0, M, M).
sum(s(N), M, s(K)) :-
sum(N,M,K).
prod(0,M,0).
prod(s(N), M, P) :-
prod(N,M,K),
sum(K,M,P).
我把乘法法则为序言。 然后,我做了查询:
?- prod(X,Y,s(s(s(s(s(s(0))))))).
这意味着找到6的基本因素。
下面是结果。
X = s(0),
Y = s(s(s(s(s(s(0)))))) ? ;
X = s(s(0)),
Y = s(s(s(0))) ? ;
X = s(s(s(0))),
Y = s(s(0)) ? ;
infinite loop
这个结果有两个问题:
- 不是所有的结果被示出,请注意,结果X = 6,Y = 1缺失。
- 它不会停止,除非我按Ctrl + C,然后选择退出。
所以...我的问题是:
- 这是为什么? 我试图切换“刺”和“和”左右。 生成的代码给了我所有的结果。 再次,这是为什么? 它还虽然死循环。
- 如何解决?
我读了无限循环,对方的回答。 不过,我会很感激的人回答在此基础上的场景。 它极大地帮助我。
如果你想深入研究终止性质,使用程序的继任者,算术是一个理想的研究对象:你知道先验他们应该说明一下,这样你就可以专注于更多的技术细节。 你需要了解几个概念。
通用终止
解释它最简单的方法,就是要考虑Goal, false
。 这将终止当且仅当Goal
终止普遍。 那就是:看着示踪剂是最无效的方法 - 他们会告诉你只有一个执行路径。 但是,你需要了解所有的人都在一次! 也从来不看答案,当你想终止普遍,他们只会让你分心。 你已经看到它上面:你有三个整齐和正确答案,只有你的程序循环。 因此,更好地“关闭”的答案与false
。 这将删除所有分心。
故障片
需要的下一个概念是,一个的故障片 。 以一个纯粹的单调逻辑程序,并扔在一些目标false
。 如果导致故障的片不会终止(通用),也将原来的程序不会。 在您为例,可以考虑:
prod(0,M,0) :- false.
prod(s(N), M, P) :-
prod(N,M,K), false,
sum(K,M,P).
这些false
目标,有助于消除在你的程序无关的装饰品:剩余部分显示你清楚,为什么prod(X,Y,s(s(s(s(s(s(0))))))).
不会终止。 它不会终止,因为碎片不关心P
在所有! 你希望的是,第三个参数将有助于使prod/3
中止,但片段显示了你,这是一切都是徒劳的,因为P
不以任何目标发生。 无需繁琐的示踪剂。
往往是不那么容易找到最小的故障片。 但是,一旦你找到一个,它旁边的琐碎,以确定其终止或者说未结束的属性。 一段时间后,你可以用你的直觉想象一个切片,然后你可以用你的理由来检查,如果该片是相关的或不是。
什么是如此显着的了解失败的切片的概念是这样的:如果你想提高节目, 你在参加上述片段可见来修改你的程序! 只要你不改变它,这个问题将长期存在。 故障切片因此你的程序非常相关部分。
终止推断
这是你需要的最后一件事:一个终止inferencer(或分析器),如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)terminates_if 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) :- false.
prod2(s(N), M, P) :-
sum(M, K, P),
prod2(N,M,K), false.
sum(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)
优雅的终止......
第一个问题(为什么),是很容易被发现,特别是如果知道左递归 。 sum(A,B,C)
结合当C 结合 A和B,但原始程序PROD(A,B,C)不使用绑定,以及不是与静止A,B未结合的递归。
如果我们换总和,督促我们从总和递归调用2个有用的绑定:
sum(M, K, P)
现在,M是装订成册,将用于终止左递归。 我们可以换N和M,因为我们知道,产品是可交换的。
sum(0, M, M).
sum(s(N), M, s(K)) :-
sum(N, M, K).
prod3(0, _, 0).
prod3(s(N), M, P) :-
sum(M, K, P),
prod3(M, N, K).
需要注意的是,如果我们换M,K(即总和(K,M,P)),当prod3被称为以P未知,我们再有一个非终止循环,但总和。
?- prod3(X,Y,s(s(s(s(s(s(0))))))).
X = s(s(s(s(s(s(0)))))),
Y = s(0) ;
X = s(s(s(0))),
Y = s(s(0)) ;
X = s(s(0)),
Y = s(s(s(0))) ;
X = s(0),
Y = s(s(s(s(s(s(0)))))) ;
false.
OT我被CTI困惑报告:prod3(A,B,C)terminates_if B(A),B(B); B(A),B(C)。