在Python中做约束满足

时间:2014-08-31 15:28:35

标签: python algorithm constraints

假设我有多个用户,每个用户都有0n之间的一组数字。例如,一个用户可能有一组{3, 7},另一个可能有{7, 8, 9}等。

我想获得最少数量的用户,如果我将所有用户组合在一起,我会在0n之间得到所有数字的集合。

奖励积分如果您想出一种方法也可以让我为每个用户分配一个可变价格(而不是像上面那样使用1),这样算法就能找到最低总价的用户组合。

我见过在Python中处理约束满足的包(like this one),但我不知道如何使用它们。如果它们可以用于此,那很好。

1 个答案:

答案 0 :(得分:3)

以下是PuLP / GLPK的解决方案。我以前从未使用过PuLP,但它是在PyPI上,似乎可以完成这项工作。 GLPK非常好而且免费。

from collections import defaultdict, namedtuple
from pulp import *


User = namedtuple('User', ('coverage', 'price'))


def solvesetcover(users):
    vars = [LpVariable('x{}'.format(i), 0, 1, cat='Binary') for i, user in enumerate(users)]
    prob = LpProblem()
    totals = defaultdict(int)
    for user, var in zip(users, vars):
        prob += user.price * var
        for elt in user.coverage:
            totals[elt] += var
    for total in totals.values():
        prob += total >= 1
    GLPK(msg=0).solve(prob)
    return [user for user, var in zip(users, vars) if value(var)]


if __name__ == '__main__':
    users = []
    users.append(User({1, 2, 3, 4, 5, 6, 7}, 1.16))
    users.append(User({8, 9, 10, 11, 12, 13, 14}, 1.08))
    users.append(User({1, 8}, 1.04))
    users.append(User({2, 3, 9, 10}, 1.02))
    users.append(User({4, 5, 6, 7, 11, 12, 13, 14}, 1.01))
    print(solvesetcover(users))