Out Of Global Stack Error in Prolog

徘徊边缘 提交于 2020-01-25 04:21:05

问题


I am trying to run the following program in 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).

The program should calculate an appropriate path of additions and multiplications leading from every number between li and hi to a result between lo and ho. An addition corresponds to the letter A and multiplication corresponds to M. At the end of the program we are supposed to get a string of As and Ms corresponding to the path we found.

The program runs well but when trying the test case :

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

I get an "ERROR: out of global stack " message.

Any ideas what is wrong with the code?


回答1:


The program runs well but ...

Really? Let's try out a minimal case:

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

That is, even in this very simple case your program loops. However, it happened to find two answers! The second answer uses library(double_quotes) for printing "A" in place of ['A'].

In Prolog you do not get just one answer, you may get several of them...

An easy way to directly detect such problems of non-termination is to add a goal false to your query:

?- p1(1,3,1,1,1,2,P), false.
   *LOOPS*

We can add further such goals false into your program. Strictly speaking, this is only possible if your program is a pure, monotonic one. You are using cut and if-then-else which both destroy such properties in the general case. However, in your case, they can just be discarded in the following failure-slice

p1(_,_,LO,LO,LO,_,[]) :- false.
p1(_,_,HO,HO,_,HO,[]) :- false.
p1(_,_,LO,HO,LO,HO,[]) :- false.
p1(_,_,X,LO,LO,HO,[]) :- false, X>LO,X<HO.
p1(_,_,X,HO,LO,HO,[]) :- false, X>LO,X<HO.
p1(_,_,LO,Y,LO,HO,[]) :- false, Y>LO,Y<HO.
p1(_,_,HO,Y,LO,HO,[]) :- false, Y>LO,Y<HO.
p1(_,_,X,Y,LO,HO,[]) :- false, 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), false,
      p1(A,M,X1,Y1,LO,HO,PROG1)
   ;  false ).
p1(A,M,X,Y,LO,HO,PROG) :- false,
   (  (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 ).

Consider this goal append(PROG1,['A'],PROG). The variable PROG1 occurs here for the first time and thus it is never instantiated. Also PROG is not instantiated. And thus this goal will loop.

Replace append(PROG1,['A'],PROG) by PROG = ['A'|PROG1]. Now the elements occur in opposite direction and thus no reversing is needed.

The query mama_mia1(70000,17,2,5,89000,89900,P) now simply fails just like false did.




回答2:


The

ERROR: out of global stack

message means that your program needs more memory. Either it's stuck in some infinite loop that consumes all the memory or there is nothing wrong with it and the input is just too large so it needs more memory.

Considering that your input looks quite large and assuming that you have tested smaller inputs and no problem occurred I would say that you just need more memory

You can expand the size of the stack OR you can try to use less memory.

Of course, if this is some sort of exercise submitted somewhere to be checked, there could be limits in how much memory you could get :b



来源:https://stackoverflow.com/questions/6762591/out-of-global-stack-error-in-prolog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!