从this question开始,我构建了以下代码:
import itertools
n=4
nodes = set(range(0,n))
ss = set()
for i in range(1,n+1):
ss = ss.union( set(itertools.combinations(range(0,n), i)))
ss2 = set()
for s in ss:
cs = []
for i in range(0,n):
if not(i in s):
cs.append(i)
cs=tuple(cs)
if not(s in ss2) and not(cs in ss2):
ss2.add(s)
ss = ss2
该代码构造S = {0,1,...,n-1}(i)的所有子集而没有补码(例如,对于n = 4,(1,3)或(0,2)为包含,无所谓); (ii)无空集,但(iii)有S;结果以ss为单位。有没有更紧凑的方法来完成这项工作?我不在乎结果是否是集合/列表/列表/元组。 (结果包含2 **(n-1)个元素)
其他选项:
答案 0 :(得分:0)
排除补码时,实际上排除了一半的组合。因此,您可以想象生成所有组合,然后将它们的后半部分踢掉。在那里,您必须确保不要将一个组合及其互补词一起踢出去,但是您订购它们的方式将不会发生。
沿着这个想法,您甚至不需要生成大小大于 n / 2 的组合。对于 n 的 even 值,您需要将大小为 n / 2 的组合列表减半。
这是实现所有目标的一种方法:
import itertools
n=4
half = n//2
# generate half of the combinations
ss = [list(itertools.combinations(range(0,n), i))
for i in range(1, half+1)]
# if n is even, kick out half of the last list
if n % 2 == 0:
ss[-1] = ss[-1][0:len(ss[-1])//2]
# flatten
ss = [y for x in ss for y in x]
print(ss)