Prolog列表成员资格,返回多个结果

时间:2013-01-30 00:52:09

标签: prolog swi-prolog prolog-toplevel

我有一个确定列表成员资格的标准程序:

member(X, [X|_]).  
member(X, [_|T]) :- member(X, T).

我不明白为什么当我提出以下问题时:

?- member(a,[a,b]).

结果是

True;  
False.

我原本以为在使用第一条规则满足目标时(作为列表的头部)将返回True,这将是if的结束。看起来好像是在试图用第二条规则来满足目标并且失败了?

Prolog翻译是SWI-Prolog。

3 个答案:

答案 0 :(得分:6)

让我们先考虑类似的问题:[编辑:执行此操作不添加添加您自己的定义; member/2已经定义了]

?- member(a,[b,a]).
true.

在这种情况下,您将获得最佳答案:只有一个解决方案。但是当交换列表中的元素时,我们得到:

?- member(a,[a,b]).
true ;
false.

从逻辑上讲,两者都只是对查询为真的肯定。

差异的原因在于,在第二个查询中,在找到true作为列表元素后立即给出答案a。其余列表[b]不包含拟合元素,但尚未对此进行检查。只有在请求时(点击 SPACE ; ),才会尝试列表的其余部分,结果是没有进一步的解决方案。

基本上,当计算完成并且还有一些工作要做时,这个小差异会给你一个提示。对于简单查询,这没有什么区别,但在更复杂的查询中,这些开放的替代(选择点)可能会累积并耗尽内存。

老年人总是被问到是否想要进一步解决方案,即使没有解决方案。

编辑:

如果没有答案,则避免要求下一个答案的能力极其依赖于实施细节。即使在同一系统中,加载相同的程序,您也可能得到不同的结果。但是,在这种情况下,我使用了SWI的member/2内置定义,而您使用了自己的定义,它覆盖了内置定义。

SWI使用以下定义作为内置逻辑上与您的定义相同,但是避免了不必要的选择点更容易SWI - 但许多其他系统无法从中获利:

member(B, [C|A]) :-
        member_(A, B, C).

member_(_, A, A).
member_([C|A], B, _) :-
        member_(A, B, C).

使事情变得更复杂:许多Prolog有一个不同的顶层,当查询不包含变量时,它永远不会要求进一步的答案。因此,在这些系统(如YAP)中,您会得到错误的印象。

尝试以下查询来查看:

?- member(X,[1]).
X = 1.

SWI再次能够确定这是唯一的答案。但YAP,例如,不是。

答案 1 :(得分:2)

你使用的是“;”操作员在第一个结果然后推回?我相信这是要求查询查找更多结果,因为没有它会出现错误。

答案 2 :(得分:1)

你知道Prolog的剪辑 - !吗?

如果您将member(X, [X|_]).更改为member(X, [X|_]) :- !.,Prolog将不会尝试在第一个解决方案之后找到其他解决方案。