最小集合覆盖

时间:2013-09-24 12:30:43

标签: python algorithm set-cover

我想解决以下类型的最小集合覆盖问题。所有列表仅包含1和0。

如果您可以通过准确插入A符号从B B A,则我会说列表x包含列表n

考虑所有2 ^ n个长度为x = n/3的1和0的列表,并设置2n/3。我想计算一组长度为2n/3的最小列表,涵盖所有这些列表。

这是我开始的一种天真的方法。对于每个可能的长度from itertools import product, combinations def all_fill(source, num): output_len = len(source) + num for where in combinations(range(output_len), len(source)): # start with every possibility poss = [[0,1]] * output_len # impose the source list for w, s in zip(where, source): poss[w] = [s] # yield every remaining possibility for tup in product(*poss): yield tup 列表,我使用此函数(由DSM编写)创建一组可以从中创建的列表。

n = 6

然后我使用n = 6 shortn = 2*n/3 x = n/3 coversets=set() for seq in product([0,1], repeat = shortn): coversets.add(frozenset(all_fill(seq,x))) 作为示例创建一组集合。

allset = set(product([0,1], repeat=n))

我想从联盟为set(all_fill([1,1,1,1],2)), set(all_fill([0,0,0,0],2)), set(all_fill([1,1,0,0],2)), set(all_fill([0,0,1,1],2))的封面中找到一组最小的集合。

在这种情况下,n = 12会这样做。

我的目标是解决n的问题。我很乐意使用外部库,如果这会有所帮助,我希望在最坏的情况下{{1}}的时间呈指数级。

1 个答案:

答案 0 :(得分:3)

我写了一个小程序来编写一个要解决的整数程序 CPLEX或其他MIP求解器。下面是n = 12的解决方案。


from collections import defaultdict
from itertools import product, combinations

def all_fill(source, num):
    output_len = (len(source) + num)
    for where in combinations(range(output_len), len(source)):
        poss = ([[0, 1]] * output_len)
        for (w, s) in zip(where, source):
            poss[w] = [s]
        for tup in product(*poss):
            (yield tup)

def variable_name(seq):
    return ('x' + ''.join((str(s) for s in seq)))
n = 12
shortn = ((2 * n) // 3)
x = (n // 3)
all_seqs = list(product([0, 1], repeat=shortn))
hit_sets = defaultdict(set)
for seq in all_seqs:
    for fill in all_fill(seq, x):
        hit_sets[fill].add(seq)
print('Minimize')
print(' + '.join((variable_name(seq) for seq in all_seqs)))
print('Subject To')
for (fill, seqs) in hit_sets.items():
    print(' + '.join((variable_name(seq) for seq in seqs)), '>=', 1)
print('Binary')
for seq in all_seqs:
    print(variable_name(seq))
print('End')

MIP - Integer optimal solution:  Objective =  1.0000000000e+01
Solution time =    7.66 sec.  Iterations = 47411  Nodes = 337

CPLEX> Incumbent solution
Variable Name           Solution Value
x00000000                     1.000000
x00000111                     1.000000
x00011110                     1.000000
x00111011                     1.000000
x10110001                     1.000000
x11000100                     1.000000
x11001110                     1.000000
x11100001                     1.000000
x11111000                     1.000000
x11111111                     1.000000
All other variables matching '*' are 0.
CPLEX>