为什么Prolog在筛选列表时会找到很多解决方案?

为什么Prolog在筛选列表时会找到很多解决方案?,prolog,Prolog,我写了一个谓词,它过滤6以下所有数字的列表,但是prolog找到了不止一个解决方案 谓词如下所示: sift([], []). sift([H | T], [H | Res]):- H > 6, sift(T, Res). sift([_ | T], Res):- sift(T, Res). 我这样问:?-sift[1,7,2,13],X 其结果是: X = [7, 13] X = [7] X = [13] X = [] 我只期望X=[7,13],那么为什么Prolog

我写了一个谓词,它过滤6以下所有数字的列表,但是prolog找到了不止一个解决方案

谓词如下所示:

sift([], []).
sift([H | T], [H | Res]):- H > 6,
    sift(T, Res).
sift([_ | T], Res):-
    sift(T, Res).
我这样问:?-sift[1,7,2,13],X

其结果是:

X = [7, 13]
X = [7]
X = [13]
X = []
我只期望X=[7,13],那么为什么Prolog会找到所有这些额外的答案呢?

回溯

当您键入sift[1,10],X时,Prolog能够模式匹配sift[H | T]、[H | Res]和sift[|T],Res。这意味着Prolog离开一个选择点,选择一个选项,然后返回到另一个谓词

Prolog匹配第一个谓词sift[7,2,13],[H | Res],进一步调用sift[1,13],Res

但是,它还与第二个谓词sift[|[2,13]]Res匹配,稍后将返回到该谓词,跳过7

如果我们想过滤掉元素,只需跳过元素就可以解决这个问题

sift([], []).
sift([H | T], [H | Res]) :-
    H >= 6,
    sift(T, Res).
sift([H | T], Res) :-
    H < 6,
    sift(T, Res).
另一种方法是在以下情况下使用序言:

这个谓词说“拿一个列表和一个可能的答案。如果第一个元素等于或大于6,则列表的第一个元素和答案应匹配,过滤后的尾部应与答案的尾部匹配。否则,列表的尾部需要能够生成整个答案”

这样可以避免回溯,并在第一次回溯后停止搜索解决方案

?- sift2([1, 7, 2, 13], X).
X = [7, 13].
用trace查看这两个谓词。已打开以获取进一步的描述

sift2([], []).
sift2([H | T], [H2 | T2]) :-
    H >= 6 ->
    (H2 = H,
    sift2(T, T2)
    ); sift2(T, [H2 | T2]).
?- sift2([1, 7, 2, 13], X).
X = [7, 13].