什么';此查询的SLD树是什么? 让我们考虑下面的Prolog程序(来自Prolog的艺术):
以及查询:什么';此查询的SLD树是什么? 让我们考虑下面的Prolog程序(来自Prolog的艺术):,prolog,successor-arithmetics,prolog-cut,Prolog,Successor Arithmetics,Prolog Cut,以及查询: ?- plus(s(s(s(0))), s(0), Z). SICStus和SWI都会生成预期的Z=s(s(s(s(0))答案,但向用户查询下一个答案(正确的no/false答案)。但是,我无法理解为什么在找到唯一目标后SLD树中会有一个打开的分支。我尝试在SICStus和SWI下进行调试,但我还不能真正解释结果。我只能说,就我所能理解的,两者都回到了加上(s(s(s(0)),0,Z2)。有人能帮我理解这种行为吗?对我们来说,很明显,加号的两个子句是“析取”的。我们可以这样说,因为
?- plus(s(s(s(0))), s(0), Z).
SICStus和SWI都会生成预期的
Z=s(s(s(s(0))
答案,但向用户查询下一个答案(正确的no
/false
答案)。但是,我无法理解为什么在找到唯一目标后SLD树中会有一个打开的分支。我尝试在SICStus和SWI下进行调试,但我还不能真正解释结果。我只能说,就我所能理解的,两者都回到了加上(s(s(s(0)),0,Z2)
。有人能帮我理解这种行为吗?对我们来说,很明显,加号的两个子句是“析取”的。我们可以这样说,因为我们知道0\=s(Y)
。但是,(我认为)这种分析通常是令人望而却步的,而PROlog则认为这样的分支仍有待证明:这里有一个跟踪,表明在找到第一个解决方案之后,调用(7)仍然是“开放”的。
问题与SLD树没有直接关系,因为Prolog 系统不会像以前那样以前瞻的方式构建SLD树 你描述它。但是在某些Prolog中发现了一些优化 系统本质上具有这种效果,改变了盲目的野蛮人 强制头部匹配。即索引和选择点消除 现在已知SWI Prolog有一个限制。尽管如此 多参数索引,它不做选择点消除 对于非第一个参数索引,使用级联索引。方法 它只选择了一个论点,但没有进一步的论证。有一些 执行多参数索引和级联索引的Prolog系统。 例如,在中,我们没有No/false: 再见 注:最新版本的Jekejeke Prolog甚至没有 字面上说是级联,因为它检测到第一个参数索引 没有敏感性。因此,尽管它为 由于实际的调用模式,第一个参数跳过 第一个参数索引,不使用它,只使用 第二个论点。跳过可以提高一点速度。:-) 通过 开发环境版本:
?- 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
索引。我们仍然可以称之为启发式级联
因为单个查询会导致多个索引,但是
没有真正的级联形状。许多Prolog系统没有我们期望的那么智能。这有几个原因,主要是因为实现者的权衡选择。对某些人来说重要的东西对其他人来说可能不那么重要 因此,这些剩余的选择点可能会及时累积,并阻止释放辅助数据。例如,当您想阅读一长串文本时。一个列表太长,无法立即放入内存,但仍然可以使用
库(pio)
高效处理
如果您只需要一个答案,您可以使用call_semidet/1
来确定答案。
有关其定义和用例,请参见
?- 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)))).
?-加(s(s(0)),s(0),Z)。
Z=s(s(s(0));
错。
?调用_semidet(加上(s(s(0)),s(0),Z))。
Z=s(s(s(0)))。
但你也可以从一个更乐观的角度来看待它:现代顶级水平(比如SWI中的顶级水平)确实会告诉你什么时候有剩余的选秀点。因此,您可以考虑一些对策,如:代码> Call SimiDt/ 1
以下是一些相关的答案:
。这也适用于……与Prolog艺术的程序3.3相比,您交换了plus/3
的第一个和第二个参数。但是就这样吧。。。
?- 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)))).