因此,当z
和z[i, j] = 1
之间的距离小于或等于150和i
时,我想添加一个二进制变量j
,其中z[i, j] = 0
除此以外。我有一个列表c
,其中每个c[i][j]
代表i
和j
之间的距离。我当然不能在下面将z
设置为普通的二进制变量:
y = m.addVars(I, J, vtype=GRB.BINARY, name="assign")
我想添加约束:
# One day mailing
m.addConstrs(
z[i,j] <= y[i,j] for i in I for j in J,
"Serve")
# Coverage Constraint
m.addConstr(
quicksum(h[i] * z[i, j] for i in I for j in J) <=
0.9 * quicksum(h[i] * y[i, j] for i in I for j in J),
"Cover")
其中h
是带有整数的列表。如何设置z
?
答案 0 :(得分:0)
首先,您需要添加z
作为二进制变量:
z = m.addVars(I, J, vtype=GRB.BINARY, name="z")
然后,当且仅当z[i, j] = 1
时,您需要约束以确保c[i, j] <= 150
。
一种方法是使用指标约束:
z = 1 -> c <= 150
z = 0 -> c >= 150
这等效于
c > 150 -> z = 0
c < 150 -> z = 1
您将这些添加如下:
m.addConstrs((z[i, j] == 1) >> (c[i][j] <= 150) for i in I for j in J)
m.addConstrs((z[i, j] == 0) >> (c[i][j] >= 150) for i in I for j in J)
您还可以自己对此进行显式建模:
如果您在M
的值上有m
和c[i][j] - 150
的上限和下限(即,对于所有M >= c[i][j] - 150 >= m
的限制是i, j
),则可以使用以下约束:
M * (1-z) >= c - 150
m * z <= c - 150
如果c > 150
,则两个不等式的右边将为正。然后,第一个强制1 - z = 1
,因此强制z = 0
。第二个不平等将被轻易满足。
如果c < 150
,则右侧为负。第一个不平等变得微不足道,而第二个不平等迫使z = 1
。
对于M
,c
中的最大条目将起作用,对于m
,如果所有-150
均为非负数,则可以选择c[i][j]
。
您添加以下约束:
m.addConstrs( M * (1 - z[i, j]) >= c[i][j] - 150 for i in I for j in J )
m.addConstrs( m * z[i,j] <= c[i][j] - 150 for i in I for j in J )
请注意,我忽略了c = 150
的情况。这是因为对于浮点数,总是只将等式视为在公差范围内,因此没有简单的方法可以区分严格和非严格不等式。您可以使用epsilon对此进行近似,例如:
z = 0 -> c >= 150 + epsilon