继承算术的力量 - 如何防止无限循环? [序言]

时间:2016-10-15 20:34:28

标签: prolog exponentiation successor-arithmetics

我整天都在考虑这个问题。 我终于承认,我不理解Prolog和我想的一样好。

在一天开始时,我无法实现后续算术,它将2个s-Numbers相乘,其结构如下:

nat(0).
nat(s(X)):-nat(X).

我的第一次尝试就是:

 mul(0,_,0).
 mul(s(F1),F2,P):-mul(F1,F2,Tmp),add(F2,Tmp,P)

有效,但查询mul(X,Y,s(0))以无限循环结束。为什么? 我已阅读以下帖子:Prolog successor notation yields incomplete result and infinite loop

我理解的是:如果我在调用add之前调用mul,并且mul / 3谓词中的变量在mul / 3调用中都没有使用,Prolog会尝试为它所做的变量找到新的可能性没约束。因此它会进入一个无限循环。

为了解决这个问题,我先调用add:

mul(0,_,0).
mul(s(F1),F2,P):-add(F2,Tmp,P),mul(F2,F1,Tmp).

那就做到了。 然后我尝试实现幂函数,并想“嗯,现在这很容易,首先尝试将是:

pow(_,0,s(0)).
pow(B,s(E),R):-pow(B,E,Tmp), mul(Tmp,B,R).

但是,我必须先把mul放在一起以防止R和Tmp的左递归。

容易!“男孩,我错了。 我不知道如何在不进入无限循环的情况下实现它,即使我将mul放在前面。

非常感谢任何建议。你可以保存我星期六的工作努力并增强我的自尊心!提前谢谢。

编辑:添加了我缺少的和谓词:

add(0, Y, Y).
add(s(S1), S2, s(Sum)):-  add(S1,S2,Sum).

1 个答案:

答案 0 :(得分:4)

我们希望以下终止条件成立:

pow(B, E, P) terminates_if b(B), b(E).
pow(B, E, P) terminates_if b(P).

或简要

pow(B, E, P) terminates_if b(B), b(E) ; b(P).

我们不能要求更多。除此之外,仅b(B)或仅b(E)。但在这些情况下,我们需要无限多的答案,这意味着不会终止。当然,我们可以采用始终终止的定义,并且对于所有测试用例都会成功,例如

  

pow(_B,_E,_P)。

唉,对于我们不想要的任何其他情况,该定义也会成功。因此,除非您只接受成功测试,否则您必须采用更详细的定义。

避免不终止的另一种方法是采用自然数的另一种定义。使用library(clpz)(SWI' s library(clpfd)是一个较弱的前兆)

pow(B, E, P) :-
   B #>= 0,
   E #>= 0,
   P #= B^E.

但目前,我们坚持继承算术。 CapelliC已经为您提供了b(B), b(E)终止的定义。所以,让我们试着改进吧!一种方法是以某种方式使用P将推理数限制为有限数。一种方法是考虑参数之间的关系。

pow/3的论点之间是否有任何有趣的关系?我真的很想那样:

  

b e ≥e,b e ≥b对于e,b≥0

几乎是真的。事实上,它增加了b≥2。

为了确保我会检查我并非完全错误,我会尝试一下 1

?- M #= 10^150, [B,E,P]ins 0..M, P #= B^E, B #>= 2, P #< E.
false.

我会认为这是一个证明,虽然它不是一个。

现在进行定义。这个想法是通过添加额外的参数来限制递归的数量来处理一般情况。 LP的一个限制powLM的一个限制mult。这些参数由额外的空格分隔,以明确它们的添加位置。

pow(_, 0, s(0)).
pow(0, s(_), 0).
pow(s(B), s(0), s(B)).
pow(s(0), s(s(_)), s(0)).
pow(B, E, P) :-
   B = s(s(_)), E = s(s(_)), P = s(s(s(s(_)))), 
   powx(B, E, P,     P, P).
%                    ^^^^^ added arguments to limit pow and mult

sum(0, M, M).
sum(s(N), M, s(K)) :-
    sum(N, M, K).

mul(0,_,0,_).
mul(s(F1),F2,P,    s(LM)) :-
   mul(F1,F2,Tmp,    LM),
   sum(Tmp, F2, P).   % note: arguments exchanged!

powx(_,0,s(0),    _, _).
powx(B,s(E),R,    s(LP), LM) :-
   powx(B,E,Tmp,     LP, LM),
   mul(Tmp,B,R,      LM).

对于简单案例pow(b,b,f),开销应该是最小的。对于新案例,pow(f,f,b)可以通过某种方式降低限制来减少开销。

脚注

1我只用10 150 试了一下。没有一般证据。让我们希望它没事。出于某种原因,较大的值会产生stackoverflow™。这是导致大量重新计算的最后一个目标P #< E。否则它最多可达10 10 7