所以我写了这个谓词来查找所有可能的子集+列表的排列。我得到了正确的输出,但由于某种原因,程序在给我所有(正确的)结果后继续循环。
我做错了什么?
% Gets all subsets of a list
aSubset([], []).
aSubset([E|Tail], [E|NTail]):- aSubset(Tail, NTail).
aSubset([_|Tail], NTail):- aSubset(Tail, NTail).
% gets all subsets and permutates them
allSubsets([],[]).
allSubsets(X, Res) :- permutation(S, Res), aSubset(X, S).
我得到的所有子集([1,2,3],X)的结果是:
4 ?- allSubsets([1,2,3], X).
X = [] ;
X = [1] ;
X = [2] ;
X = [3] ;
X = [1,2] ;
X = [1,3] ;
X = [2,3] ;
X = [2,1] ;
X = [3,1] ;
X = [3,2] ;
X = [1,2,3] ;
X = [1,3,2] ;
X = [2,1,3] ;
X = [2,3,1] ;
X = [3,1,2] ;
X = [3,2,1] ;
Action (h for help) ? abort
% Execution Aborted
我必须在最后两行中止循环。
提前谢谢。
不仅allSubset([1,2,3], X)
循环,而且更短的allSubset([], X)
。
以下程序片段(故障片)已循环。所以没有必要再看了。
allSubsets([],[]) :- false.所有子集(X, Res) :- 排列(S, Res), 假,a子集(X, S)。
为了改善这一点,您需要更改可见部分中的某些内容。 目前,只有Arg2(Res
)可以影响目标permutation(S, Res)
,Arg1(X
)只出现在第二个目标中,此时影响(普遍)终止第一个目标已经为时已晚。
实现目标的一种方法是对当前代码稍作修改:
% Gets all subsets of a list
aSubset([], []).
aSubset([E|Tail], [E|NTail]):- aSubset(Tail, NTail).
aSubset([_|Tail], NTail):- aSubset(Tail, NTail).
% gets all subsets and permutates them
allSubsets([],[]).
allSubsets(X, Res) :- aSubset(X, S), permutation(S, Res).
因此,与其先进行无界排列,不如先生成已知列表的子集(有限数量的解决方案),然后排列已知子集(也是有限数量的解决方案)。回溯将对所有子集的所有排列执行此操作:
| ?- allSubsets([1,2,3], L).
L = [1,2,3] ? a
L = [1,3,2]
L = [2,1,3]
L = [2,3,1]
L = [3,1,2]
L = [3,2,1]
L = [1,2]
L = [2,1]
L = [1,3]
L = [3,1]
L = [1]
L = [2,3]
L = [3,2]
L = [2]
L = [3]
L = []
(2 ms) no
| ?-