Loops 结果后的Prolog循环
所以我写这个谓词是为了找到列表中所有可能的子集+置换。 我得到了正确的输出,但由于某种原因,程序在给出所有(正确的)结果后继续循环 我做错了什么Loops 结果后的Prolog循环,loops,prolog,declarative,failure-slice,declarative-programming,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 permu
% 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)的结果是:
我必须在最后两行中止循环
提前感谢。不仅所有子集([1,2,3],X)
循环,而且更短的所有子集([],X)
以下程序片段()已循环。因此,无需进一步研究
要改进这一点,您需要更改可见部分中的某些内容。目前,只有Arg2(
Res
)可以影响目标置换(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
| ?-
由于我是prolog新手,我不太确定什么是解决方案。。我也不太明白我的想法中“错误”的部分是什么。@ValentijnSpruyt以另一种方式陈述:你对
permutation(S,Res)
的查询太“开放”。这两个参数都是可变的。回溯时,它将继续生成并尝试无限排列,元素数量不断增加。你需要约束它。@潜伏者:发布一个终止“尽可能好”的版本怎么样?让我们看看我们能走多远@瓦伦蒂恩斯普鲁伊特:你读过标签上的其他答案吗?哪个系统给你这个结果?我的意思是,在不同的L
之间是否真的没有分号(;
)?啊,可能是Prolog GNU。对吗?@falseYes,如果我在GNU中按“a”,它不会显示分号。它只是列出了所有的结果。
| ?- 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
| ?-