为什么Prolog在筛选列表时会找到很多解决方案?
我写了一个谓词,它过滤6以下所有数字的列表,但是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
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].