组合嵌套集的排列

时间:2017-01-02 12:19:03

标签: python nested combinations permutation

我有两组集合,我需要将它们的组合的所有排列(如在联合中)组合成一个集合,使得其中没有2个集合包含重复的元素(您可以假设每个父集合都不具有' t有自己的重复元素的集合),而我只能删除第二级集合,而不是元素本身,例如:

[(a,b),(c),(d)] and [(a),(b,c),(e)]

会得到我:

[(a,b),(c),(d),(e)],[(a),(b,c),(d),(e)],[(a),(c),(d),(e)]

来自一个父集合的一个集合可以给我一个来自另一个父集合的集合的子集是不兼容的(即包含一个或多个公共元素),保持第二集合中的每个集合将给我一个新的集合子集我可以从第一个中移除等等..递归地运行这个并检查重复是非常耗时的......

有没有更好的方法来解决这个问题?我可以用什么工具? (目前在python中这样做)

P.S。我的意思的一个小代码示例,再次,我不想修复错误,只是要求更简洁的方法:

def combine(S1, S2, incompatible_set, parent_set_pairs):

    new_S2 = None
    new_incompatible_sets = set()

    for s2 in S2:
        if incompatible_set & s2:
            new_incompatible_sets.add(s2)
            if not S2:
                S2 = S2.copy()
            new_S2.remove(s2)
    parent_set_pairs.add((S1, new_S2)) # here it should look for a new incompatible set in S1 and apply the function again..
    for new_incompatible_set in new_incompatible_sets:
        new_parent_set_pairs = combine(S2, S1, new_incompatible_set,
                                 parent_set_pairs)
        for pair1 in new_parent_set_pairs:
            for pair2 in parent_set_pairs:
                if pair1[0]|pair1[1] not in pair2[0]|pair2[1]
            parent_set_pairs.add(new_parent_set_pairs)

    return parent_set_pairs

1 个答案:

答案 0 :(得分:0)

这是一个基于itertools的方法,它采用两个不相交的集合列表,并返回从两个列表中提取的所有最大的脱离集合组合,但受组合中的集合不相交的约束:

from itertools import combinations

def maxDisjoints(A,B):
    n = len(A)
    combos = set()
    for i in range(n+1):
        for partA in combinations(A,i):
            A_covered = set().union(*partA)
            filteredB = [s for s in B if A_covered & s == set()]
            B_covered = set().union(*filteredB)
            filteredA = [s for s in A if B_covered & s == set()]
            #filteredA is a superset of partA
            #freeze and record:
            combos.add(tuple(frozenset(s) for s in filteredA + filteredB))
    #unfreeze and return as list of lists of sets:       
    return [[set(f) for f in t] for t in combos]

测试它:

A = [{'a','b'},{'c'},{'d'}]
B = [{'a'},{'b','c'},{'e'}]
for p in jointPartitions(A,B):
    print(p)

输出:

[{'c'}, {'d'}, {'a'}, {'e'}]
[{'d'}, {'a'}, {'b', 'c'}, {'e'}]
[{'b', 'a'}, {'c'}, {'d'}, {'e'}]

作为技术上的烦恼,设置和列表都不可清除,因此不可能维护一组集合列表以过滤冗余(因为算法不止一次地生成相同的最大组合)。因此,我不得不将集合列表转换为冻结集合的元组以临时记录它们,只是为了在最后反转过程。

这是一种蛮力的方法。它遍历A的所有2 ^ n个子集,以唯一可能的方式将每个子集扩展为最大组合。如果A的大小和B的大小之间存在差异,则首先传递两个列表中较短的一个(或调整代码以便它自动执行此操作)。这种方法对于小型集合来说是合理的,但是不能很好地扩展。我怀疑问题本身是NP难的,所以你可以预期的效率有限(这并不是说这个算法是最优的)。