PROLOG堆栈溢出递归乘法

时间:2019-03-01 02:20:38

标签: prolog

multiply(A,0,0).
multiply(A,B,C) :- D is B-1, multiply(A,D,E), C is E+A.

使用此规则一次后,Prolog返回一个答案,如果我希望它继续搜索(提示A = 5?,然后单击;),则Prolog崩溃。我不明白为什么?任何人都可以解释。谢谢。

2 个答案:

答案 0 :(得分:5)

问题是

multiply(A,B,C) :- D is B-1, multiply(A,D,E), C is E+A.

此代码没有约束B > 0,该约束将防止发生堆栈溢出。

您可以将代码修改为

multiply(A,B,C) :- B > 0, D is B-1, multiply(A,D,E), C is E+A.

此外,此行multiply(A,0,0).发出单例警告,因此您可以将其更改为multiply(_,0,0)

注意:我写了约束B > 0,认为您将谓词称为multiply(5,1,A)

答案 1 :(得分:1)

以下是您可以轻松进行无限循环的方法:

?- [user].
|: loop(0). 
|: loop(X) :- X0 is X - 1, loop(X0).
|: ^D% user://1 compiled 0.01 sec, 2 clauses
true.

?- loop(3).
true ;

重做后(按;时)将返回到带有0的第二个子句。

然后X0变为-1,进入递归loop(X0),从这里开始,第一个子句将不再匹配。

尝试例如查询:

?- loop(-1).

您的无限循环版本不是尾递归的,这意味着它最终将耗尽堆栈。这是一个最小的示例:

?- [user].
|: out_of_stack(0, 0).
|: out_of_stack(X, Y) :- X0 is X - 1, out_of_stack(X0, Y0), Y is Y0 + 1.
|: ^D% user://1 compiled 0.01 sec, 2 clauses
true.

?- out_of_stack(3, R).
R = 3 ;
ERROR: Stack limit (1.0Gb) exceeded
ERROR:   Stack sizes: local: 1.0Gb, global: 19Kb, trail: 1Kb
ERROR:   Stack depth: 11,183,864, last-call: 0%, Choice points: 3
ERROR:   Possible non-terminating recursion:
ERROR:     [11,183,864] user:out_of_stack(-11183853, _5046)
ERROR:     [11,183,863] user:out_of_stack(-11183852, _5066)

这就是正在发生的事情,也是Prolog崩溃的原因。

要解决此问题,请按照其他建议进行操作。另一种解决方案是使用0s(0)s(s(0)),...表示自然数。