编辑:
感谢评论者道格拉斯·扎尔(Douglas Zare),我已经将这篇文章的标题重新命名为更合适的术语,以供其他可能正在寻找类似内容的人使用。以下David Eisenstat的代码非常有用。
原始邮件:
我为缺乏合适的集合理论术语而道歉...但我在这里有点超出我的深度(虽然我怀疑这是一个容易的问题)。我正在尝试开发一种算法,它将接受一个集合和一个数字K,并返回所有可能的“完整”分区,其中包含K大小的子集和set coverage = K,以便:
例如:
function({A, B, C, D}, 2)
应该返回所有可能的集合:
[AB, BC, CD, DA]
[AB, BD, CA, DC]
[AC, BD, CA, DB]
[AD, DA, CB, BC]
[BC, CA, DB, AD]
...
另外,为了它的价值
所以以下内容是等效的:
[AB, BA, CD, DC] = [BA, AB, DC, CD] = [AB, BA, DC, CD] = [BA, AB, CD, DC]
和
所以以下是不同的:
[BC, CA, DB, AD] ≠ [CA, BC, AD, DB]
换句话说,用矩阵术语:我正在查找包含rows=len(set)
和columns=K
的所有矩阵,因此每列都有精确的封面,任何行都不会出现多次。
function({A, B, C, D}, 3)
将返回所有矩阵,如下所示......
ABC ADB
BCD DCA
CDA CBD
DAB BAC
我希望在python中得到一个答案,使用像numpy这样的库很好......但只是一般的算法策略也会受到赞赏。我认为像Algorithm X这样的东西可能会派上用场......但是我无法从那里跳到这里概述的问题......
答案 0 :(得分:0)
可以进行回溯搜索。 Python 3:
import itertools
import operator
def valid(cols_so_far):
for i, col1 in enumerate(cols_so_far):
for col2 in cols_so_far[i + 1:]:
if any(map(operator.eq, col1, col2)):
return False
return True
def enum(letters, k, cols_so_far=None):
if cols_so_far is None:
cols_so_far = (tuple(letters),)
if not valid(cols_so_far):
pass
elif len(cols_so_far) == k:
yield tuple(zip(*cols_so_far)) # transpose
else:
for perm in itertools.permutations(letters):
yield from enum(letters, k, cols_so_far + (perm,))