您可以只生成原始元素集的所有可能排列,并将它们用作从原始元素到新配置的“映射”。例如,2345671 将每个数字映射到下一个数字并环绕;这将创建集合:
A = {2, 3, 4} # from {1, 2, 3}
B = {3, 4, 5, 6} # from {2, 3, 4, 5}
C = {3, 6, 7, 1} # from {2, 5, 6, 7}
使用itertools 非常简单:
from itertools import permutations
def all_configurations(*sets):
elements = list(set.union(*sets))
for perm in permutations(elements):
map = {old: new for old, new in zip(elements, perm)}
new_sets = [{map[k] for k in old_set} for old_set in sets]
yield new_sets
A = {1, 2, 3}
B = {2, 3, 4, 5}
C = {2, 5, 6, 7}
confs = all_configurations(A, B, C)
for conf in confs:
print(conf)
# Or: Ax, Bx, Cx = conf
请注意我是如何使用yield 语句的,这将一次生成每个新排列,而不是一次创建它们,因此您可以将其用于大量元素而不会占用内存。此外,所编写的函数适用于任意数量的输入集。
当然,这肯定会生成一些重复项(例如,在您的示例中,映射 6 到 7 和 7 到 6 不会改变任何内容)但它肯定也应该生成每个有效选项。一些示例输出:
[{2, 4, 6}, {3, 4, 5, 6}, {1, 3, 6, 7}]
[{4, 5, 7}, {1, 3, 4, 7}, {2, 3, 6, 7}]
[{3, 5, 6}, {1, 3, 5, 7}, {2, 3, 4, 7}]
[{1, 6, 7}, {1, 2, 4, 7}, {2, 3, 5, 7}]
编辑:为了获得固定数量的非重复排列,您可以更改原始代码以返回 tuple 的 frozensets 而不是集合列表,这样整个事情可以散列,所以你只能得到唯一的。然后,您可以将内容添加到输出集中,直到达到您想要的基数:
from itertools import permutations
def all_configurations(*sets):
elements = list(set.union(*sets))
for perm in permutations(elements):
map = {old: new for old, new in zip(elements, perm)}
new_sets = tuple(frozenset(map[k] for k in old_set) for old_set in sets)
yield new_sets
def n_configurations(n, *sets):
output = set()
confs = all_configurations(*sets)
for conf in confs:
output.add(conf)
if len(output) >= n:
break
return output
A = {1, 2, 3}
B = {2, 3, 4, 5}
C = {2, 5, 6, 7}
confs = n_configurations(10, A, B, C)
for a, b, c in confs:
print(a, b, c)
这会产生以下 10 种配置:
(frozenset([1, 2, 3]), frozenset([2, 3, 5, 6]), frozenset([2, 4, 6, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 4, 6]), frozenset([2, 5, 6, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 6, 7]), frozenset([2, 4, 5, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 4, 6]), frozenset([2, 4, 5, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 4, 5]), frozenset([2, 4, 6, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 5, 6]), frozenset([2, 4, 5, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 4, 7]), frozenset([2, 5, 6, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 4, 5]), frozenset([2, 5, 6, 7]))
(frozenset([1, 2, 3]), frozenset([2, 3, 4, 7]), frozenset([2, 4, 5, 6]))
(frozenset([1, 2, 3]), frozenset([2, 3, 5, 7]), frozenset([2, 4, 6, 7]))