优化 | 线性化:0-1变量乘以连续变量的线性化
作者:刘兴禄, 清华大学
清华-伯克利深圳学院,博士在读
欢迎关注我们的微信公众号 运小筹
非线性整数规划模型
考虑下面的非线性整数规划
max 3 y + x z s . t . 2 y + 3 z ⩽ 12 x + y ⩽ 1 x , y , ∈ { 0 , 1 } , 0 ⩽ z ⩽ 100 \begin{aligned} \max \quad \,\,\,& 3y + xz \\ s.t. \quad \,\,\,& 2y + 3z \leqslant 12 \\ & x + y \leqslant 1 \\ & x, y, \in \{0, 1\}, 0 \leqslant z \leqslant 100 \end{aligned} maxs.t.3y+xz2y+3z⩽12x+y⩽1x,y,∈{0,1},0⩽z⩽100
Gurobi求解代码
from gurobipy import *
model = Model('non-linear model')
x = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='x')
y = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='y')
z = model.addVar(lb=0, ub=100, vtype=GRB.CONTINUOUS, name='z')
model.setObjective(3 * y + x*z, GRB.MAXIMIZE)
model.addConstr(2 * y + 3*z <= 12)
model.addConstr(x + y <= 1)
model.optimize()
print('x:', x.x)
print('y:', y.x)
print('z:', z.x)
求解结果
Optimal solution found (tolerance 1.00e-04)
Best objective 4.000000000000e+00, best bound 4.000000000000e+00, gap 0.0000%
x: 1.0
y: 0.0
z: 4.0
线性化
- 令 w = x z w=xz w=xz,且 w ∈ [ 0 , U ] w\in [0, U] w∈[0,U]
- 引入下面的辅助约束
w ⩽ U x w ⩽ z w ⩾ z − U ( 1 − x ) \begin{aligned} &w \leqslant Ux \\ &w \leqslant z \\ &w \geqslant z - U(1-x) \end{aligned} w⩽Uxw⩽zw⩾z−U(1−x)
原模型等价为
max 3 y + x z s . t . 2 y + 3 z ⩽ 12 x + y ⩽ 1 w ⩽ U x w ⩽ z w ⩾ z − U ( 1 − x ) x , y , ∈ { 0 , 1 } , 0 ⩽ z , w ⩽ U \begin{aligned} \max \quad \,\,\,& 3y + xz \\ s.t. \quad \,\,\,& 2y + 3z \leqslant 12 \\ & x + y \leqslant 1 \\ &w \leqslant Ux \\ &w \leqslant z \\ &w \geqslant z - U(1-x) \\ & x, y, \in \{0, 1\}, 0 \leqslant z, w \leqslant U \end{aligned} maxs.t.3y+xz2y+3z⩽12x+y⩽1w⩽Uxw⩽zw⩾z−U(1−x)x,y,∈{0,1},0⩽z,w⩽U
具体推导见视频详解。
令
w
=
x
z
\begin{aligned} w=xz \end{aligned}
w=xz
我们分为下面几种情况讨论:
- 情况1
if x = 0 , then w = 0 \text{if}\,\,x=0 , \text{then}\,\,w=0 ifx=0,thenw=0, 容易得到 w − M x ⩽ 0 w-Mx\leqslant 0 w−Mx⩽0, 整理得 w ⩽ M x w\leqslant Mx w⩽Mx,这里 M M M是 w w w的一个上界即可,我们取最紧的上界,即 M = U M=U M=U。因此该式化简为
w
⩽
U
x
\begin{aligned} &w\leqslant Ux \end{aligned}
w⩽Ux
另外,我们易得
w
⩽
z
\begin{aligned} &w\leqslant z \end{aligned}
w⩽z
- 情况2
if x = 1 , then w = z \text{if}\,\,x=1, \text{then}\,\,w= z ifx=1,thenw=z, 由于逻辑约束不能写等号,因此我们将 = = =分成2个。
(1)
if
x
=
1
,
then
w
⩾
z
\text{if}\,\,x=1, \text{then}\,\,w\geqslant z
ifx=1,thenw⩾z, 此时
if
1
−
x
=
0
,
then
z
−
w
⩽
0
\text{if}\,\,1-x=0, \text{then}\,\,z-w\leqslant 0
if1−x=0,thenz−w⩽0, 也就是
z
−
w
−
M
(
1
−
x
)
⩽
0
z-w-M\left( 1-x \right) \leqslant 0
z−w−M(1−x)⩽0, 进而得到
w
⩾
z
−
M
(
1
−
x
)
\begin{aligned} &w\geqslant z-M\left( 1-x \right) \end{aligned}
w⩾z−M(1−x)
这里仍然取
M
=
U
M=U
M=U。
(2)
if
x
=
1
,
then
w
⩽
z
\text{if}\,\,x=1, \text{then}\,\,w\leqslant z
ifx=1,thenw⩽z, 此时
if
1
−
x
=
0
,
then
w
−
z
⩽
0
\text{if}\,\,1-x=0, \text{then}\,\,w-z\leqslant 0
if1−x=0,thenw−z⩽0, 也就是
w
−
z
−
M
(
1
−
x
)
⩽
0
w-z-M\left( 1-x \right) \leqslant 0
w−z−M(1−x)⩽0, 进而得到
w
⩽
z
+
M
(
1
−
x
)
\begin{aligned} &w\leqslant z + M\left( 1-x \right) \end{aligned}
w⩽z+M(1−x)
这里仍然取
M
=
U
M=U
M=U。
这样, if x = 1 , then w ⩾ z \text{if}\,\,x=1, \text{then}\,\,w\geqslant z ifx=1,thenw⩾z
并且, if x = 1 , then w ⩽ z \text{if}\,\,x=1, \text{then}\,\,w\leqslant z ifx=1,thenw⩽z
同时约束,就得到了 if x = 1 , then w = z \text{if}\,\,x=1, \text{then}\,\,w = z ifx=1,thenw=z.
但是其实,
if
x
=
1
,
then
w
⩽
z
\text{if}\,\,x=1, \text{then}\,\,w\leqslant z
ifx=1,thenw⩽z是不需要的,因为前面已经有了
w
⩽
z
w\leqslant z
w⩽z的约束,因此,约束
w ⩽ z + M ( 1 − x ) \begin{aligned} &w\leqslant z + M\left( 1-x \right) \end{aligned} w⩽z+M(1−x)
可以被约束 w ⩽ z w \leqslant z w⩽z给dominate掉,也就是说, w ⩽ z + M ( 1 − x ) w\leqslant z + M\left( 1-x \right) w⩽z+M(1−x)是冗余的。
下面我们用代码进行验证。
from gurobipy import *
model = Model('non-linear model')
x = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='x')
y = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='y')
z = model.addVar(lb=0, ub=100, vtype=GRB.CONTINUOUS, name='z')
w = model.addVar(lb=0, ub=100, vtype=GRB.CONTINUOUS, name='w')
model.setObjective(3 * y + w, GRB.MAXIMIZE)
model.addConstr(2 * y + 3*z <= 12)
model.addConstr(x + y <= 1)
model.addConstr(w <= 100 * x)
model.addConstr(w <= z)
model.addConstr(w >= z - 100 * (1 - x))
# model.addConstr(w <= z + 100 * (1 - x))
model.optimize()
print('x:', x.x)
print('y:', y.x)
print('z:', z.x)
print('w:', w.x)
求解结果为
Optimal solution found (tolerance 1.00e-04)
Best objective 4.000000000000e+00, best bound 4.000000000000e+00, gap 0.0000%
x: 1.0
y: 0.0
z: 4.0
w: 4.0
可见结果是一致的。
总结
一个0-1变量 x x x和一个连续变量 z z z相乘, 0 ⩽ z ⩽ U 0\leqslant z \leqslant U 0⩽z⩽U,则可以用下面3个约束以及一个辅助变量等价线性化。
- 引入辅助变量 w = x z w=xz w=xz, 且 w ∈ [ 0 , U ] w \in [0, U] w∈[0,U].
- 加入下面的3个约束
w ⩽ U x w ⩽ z w ⩾ z − U ( 1 − x ) \begin{aligned} &w \leqslant Ux \\ &w \leqslant z \\ &w \geqslant z - U(1-x) \end{aligned} w⩽Uxw⩽zw⩾z−U(1−x)
欢迎关注我们的微信公众号 运小筹
公众号往期推文如下