这个查询的SLD树是什么?

时间:2012-10-31 16:43:38

标签: prolog successor-arithmetics prolog-cut

让我们考虑下面的Prolog程序(来自“The Prolog”):

natural_number(0).
natural_number(s(X)) :- natural_number(X).

plus(X, 0, X) :- natural_number(X).
plus(X, s(Y), s(Z)) :- plus(X, Y, Z).

和查询:

?- plus(s(s(s(0))), s(0), Z).

SICStus和SWI都会产生预期的Z = s(s(s(s(0))))答案,但会向用户询问下一个答案(正确的no / false答案)。但是,我无法理解为什么在找到唯一目标后SLD树中存在一个开放分支。我尝试在SICStus和SWI下调试,但我还不能解释结果。我只能说,据我所知,两者都回溯到plus(s(s(s(0))), 0, _Z2)。有人可以帮我理解这种行为吗?

3 个答案:

答案 0 :(得分:3)

许多Prolog系统并不像我们期望的那样聪明。这有几个原因,主要是因为实施者的权衡选择。对某些人来说重要的事情对其他人来说可能并不重要。

因此,这些剩余的选择点可能会及时累积并阻止释放辅助数据。例如,当您想要读取一长串文本时。一个列表,它一次不适合内存,但仍然可以使用library(pio)高效处理。

如果您只想要一个答案,可以使用call_semidet/1来确定答案。 有关其定义和用例,请参阅this answer

?- plus(s(s(s(0))), s(0), Z).
Z = s(s(s(s(0)))) ;
false.

?- call_semidet(plus(s(s(s(0))), s(0), Z)).
Z = s(s(s(s(0)))).

但你也可以从一个更乐观的方面看到它:现代的toplevels(如SWI中的那个)确实会在有剩余的选择点时向你展示。因此,您可以考虑一些对策,例如call_semidet/1

以下是一些相关的答案:

答案 1 :(得分:1)

对我们来说,很明显,加号的两个条款是“析取的”。我们可以说,因为我们知道0 \= s(Y)。但是(我认为)这样的分析一般都是令人望而却步的,Prolog然后认为这样的分支仍有待证明:这里有一条迹象表明,在找到第一个解决方案之后,调用(7)对于替代方案仍然是“开放的”。

enter image description here

答案 2 :(得分:1)

问题与SLD树没有直接关系,因为Prolog 系统不会以预先的方式构建SLD树 你形容它。但在某些Prolog中发现了一些优化 系统基本上具有这种效果并改变了盲目的暴力 强制头匹配。即索引和选择点消除。

现在有一个已知的SWI-Prolog限制。虽然确实如此 多参数索引,它不做选择点消除 对于非第一个参数索引级联索引。手段 它只挑选一个参数,但后来没有进一步。有一些 Prolog系统执行多参数索引和级联索引。 例如,在Jekejeke Prolog中我们没有No / false:

Peano Cascade

再见

P.S。:Jekejeke Prolog的最新版本甚至没有 字面上级联,因为它检测到第一个参数索引 没有敏感性。因此,虽然它建立索引 由于实际的调用模式,第一个参数,它跳过了 第一个参数索引并不使用它,并且仅使用 第二个论点。跳过给出了一点速度。 : - )

通过dump/1命令可以看到跳过 开发环境版本:

?- dump(plus/3).
-------- plus/3 ---------
length=2
arg=0
  =length=2
arg=1
  0=length=1
  s=length=1
Yes

所以它没有降级到arg=0并构建了arg=1 索引那里,而是并行构建arg=0和 一个arg=1索引。我们仍然可以称之为启发式级联 因为个别查询会导致多个索引,但它们 没有真正的级联形状。