结果后Prolog循环

时间:2014-12-12 10:20:41

标签: loops prolog declarative failure-slice declarative-programming

所以我编写了这个谓词来查找列表的所有可能的子集+排列。 我得到了正确的输出,但由于某种原因,程序在给出所有(正确的)结果后保持循环。

我做错了什么?

% 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

我必须在最后两行中止循环。

提前致谢。

2 个答案:

答案 0 :(得分:4)

不仅allSubset([1,2,3], X)循环,而且短allSubset([], X)

以下程序片段(failure-slice)已经循环。所以不需要再看了。

allSubsets([],[]) :- false.
allSubsets(X, Res) :-
   permutation(S, Res), false,
   aSubset(X, S).

要改善这一点,您需要更改可见部分中的内容。目前,只有Arg2(Res)可以影响目标permutation(S, Res),Arg1(X)仅出现在第二个目标中,当影响(普遍)终止时已经太晚了第一

答案 1 :(得分:3)

实现目标的一种方法是略微修改您当前的代码:

% 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
| ?-