Следующая функция рекурсивного генератора должна работать.Я уверен, что производительность может быть улучшена.
def subsets(lsts):
if not lsts:
return
for i, lst in enumerate(lsts):
yield [lst]
s = set(lst)
pool = [x for x in lsts[i+1:] if not s.intersection(x)]
for subs in subsets(pool):
yield [lst] + subs
>>> L = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]]
>>> list(subsets(L))
[[[0, 1]],
[[0, 1], [2, 3]],
[[0, 1], [2, 3], [4, 5]],
[[0, 1], [3, 4]],
[[0, 1], [4, 5]],
[[1, 2]],
[[1, 2], [3, 4]],
[[1, 2], [4, 5]],
[[2, 3]],
[[2, 3], [4, 5]],
[[3, 4]],
[[4, 5]]]
Если вам нужны только полностью исчерпывающие списки подмножеств (которые не могут быть добавлены к другим подмножествам), подойдут некоторые незначительные изменения:
def subsets(lsts, make_unique=True, used=None):
if not lsts:
yield []
used = set(used or [])
if make_unique:
lsts = sorted(map(list, set(map(tuple, lsts))))
for i, lst in enumerate(lsts):
s = set(lst)
pool = [x for x in lsts if not s.intersection(x)]
for subs in subsets(pool, make_unique=False, used=used):
if not used.intersection(map(tuple, subs)):
yield [lst] + subs
used.add(tuple(lst))
>>> list(subsets(L))
[[[0, 1], [2, 3], [4, 5]],
[[0, 1], [3, 4]],
[[1, 2], [3, 4]],
[[1, 2], [4, 5]]]
>>> L = [[0, 1, 2], [3, 4, 5], [0, 1], [2, 3], [6, 7]]
>>> list(subsets(L))
[[[0, 1], [2, 3], [6, 7]],
[[0, 1], [3, 4, 5], [6, 7]],
[[0, 1, 2], [3, 4, 5], [6, 7]]]