【问题标题】:Why does this command cause a stack overflow in prolog?为什么此命令会导致 prolog 中的堆栈溢出?
【发布时间】:2011-01-29 09:41:48
【问题描述】:

我有以下序言代码的sn-p:

num(0).
num(X) :- num(X1), X is X1 + 1.

fact(0,1) :-!.
fact(X,Y) :- X1 is X-1, fact(X1,Y1), !, Y is Y1 * X.

fact(X) :- num(Y), fact(Y,X).

谁能解释一下为什么下面的命令会导致堆栈溢出?提前致谢。

fact(6).

【问题讨论】:

    标签: prolog failure-slice


    【解决方案1】:

    首先,看规则

      num(0).
      num(X) :- num(X1), X is X1 + 1.
    

    谓词num(Y) 将立即对Y = 0 有效。

    因此规则

      fact(X) :- num(Y), fact(Y,X).
    

    可以简化为

      fact(X) :- fact(0,X).
    

    这将找到 fact(0,1) 的匹配项。对于X = 6,发生的情况是,因为没有规则为fact(0,6) 定义谓词,所以搜索从fact(-1,V1) 开始,然后是fact(-2,V2) 等等......直到匹配到fact(-value, Var),其中本地结果将是找到的 Var。

    这不可能发生,无限循环会消耗整个堆栈,直到触发错误。

    【讨论】:

    • 也许您应该向菜鸟指出,您分析的问题可以通过在 fact/2 的第二个子句的正文中添加 X > 0 来避免。
    【解决方案2】:

    fact(6)不终止的原因可以在下面的中找到:

    ?- 事实(6)。 num(0) :- false。 数字(X):- 数(X1),X 是 X1 + 1。 事实(X):- 数(Y),事实(Y,X)

    因为这个片段不会终止,你的原始程序也不会终止。请注意,不终止与fact/2 的定义无关!充其量,您的程序可能会成功,但永远不会(一定)失败。

    考虑使用another definition of fact/2,它也终止于fact(N, 6).

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-20
      • 1970-01-01
      • 2018-07-01
      • 2010-09-11
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      相关资源
      最近更新 更多