python约束 - 约束金额

时间:2018-04-04 16:19:40

标签: python constraints constraint-programming

我有一个约束问题,我正试图用python-constraint

解决

所以我想说我有3个地点:loc1,...loc3

另外,我有7个设备:device1,...device7

每个位置的最大设备数量:loc1:3, loc2:4, loc3:2 (例如loc1中最多3个设备,依此类推......)

关于位置和设备的一些限制:

loc1: device1, device3, device7

loc2: device1, device3, device4, device5, device6, device7

loc3: device2, device4, device5, device6

(仅作为示例device1device3device7可以在loc1中。)

我正在尝试为各个位置的设备提供一组可能的选项。

    from constraint import *
    problem = Problem()
        for key in locations_devices_dict:
           problem.addVariable(key,locations_devices_dict[key])
           # problem.addVariable("loc1", ['device1', 'device3', 'device7'])
   problem.addConstraint(AllDifferentConstraint())

我坚持如何做约束。我试过了:

problem.addConstraint(MaxSumConstraint(3), 'loc1')

但它不起作用,MaxSumConstraint并不总结我需要的东西。

所有设备必须放在某处

可能的解决方案:

loc1: device1, device3
loc2: device4, device6, device7
loc3: device2, device5

有人有想法吗?

(另一个python包/不使用任何包,如果有人有任何建议也是个好主意...)

2 个答案:

答案 0 :(得分:3)

这是一个类似于任务的简单模型:

enter image description here

所以我们有一个二进制变量,指示设备 d 是否分配给位置 L 。线性约束只是:

  • 将每个设备分配到一个位置
  • 每个位置都有最大数量的设备
  • 确保仅使用允许的分配(由allowed(L,d)建模)

任何约束求解器都可以处理此问题。

列举所有可能的解决方案有点危险。对于大型实例,有太多的方法。即使对于这个小问题,我们已经有25个解决方案:

enter image description here

对于大问题,这个数字将是天文数字。

使用Python约束包,它可能如下所示:

from constraint import *

D = 7 # number of devices
L = 3 # number of locations

maxdev = [3,4,2]
allowed = [[1,3,7],[1,3,4,5,6,7],[2,4,5,6]]

problem = Problem()
problem.addVariables(["x_L%d_d%d" %(loc+1,d+1) for loc in range(L) for d in range(D) if d+1 in allowed[loc]],[0,1])
for loc in range(L):
    problem.addConstraint(MaxSumConstraint(maxdev[loc]),["x_L%d_d%d" %(loc+1,d+1) for d in range(D) if d+1 in allowed[loc]])
for d in range(D):
    problem.addConstraint(ExactSumConstraint(1),["x_L%d_d%d" %(loc+1,d+1) for loc in range(L) if d+1 in allowed[loc]])

S = problem.getSolutions()
n = len(S)
n

对于大问题,您可能希望使用dicts来加快速度。

答案 1 :(得分:0)

编辑:在我看到@ ErwinKalvelagen的代码之前,我写了这个答案。所以我没有检查他的解决方案......

所以我使用@ErwinKalvelagen方法创建了一个表示问题的矩阵。 对于每个(i,j),如果设备i可以到达位置j,则x [i,j] = 1,否则为0。

然后,我为每一行使用addConstraint(MaxSumConstraint(maxAmount[i]), row) - 这是表示每个位置中最大设备的约束。

每列的

addConstraint(ExactSumConstraint(1), col) - 这是每个设备只能放在一个位置的约束。

接下来,我把所有x [i,j] = 0(设备我不能在位置j)和每个t(i,j)addConstraint(lambda var, val=0: var == val, (t,))

此问题类似于数独问题,我使用this示例获取帮助

上面示例的矩阵是:

(devices:) 1 2 3 4 5 6 7
     loc1: 1 0 1 0 0 0 1
     loc2: 1 0 1 1 1 1 1
     loc3: 0 1 0 1 1 1 0

我的代码:

        problem = Problem()
        rows = range(locations_amount)
        cols = range(devices_amount)
        matrix = [(row, col) for row in rows for col in cols]
        problem.addVariables(matrix, range(0, 2)) #each cell can get 0 or 1
        rowSet = [zip([el] * len(cols), cols) for el in rows]
        colSet = [zip(rows, [el] * len(rows)) for el in cols]

        rowsConstrains = getRowConstrains() # list that has the maximum amount in each location(3,4,2) 
                                            #from my example: loc1:3, loc2:4, loc3:2 

        for i,row in enumerate(rowSet):
            problem.addConstraint(MaxSumConstraint(rowsConstrains[i]), row)
        for col in colSet:
            problem.addConstraint(ExactSumConstraint(1), col)

        s = getLocationsSet() # set that has all the tuples that x[i,j] = 1

        for i, loc in enumerate(locations_list):
            for j, iot in enumerate(devices_list):
                t=(i,j)
                if t in s:
                    continue
                problem.addConstraint(lambda var, val=0: var == val, (t,)) # the value in these cells must be 0

        solver = problem.getSolution()

解决方案的示例:

(devices:) 1 2 3 4 5 6 7
     loc1: 1 0 1 0 0 0 1
     loc2: 0 0 0 1 1 1 0
     loc3: 0 1 0 0 0 0 0