超出堆栈限制(0.2Gb)...可能的无限递归(周期):

时间:2019-05-28 04:00:49

标签: recursion stack limit infinite-loop swi-prolog

Prolog相当新,但是我正在尝试实现无上下文语法,并且在通过具有我自己的规则的测试用例时遇到问题。

我尝试更改规则的顺序以使其看起来在逻辑上更正确,但是我似乎无法获得一致的正确输出,并且我继续遇到相同的堆栈错误。我认为这与vp --> vp, np.递归有关,但是如果是这种情况,那么为什么np --> np, pp.也没有给我一个错误?我的代码如下:

:- use_module(library(tabling)).
:- table s/2.

s --> np, vp.
np --> det, n.
np --> np, pp.
vp --> vp, pp.
vp --> v, np.
pp --> p, np.

det --> [the].
n --> [cop].
n --> [criminal].
n --> [street].
v --> [chased].

p --> [in].
p --> [by].

将此问题理想地返回给查询应返回 true

$- s([the,cop,chased,the,criminal], []).

并要求其返回 false

$- s([the, cop, the, criminal, chased], []).

我都尝试过,但它们都给了我相同的错误:

Stack limit (0.2Gb) exceeded
  Stack sizes: local: 0.2Gb, global: 22Kb, trail: 5Kb
  Stack depth: 1,561,893, last-call: 0%, Choice points: 1,561,869
  Probable infinite recursion (cycle):
    [1,561,893] vp([length:3], _1424)
    [1,561,892] vp([length:3], _1456)

任何反馈表示赞赏!

1 个答案:

答案 0 :(得分:2)

问题在于您已经构建了left recursive grammar。确实,如果我们查看您定义的规则,就会看到:

:- use_module(library(tabling)).
:- table s/2.

s --> np, vp.
np --> det, n.
np --> np, pp.
vp --> vp, pp.
vp --> v, np.
pp --> p, np.

det --> [the].
n --> [cop].
n --> [criminal].
n --> [street].
v --> [chased].

p --> [in].
p --> [by].

现在基于Prolog实现谓词的方式,它无法使用这种左递归语法,因为如果您调用np/2,它将首先调用np/2,因此我们永远不会脱离“循环”(直到调用堆栈溢出)。

不过,我们可以在这里使用tabling,就像您对s/2所做的那样,这是没有必要的,因为s中没有左递归路径可以直接或间接产生( )s --> s, ...。我们需要表np/2vp/2,例如:

:- use_module(library(tabling)).
:- table np/2.
:- table vp/2.

s --> np, vp.
np --> det, n.
np --> np, pp.
vp --> vp, pp.
vp --> v, np.
pp --> p, np.

det --> [the].
n --> [cop].
n --> [criminal].
n --> [street].
v --> [chased].

p --> [in].
p --> [by].

然后,我们确实可以获得预期的结果:

?- s([the,cop,chased,the,criminal], []).
true.

?- s([the, cop, the, criminal, chased], []).
false.