我需要一个将给定集合拆分为子集的谓词
到目前为止我所拥有的:
divide_set(S, Sd) :-
length(S, L),
between(1, L, N),
length(Sd, N),
append(Sd, S),
forall(member(M, Sd), M \= []).
这给了我这些结果:
?- divide_set([a, b, c, d, e, f], Sd).
Sd = [[a, b, c, d, e, f]] ;
Sd = [[a], [b, c, d, e, f]] ;
Sd = [[a, b], [c, d, e, f]] ;
Sd = [[a, b, c], [d, e, f]] ;
Sd = [[a, b, c, d], [e, f]] ;
Sd = [[a, b, c, d, e], [f]] ;
...
因此该集合被视为有序集合,但我也希望包含[a, f]
。
如何扩展谓词以便获取子集而不是子序列?
(我可以为每个可能的序列做到这一点,但我认为这不是最好的解决方案)
答案 0 :(得分:3)
superset(Superset, Subsets) :-
foreach(member(Subset, Subsets),
foreach(member(X, Subset), member(X, Superset))).
这在纸面上看起来不错,但使用member/2
生成会导致无限递归,因为它会产生包含未绑定变量的大量列表。所以这不起作用。
我的下一个想法是,也许我可以像你建议的那样生成所有排列。但是当我想象生成所有排列然后围绕它们构建所有可能的列表时,它听起来好像会有很多重复的答案。所以我想到了你的意见,这可能是一种更有效的方法。
然后我开始做一些示例输入/输出,看起来像这样:
divide_set([X,Y], [[X],[Y]]).
divide_set([X,Y], [[X,Y]]).
divide_set([X,Y,Z], [[X],[Y],[Z]]).
divide_set([X,Y,Z], [[X],[Y,Z]]).
divide_set([X,Y,Z], [[X,Y],[Z]]).
divide_set([X,Y,Z], [[X,Z],[Y]]).
divide_set([X,Y,Z], [[X,Y,Z]]).
以这种方式对它们进行分组有助于我看到一种方法:我要么拉出前面的项目并重复,要么拉出前面的项目并将其添加到递归结果中,这导致我实现了这个:
divide_set([X], [[X]]).
divide_set([X|Remainder], [[X]|Rest]) :-
divide_set(Remainder, Rest).
divide_set([X|Remainder], [[X|Subset]|RestButOne]) :-
divide_set(Remainder, Rest),
select(Subset, Rest, RestButOne).
我不确定这是否正确,但这是我对您的示例输入的输出:
?- divide_set([1,2,3,4], X).
X = [[1], [2], [3], [4]] ;
X = [[1], [2], [3, 4]] ;
X = [[1], [2, 3], [4]] ;
X = [[1], [2, 4], [3]] ;
X = [[1], [2, 3, 4]] ;
X = [[1, 2], [3], [4]] ;
X = [[1, 3], [2], [4]] ;
X = [[1, 4], [2], [3]] ;
X = [[1, 2], [3, 4]] ;
X = [[1, 3, 4], [2]] ;
X = [[1, 2, 3], [4]] ;
X = [[1, 4], [2, 3]] ;
X = [[1, 2, 4], [3]] ;
X = [[1, 3], [2, 4]] ;
X = [[1, 2, 3, 4]] ;
false.
我没有做过数学计算,看看我们应该在答案的组合方面得到什么,但乍一看,这对我来说是正确的。我看到了所有不同大小的子集,我期望有四个元素,我看到了所有不同数量的子集。随着它进一步进入递归,工作确实减少了;你会注意到数字1从未出现在第二个或后续的列表中,2个从未出现在第3个或第4个子集中,等等。所以我认为这是合理的,这是正确的。
此外,您感兴趣的方案确实发生:
?- divide_set([a, b, c, d, e, f], [[a,f]|Rest]).
Rest = [[b], [c], [d], [e]] ;
Rest = [[b], [c], [d, e]] ;
Rest = [[b], [c, d], [e]] ;
Rest = [[b], [c, e], [d]] ;
Rest = [[b], [c, d, e]] ;
Rest = [[b, c], [d], [e]] ;
Rest = [[b, d], [c], [e]] ;
Rest = [[b, e], [c], [d]] ;
Rest = [[b, c], [d, e]] ;
Rest = [[b, d, e], [c]] ;
Rest = [[b, c, d], [e]] ;
Rest = [[b, e], [c, d]] ;
Rest = [[b, c, e], [d]] ;
Rest = [[b, d], [c, e]] ;
Rest = [[b, c, d, e]] ;
false.