【问题标题】:how find all groups of subsets of set A? Set partitions in Python如何找到集合 A 的所有子集组?在 Python 中设置分区
【发布时间】:2015-05-08 18:00:26
【问题描述】:

我想找到一个算法,给定一个集合A 来找到满足以下条件的所有子集组:

x ∪ y ∪ .... z = A,其中 x, y, ... z ∈ Group

∀ x,y ∈ 组:x ⊆ A, y ⊆ A, x ∩ y = ∅ = {}

∀ x ∈ 组:x != ∅

注意:我希望定义好,我不擅长数学符号

我采用以下方法仅搜索两个子集的组:

from itertools import product, combinations

def my_combos(A):
  subsets = []
  for i in xrange(1, len(A)):
    subsets.append(list(combinations(A,i)))
  combos = []
  for i in xrange(1, 1+len(subsets)/2):
    combos.extend(list(product(subsets[i-1], subsets[-i])))
  if not len(A) % 2:
    combos.extend(list(combinations(subsets[len(A)/2-1], 2)))
  return [combo for combo in combos if not set(combo[0]) & set(combo[1])]

my_combos({1,2,3,4})

我得到以下输出,这些都是由两个子集组成的组

[
  ((1,), (2, 3, 4)), 
  ((2,), (1, 3, 4)), 
  ((3,), (1, 2, 4)), 
  ((4,), (1, 2, 3)), 
  ((1, 2), (3, 4)), 
  ((1, 3), (2, 4)), 
  ((1, 4), (2, 3))
]

..... 但是,由一个、三个、四个子集组成的组......

问题:

我怎样才能找到一个通用的解决方案?

例如以下预期输出:

my_combos({1,2,3,4})

[
  ((1,2,3,4)),
  ((1,2,3),(4,)),
  ((1,2,4),(3,)),
  ((1,3,4),(2,)),
  ((2,3,4),(1,)),
  ((1,2),(3,4)),
  ((1,3),(2,4)),
  ((1,4),(2,3)),
  ((1,2),(3,),(4,)),
  ((1,3),(2,),(4,)),
  ((1,4),(2,),(3,)),
  ((1,),(2,),(3,4)),
  ((1,),(3,),(2,4)),
  ((1,),(4,),(2,3)),
  ((1,),(4,),(2,),(3,))
]

【问题讨论】:

  • 具体看brice关于powersets的回答
  • @Cyber​​ 嗯,但是 OP 的情况有点不同,尽管可以调整相同的代码以获得答案
  • @Cyber​​ 问题不同
  • @Cyber​​ answer brice 解决了我已经解决的问题,但我的问题不同:-(
  • 好的,我重新打开了这个问题。

标签: python algorithm python-3.x set subset


【解决方案1】:

解决方案:

def partitions(A):
    if not A:
        yield []
    else:
        a, *R = A
        for partition in partitions(R):
            yield partition + [[a]]
            for i, subset in enumerate(partition):
                yield partition[:i] + [subset + [a]] + partition[i+1:]

解释:

  • 空集只有空分区。
  • 对于非空集,取出一个元素,然后对于剩余元素的每个分区,将该元素添加为其自己的子集或将其添加到分区的子集中之一。
  • 请注意,分区实际上是一组集合。我只将它表示为列表列表,因为这样更快,而且我不想使用无法很好打印的冻结集。元组更快,而且问题要求它们,但我无法忍受单元素元组的逗号。

用输出测试:

for partition in partitions({1, 2, 3, 4}):
    print(partition)

[[4], [3], [2], [1]]
[[4, 1], [3], [2]]
[[4], [3, 1], [2]]
[[4], [3], [2, 1]]
[[4, 2], [3], [1]]
[[4, 2, 1], [3]]
[[4, 2], [3, 1]]
[[4], [3, 2], [1]]
[[4, 1], [3, 2]]
[[4], [3, 2, 1]]
[[4, 3], [2], [1]]
[[4, 3, 1], [2]]
[[4, 3], [2, 1]]
[[4, 3, 2], [1]]
[[4, 3, 2, 1]]

输出速度测试(在相对较弱的笔记本电脑上):

from time import time
print('elements partitions seconds')
for n in range(14):
    t0 = time()
    number = sum(1 for partition in partitions(range(n)))
    print('{:5}{:10}{:11.2f}'.format(n, number, time() - t0))

elements partitions seconds
    0         1       0.00
    1         1       0.00
    2         2       0.00
    3         5       0.00
    4        15       0.00
    5        52       0.00
    6       203       0.00
    7       877       0.00
    8      4140       0.06
    9     21147       0.07
   10    115975       0.36
   11    678570       2.20
   12   4213597      13.56
   13  27644437      87.59

我用OEIS page 确认了这些分区号。

【讨论】:

    猜你喜欢
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 2020-05-14
    相关资源
    最近更新 更多