【问题标题】:Out Of Global Stack Error in PrologProlog中的全局堆栈错误
【发布时间】:2011-07-20 13:16:59
【问题描述】:

我正在尝试在 Prolog 中运行以下程序。

mama_mia1(A,M,LI,HI,LO,HO,AA) :-
   p1(A,M,LI,HI,LO,HO,PROGS),
   reverse(PROGS,PROG),
   atom_chars(AA,PROG),
   !.

p1(_,_,LO,LO,LO,_,[]).
p1(_,_,HO,HO,_,HO,[]).
p1(_,_,LO,HO,LO,HO,[]).
p1(_,_,X,LO,LO,HO,[]) :- X>LO,X<HO.
p1(_,_,X,HO,LO,HO,[]) :- X>LO,X<HO.
p1(_,_,LO,Y,LO,HO,[]) :- Y>LO,Y<HO.
p1(_,_,HO,Y,LO,HO,[]) :- Y>LO,Y<HO.
p1(_,_,X,Y,LO,HO,[]) :- X>LO,X<HO,Y>LO,Y<HO.
p1(A,M,X,Y,LO,HO,PROG) :-
   (  (X1 is X+A,  H1 is HO+1, X1<H1, Y1 is Y+A,  Y1<H1 )
   -> append(PROG1,['A'],PROG),
      p1(A,M,X1,Y1,LO,HO,PROG1)
   ;  false).
p1(A,M,X,Y,LO,HO,PROG) :-
   (  (X2 is X * M,  H1 is HO+1, X2<H1, Y2 is Y * M,  Y2<H1)
   -> append(PROG2,['M'],PROG),
      p1(A,M,X2,Y2,LO,HO,PROG2)
   ;  false).

程序应该计算从 li 和 hi 之间的每个数字到 lo 和 ho 之间的结果的适当的加法和乘法路径。加法对应字母A,乘法对应M。在程序结束时,我们应该得到对应于我们找到的路径的As和Ms字符串。

程序运行良好,但在尝试测试用例时:

mama_mia1(70000,17,2,5,89000,89900,P) 

我收到“错误:超出全局堆栈”消息。

知道代码有什么问题吗?

【问题讨论】:

    标签: prolog out-of-memory failure-slice


    【解决方案1】:

    程序运行良好,但是...

    真的吗?让我们尝试一个最小的案例:

    ?- p1(1,3,1,1,1,2,P).
       P = []
    ;  P = "A"
    ;  *LOOPS*
    

    也就是说,即使在这种非常简单的情况下,您的程序也会循环。然而,它恰好找到了两个答案!第二个答案使用library(double_quotes) 打印"A" 代替['A']

    在 Prolog 中,您不会只得到一个答案,您可能会得到几个答案...

    直接检测此类非终止问题的简单方法是在查询中添加目标false

    ?- p1(1,3,1,1,1,2,P), 。 *循环*

    我们可以将更多此类目标false 添加到您的程序中。严格来说,这只有在您的程序是纯粹的、单调的程序时才有可能。您正在使用 cut 和 if-then-else 在一般情况下它们都会破坏这些属性。但是,在您的情况下,它们可以在以下

    中被丢弃 p1(_,_,LO,LO,LO,_,[]) :- p1(_,_,HO,HO,_,HO,[]) :- p1(_,_,LO,HO,LO,HO,[]) :- p1(_,_,X,LO,LO,HO,[]) :- false, X>LO,Xp1(_,_,X,HO,LO,HO,[]) :- false, X>LO,Xp1(_,_,LO,Y,LO,HO,[]) :- false, Y>LO,Yp1(_,_,HO,Y,LO,HO,[]) :- false, Y>LO,Yp1(_,_,X,Y,LO,HO,[]) :- false, X>LO,XLO,Y . p1(A,M,X,Y,LO,HO,PROG):- ((X1 是 X+A,H1 是 HO+1,X1

    附加(PROG1,['A'],PROG),p1(A,M,X1,Y1,LO,HO,PROG1) ;错误的 )。 p1(A,M,X,Y,LO,HO,PROG) :- false, ((X2 是 X * M, H1 是 HO+1, X2

    -> 附加(PROG2,['M'],PROG), p1(A,M,X2,Y2,LO,HO,PROG2) ;假)

    考虑这个目标append(PROG1,['A'],PROG)。变量PROG1 第一次出现在这里,因此它永远不会被实例化。 PROG 也没有实例化。因此这个目标会循环。

    append(PROG1,['A'],PROG) 替换为PROG = ['A'|PROG1]。现在元素以相反的方向出现,因此不需要反转。

    查询 mama_mia1(70000,17,2,5,89000,89900,P) 现在就像 false 一样失败。

    【讨论】:

      【解决方案2】:

      错误:超出全局堆栈

      消息意味着您的程序需要更多内存。要么它陷入了某个消耗所有内存的无限循环,要么它没有任何问题并且输入太大,因此需要更多内存。

      考虑到您的输入看起来很大并且假设您已经测试了较小的输入并且没有发生问题,我会说您只需要更多的内存

      您可以扩大stack 的大小,或者您可以尝试使用更少的内存。

      当然,如果这是提交某处进行检查的某种练习,那么您可以获得的内存量可能会受到限制:b

      【讨论】:

      • 感谢您的回答。问题是,上面的输入不应该消耗那么多内存......我已经测试了更大的输入,它们工作得很好。此外,我过早收到错误消息,而在其他运行时间较长的测试用例中,我没有收到任何错误消息。
      猜你喜欢
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多