【MIP Cutting plane method】-1: Cover cuts
- MIP的标准形式
- 什么是Cover Cuts
- Cover Cuts的详细案例
- Stronger Cover Cuts及其案例
- Separation for Cover Cuts
- 用Separation生成 Cover Cuts的详细例子
- 调用Gurobi验证Cover Cuts和Stronger Cover Cuts的作用
- 线性松弛模型的解
- 加入Cover Cut
- 加入Stronger Cover Cut
- Separation for Cover Cuts
- 小结
- 参考文献
作者:刘兴禄,清华大学,清华大学深圳国际研究生院,清华-伯克利深圳学院,博士在读
MIP的标准形式
MIP的一般形式如下:
min
∑
i
∈
N
c
i
x
i
s
.
t
.
∑
i
∈
N
a
i
x
i
⩽
b
,
x
i
∈
Z
,
∀
i
∈
I
.
\begin{align} \min \quad &\sum_{i\in N} c_i x_i && \\ s.t. \quad & \sum_{i\in N} a_i x_i \leqslant b, && \\ \quad &x_{i} \in \mathbb{Z}, && \forall i \in I. \end{align}
mins.t.i∈N∑cixii∈N∑aixi⩽b,xi∈Z,∀i∈I.
其中,
I
I
I为取值要求为整数的变量的下标集合。
求解MIP的最高效的通用算法为Branch and cut
。该方法是将Cutting plane method
嵌入到Branch and bound
框架中,从而达到显著加速求解MIP的效果的一种精确算法框架。Cutting plane算法用于提升全局界限,收紧可行域,而Branch and bound用于搜索可行域。
本文主要来介绍一种基本的Cutting plane算法,即:Cover Cut
。此外,本文还对其拓展方法进行了介绍,并提供了相应的验证代码。
假设有下面的MIP或者IP:
min
∑
i
∈
N
c
i
x
i
s
.
t
.
∑
i
∈
N
a
i
x
i
⩽
b
,
x
i
∈
{
0
,
1
}
,
∀
i
∈
N
.
\begin{align} \min \quad &\sum_{i\in N} c_i x_i && \\ s.t. \quad & \sum_{i\in N} a_i x_i \leqslant b, && \\ \quad &x_{i} \in \{0, 1\}, && \forall i \in N. \end{align}
mins.t.i∈N∑cixii∈N∑aixi⩽b,xi∈{0,1},∀i∈N.
下面我们基于该模型来介绍Cover cuts
.
什么是Cover Cuts
考虑下面的约束
∑ j = 1 n a j x j ⩽ b , \begin{align} \sum_{j= 1}^{n} a_j x_j \leqslant b, && \end{align} j=1∑najxj⩽b,
是否可以找到上面约束的一个有效割平面?
可以基于Cover来生成有效的割平面。首先我们来介绍Cover的概念。
Cover
集合 C ⊆ N = { 1 , 2 , ⋯ , n } C\subseteq N = \{1, 2, \cdots, n\} C⊆N={1,2,⋯,n}被称之为一个Cover,当
∑ j ∈ C a j > b \begin{align} \sum_{j \in C} a_j > b \end{align} j∈C∑aj>b
Minimal Cover
如果 C C C是一个Cover,并且对于任意的 j ∈ C j \in C j∈C,而言,集合 C \ { j } C\backslash\{j\} C\{j}都不再是Cover,则称 C C C是一个最小Cover。
Cover cut
如果集合 C ⊆ N = { 1 , 2 , ⋯ , n } C\subseteq N = \{1, 2, \cdots, n\} C⊆N={1,2,⋯,n}是一个Cover,则下面的表达式是原问题的一个有效不等式:
∑ j ∈ C x j ⩽ ∣ C ∣ − 1. \begin{align} \sum_{j \in C} x_j \leqslant |C| - 1. \end{align} j∈C∑xj⩽∣C∣−1.
Cover Cuts的详细案例
考虑下面的约束
10
x
1
+
7
x
2
+
7
x
3
+
5
x
4
+
4
x
5
+
4
x
6
+
x
7
⩽
18.
\begin{align} 10x_1 + 7x_2 + 7x_3 + 5x_4 + 4x_5 + 4x_6 + x_7 \leqslant 18. \end{align}
10x1+7x2+7x3+5x4+4x5+4x6+x7⩽18.
我们可以很轻易地找到一个Cover C = { 1 , 2 , 3 } C = \{1, 2, 3\} C={1,2,3},因为 a 1 + a 2 + a 3 = 10 + 7 + 7 = 24 > 19 a_1+ a_2 + a_3 = 10+7+7=24 > 19 a1+a2+a3=10+7+7=24>19,从而可以推导出下面的有效不等式:
x 1 + x 2 + x 3 ⩽ 2. \begin{align} x_1 + x_2 + x_3 \leqslant 2. \end{align} x1+x2+x3⩽2.
类似地,我们可以很轻易地找到一个Cover C = { 3 , 4 , 5 , 6 } C = \{3, 4, 5, 6\} C={3,4,5,6},因为 a 3 + a 4 + a 5 + a 6 = 7 + 5 + 4 + 4 = 20 > 19 a_3+ a_4 + a_5 + a_6 = 7+5+4+4=20 > 19 a3+a4+a5+a6=7+5+4+4=20>19,从而可以推导出下面的有效不等式:
x 3 + x 4 + x 5 + x 6 ⩽ 3. \begin{align} x_3 + x_4 + x_5 + x_6 \leqslant 3. \end{align} x3+x4+x5+x6⩽3.
Stronger Cover Cuts及其案例
Stronger Cover cut
如果集合 C ⊆ N = { 1 , 2 , ⋯ , n } C\subseteq N = \{1, 2, \cdots, n\} C⊆N={1,2,⋯,n}是一个Cover,则下面的表达式是原问题的一个有效不等式:
∑ j ∈ E ( C ) x j ⩽ ∣ C ∣ − 1. \begin{align} \sum_{j \in E(C)} x_j \leqslant |C| - 1. \end{align} j∈E(C)∑xj⩽∣C∣−1.
其中,
E ( C ) = C ∪ { j ∣ a j ⩾ a i , ∀ i ∈ C } \begin{align} E(C) = C \cup \{j | a_j \geqslant a_i, \forall i \in C\} \end{align} E(C)=C∪{j∣aj⩾ai,∀i∈C}
即,将比 C C C中的序号对应的决策变量的约束系数都大的变量挑选出来。
再次考虑上面的约束。考虑 C = { 3 , 4 , 5 , 6 } C = \{3, 4, 5,6\} C={3,4,5,6},则容易得到 E ( C ) = { 1 , 2 , 3 , 4 , 5 , 6 } E(C) = \{1,2,3, 4, 5,6\} E(C)={1,2,3,4,5,6},因此可以推出Stronger Cover Cuts为:
x 1 + x 2 + x 3 + x 4 + x 5 + x 6 ⩽ 3. \begin{align} x_1 + x_2 + x_3 + x_4 + x_5 + x_6 \leqslant 3. \end{align} x1+x2+x3+x4+x5+x6⩽3.
上面的Stronger Cover Cuts要更紧凑。
下面我们用代码来验证Cover Cuts和Stronger Cover Cuts对于收紧下界的用处。
Separation for Cover Cuts
考虑有MIP的MILP的最优解是 x ∗ \mathbf{x}^* x∗,我们想,是否存在一个Cover Cut可以将这个 x ∗ \mathbf{x}^* x∗给割去。Separation for Cover Cuts就是为了达到这个目的。
在介绍Separation for Cover Cuts之前,我们先来看下面的一些分析。
考虑下面的Cover cuts:
∑
j
∈
C
x
j
⩽
∣
C
∣
−
1.
\begin{align} \sum_{j \in C} x_j \leqslant |C| - 1. \end{align}
j∈C∑xj⩽∣C∣−1.
上面的约束是说,
C
C
C中的元素不能被全选。我们考虑其反面,则可知,
C
C
C中至少有一个元素不被选(落选)
。因此,这个Cut可以被重写为
∑ j ∈ C ( 1 − x j ) ⩾ 1. \begin{align} \sum_{j \in C} (1 - x_j) \geqslant 1. \end{align} j∈C∑(1−xj)⩾1.
- 注意: x j x_j xj表示 j j j是否被选, ( 1 − x j ) (1-x_j) (1−xj)就表示 j j j是否落选。
接下来我们思考,如何将最优松弛小数解 x ∗ \mathbf{x}^* x∗给割去呢?一个直观的想法是,找到一个Cover C C C 满足下面的条件:
∑ j ∈ C a j > b ( 即集合 C 是一个Cover ) ∑ j ∈ C ( 1 − x j ∗ ) < 1 ( 但是当前小数最优解 x ∗ 违背了Cover Cut ) \begin{align} &\sum_{j \in C} a_j > b \quad&& (\text{即集合$C$是一个Cover}) \\ &\sum_{j \in C} (1 - x_j^*) < 1 \quad && (\text{但是当前小数最优解$\mathbf{x}^*$违背了Cover Cut}) \end{align} j∈C∑aj>bj∈C∑(1−xj∗)<1(即集合C是一个Cover)(但是当前小数最优解x∗违背了Cover Cut)
也就是说,若整数最优解为 x i n t ∗ \mathbf{x}_{int}^* xint∗,则 x i n t ∗ \mathbf{x}_{int}^* xint∗一定满足上面的Cover Cut,但是如果我们能找到一个Cover C C C,使得当前最优松弛小数解 x ∗ \mathbf{x}^* x∗不满足Cover Cut,这说明我们找到了一个Cover Cut,可以将当前最优松弛小数解 x ∗ \mathbf{x}^* x∗割去,从而提升了界限,缩小了可行域。
但是问题是,这个 C C C如何去找呢?
有一个很不错的办法是,构建一个整数规划模型去找,该模型如下:
min ∑ i ∈ N ( 1 − x j ∗ ) z j s . t . ∑ i ∈ N a j z j > b , z j ∈ { 0 , 1 } , ∀ i ∈ N . \begin{align} \min \quad &\sum_{i\in N} (1 - x_j^*) z_j && \\ s.t. \quad & \sum_{i\in N} a_j z_j > b, && \\ \quad &z_{j} \in \{0, 1\}, && \forall i \in N. \end{align} mins.t.i∈N∑(1−xj∗)zji∈N∑ajzj>b,zj∈{0,1},∀i∈N.
其中 z j z_j zj表示下标 j j j是否包含在要找的集合 C C C中,是一个辅助0-1决策变量。
求解上述模型,如果最优值小于1,则我们就可以找到一个Cut,其中 C = { j ∣ z j = 1 , ∀ j ∈ N } C = \{j | z_j=1, \forall j \in N\} C={j∣zj=1,∀j∈N}. 即,若 z j = 1 z_j = 1 zj=1,则其下标就会被加入到 C C C中。
用Separation生成 Cover Cuts的详细例子
考虑下面的约束
45
x
1
+
46
x
2
+
79
x
3
+
54
x
4
+
53
x
5
+
125
x
6
⩽
178.
\begin{align} 45x_1 + 46x_2 + 79x_3 + 54x_4 + 53x_5 + 125x_6 \leqslant 178. \end{align}
45x1+46x2+79x3+54x4+53x5+125x6⩽178.
假设我们得到的解为:
x
∗
=
(
0
,
0
,
3
4
,
1
2
,
1
,
0
)
.
\begin{align} \mathbf{x}^* = \left(0, 0, \frac{3}{4}, \frac{1}{2}, 1, 0\right). \end{align}
x∗=(0,0,43,21,1,0).
我们如何来获得一个Cover Cut呢?我们来构建下面的模型:
min ∑ i ∈ N ( 1 − x j ∗ ) z j s . t . ∑ i ∈ N a j z j > b , z j ∈ { 0 , 1 } , ∀ i ∈ N . \begin{align} \min \quad &\sum_{i\in N} (1 - x_j^*) z_j && \\ s.t. \quad & \sum_{i\in N} a_j z_j > b, && \\ \quad &z_{j} \in \{0, 1\}, && \forall i \in N. \end{align} mins.t.i∈N∑(1−xj∗)zji∈N∑ajzj>b,zj∈{0,1},∀i∈N.
写成具体的形式即:
min z 1 + z 2 + 1 4 z 3 + 1 2 z 4 + z 6 s . t . 45 z 1 + 46 z 2 + 79 z 3 + 54 z 4 + 53 z 5 + 125 z 6 > 178. z 1 , z 2 , z 3 , z 4 , z 5 , z 6 ∈ { 0 , 1 } . \begin{align} \min \quad & z_1 + z_2 + \frac{1}{4}z_3 + \frac{1}{2}z_4 + z_6 \\ s.t. &45z_1 + 46z_2 + 79z_3 + 54z_4 + 53z_5 + 125z_6 > 178. \\ \quad &z_1, z_2, z_3, z_4,z_5, z_6 \in \{0, 1\}. \end{align} mins.t.z1+z2+41z3+21z4+z645z1+46z2+79z3+54z4+53z5+125z6>178.z1,z2,z3,z4,z5,z6∈{0,1}.
用Python调用Gurobi求解这个模型,代码如下:
from gurobipy import *
model = Model()
z = {}
for i in range(1, 7):
z[i] = model.addVar(lb=0, ub=1, vtype=GRB.INTEGER, name='z_'+str(i))
model.setObjective(z[1] + z[2] + 0.25*z[3] + 0.5*z[4] + z[6], GRB.MINIMIZE)
model.addConstr(45*z[1] + 46*z[2] + 79*z[3] + 54*z[4] + 53*z[5] + 125*z[6] >= 177.99999)
model.optimize()
print('Obj: {}'.format(model.ObjVal))
for i in range(1, 7):
print('{} = {}'.format(z[i].VarName, z[i].x))
求解结果如下:
Best objective 7.500000000000e-01, best bound 7.500000000000e-01, gap 0.0000%
Obj: 0.75
z_1 = -0.0
z_2 = -0.0
z_3 = 1.0
z_4 = 1.0
z_5 = 1.0
z_6 = -0.0
可见,目标函数
Obj
∗
=
0.75
<
1
\text{Obj}^* = 0.75<1
Obj∗=0.75<1,因此可以找到一个Cover,即
C
=
{
3
,
4
,
5
}
C=\{3,4,5\}
C={3,4,5}。可以找到一个Cover Cut,为:
x
3
+
x
4
+
x
5
⩽
2.
\begin{align} x_3 + x_4 + x_5 \leqslant 2. \end{align}
x3+x4+x5⩽2.
此外,我们可以继续探讨上面的Separation model,我们将 z j z_j zj用 1 − y j 1-y_j 1−yj代替,则得到:
min ∑ i ∈ N ( 1 − x j ∗ ) ( 1 − y j ) s . t . ∑ i ∈ N a j ( 1 − y j ) > b , y j ∈ { 0 , 1 } , ∀ i ∈ N . \begin{align} \min \quad &\sum_{i\in N} (1 - x_j^*) (1-y_j) && \\ s.t. \quad & \sum_{i\in N} a_j (1-y_j) > b, && \\ \quad &y_{j} \in \{0, 1\}, && \forall i \in N. \end{align} mins.t.i∈N∑(1−xj∗)(1−yj)i∈N∑aj(1−yj)>b,yj∈{0,1},∀i∈N.
进一步,模型可以转化为
max ∑ i ∈ N ( 1 − x j ∗ ) y j s . t . ∑ i ∈ N a j y j < ∑ i ∈ N a j − b , y j ∈ { 0 , 1 } , ∀ i ∈ N . \begin{align} \max \quad &\sum_{i\in N} (1 - x_j^*) y_j && \\ s.t. \quad & \sum_{i\in N} a_j y_j < \sum_{i\in N} a_j - b, && \\ \quad &y_{j} \in \{0, 1\}, && \forall i \in N. \end{align} maxs.t.i∈N∑(1−xj∗)yji∈N∑ajyj<i∈N∑aj−b,yj∈{0,1},∀i∈N.
这就可以转化为一个背包问题
。
调用Gurobi验证Cover Cuts和Stronger Cover Cuts的作用
考虑下面的0-1背包问题的整数规划模型。
max 5 x 1 + 2 x 2 + 4 x 3 + 2 x 4 + 3 x 5 + 3 x 6 + 2 x 7 s . t . 10 x 1 + 7 x 2 + 7 x 3 + 5 x 4 + 4 x 5 + 4 x 6 + x 7 ⩽ 18. x 1 , x 2 , x 3 , x 4 , x 5 , x 6 , x 7 ∈ { 0 , 1 } . \begin{align} \max \quad & 5 x_1 + 2x_2 + 4x_3 + 2x_4 + 3x_5 + 3x_6 + 2 x_7 \\ s.t. &10x_1 + 7x_2 + 7x_3 + 5x_4 + 4x_5 + 4x_6 + x_7 \leqslant 18. \\ \quad &x_1, x_2, x_3, x_4,x_5, x_6, x_7 \in \{0, 1\}. \end{align} maxs.t.5x1+2x2+4x3+2x4+3x5+3x6+2x710x1+7x2+7x3+5x4+4x5+4x6+x7⩽18.x1,x2,x3,x4,x5,x6,x7∈{0,1}.
该问题的整数最优解为:
x
3
=
x
5
=
x
6
=
1
Obj
∗
=
12
\begin{align} &x_3=x_5=x_6=1 \\ &\text{Obj}^* = 12 \end{align}
x3=x5=x6=1Obj∗=12
线性松弛模型的解
我们用Python调用Gurobi求解上述模型的线性松弛,代码如下:
from gurobipy import *
model = Model()
x = {}
for i in range(1, 8):
x[i] = model.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS, name='x_'+str(i))
model.setObjective(5*x[1] + 2*x[2] + 4*x[3] + 2*x[4] + 3*x[5] + 3*x[6] + 2*x[7], GRB.MAXIMIZE)
model.addConstr(10*x[1] + 7*x[2] + 7*x[3] + 5*x[4] + 4*x[5] + 4*x[6] + x[7] <= 18)
model.optimize()
print('Obj: {}'.format(model.ObjVal))
for i in range(1, 7):
print('{} = {}'.format(x[i].VarName, x[i].x))
求解结果如下:
Obj: 13.0
x_1 = 0.2
x_2 = 0.0
x_3 = 1.0
x_4 = 0.0
x_5 = 1.0
x_6 = 1.0
x_7 = 1.0
这说明此时, U B = 13 UB=13 UB=13,但是是小数解。
加入Cover Cut
我们尝试生成一个Cover Cut:
首先加入Cover Cut 1:
x
1
+
x
2
+
x
3
⩽
2.
\begin{align} x_1 + x_2 + x_3 \leqslant 2. \end{align}
x1+x2+x3⩽2.
发现加入后, U B = 13 UB=13 UB=13,没变。
我们继续加入Cover Cut 2:
x
3
+
x
4
+
x
5
+
x
6
⩽
3.
\begin{align} x_3 + x_4 + x_5 + x_6 \leqslant 3. \end{align}
x3+x4+x5+x6⩽3.
发现加入后,
U
B
=
13
UB=13
UB=13,依然没有变。
接下来我们生成所有的Cover Cut,具体如下:
x 1 + x 2 + x 3 ⩽ 2 x 1 + x 2 + x 4 ⩽ 2 x 1 + x 2 + x 5 ⩽ 2 x 1 + x 2 + x 6 ⩽ 2 x 1 + x 3 + x 4 ⩽ 2 x 1 + x 3 + x 5 ⩽ 2 x 1 + x 3 + x 6 ⩽ 2 x 2 + x 3 + x 4 ⩽ 2 x 3 + x 4 + x 5 + x 6 ⩽ 3 \begin{align*} &x_1 + x_2 + x_3 \leqslant 2 \\ &x_1 + x_2 + x_4 \leqslant 2 \\ &x_1 + x_2 + x_5 \leqslant 2 \\ &x_1 + x_2 + x_6 \leqslant 2 \\ &x_1 + x_3 + x_4 \leqslant 2 \\ &x_1 + x_3 + x_5 \leqslant 2 \\ &x_1 + x_3 + x_6 \leqslant 2 \\ &x_2 + x_3 + x_4 \leqslant 2 \\ &x_3 + x_4 + x_5 + x_6 \leqslant 3 \end{align*} x1+x2+x3⩽2x1+x2+x4⩽2x1+x2+x5⩽2x1+x2+x6⩽2x1+x3+x4⩽2x1+x3+x5⩽2x1+x3+x6⩽2x2+x3+x4⩽2x3+x4+x5+x6⩽3
将上述Cover Cut全部加入到模型,求解的结果为:
Obj: 12.75
x_1 = 0.25
x_2 = 0.0
x_3 = 0.75
x_4 = 0.25
x_5 = 1.0
x_6 = 1.0
x_7 = 1.0
可以看到,目标函数变化为12.75,略有改进。
实际上,Cover Cuts的效果一般不会太理想,因此需要加入更强的Cut。
加入Stronger Cover Cut
我们加入Stronger Cover Cut 1:
x 1 + x 2 + x 3 + x 4 + x 5 + x 6 ⩽ 3. \begin{align} x_1 + x_2 + x_3 + x_4 + x_5 + x_6 \leqslant 3. \end{align} x1+x2+x3+x4+x5+x6⩽3.
代码如下:
model.addConstr(10*x[1] + 7*x[2] + 7*x[3] + 5*x[4] + 4*x[5] + 4*x[6] + x[7] <= 18)
model.addConstr(x[1] + x[2] + x[3] + x[4] + x[5] + x[6] <= 3)
求解结果如下:
Obj: 12.666666666666666
x_1 = 0.3333333333333333
x_2 = 0.0
x_3 = 1.0
x_4 = 0.0
x_5 = 0.6666666666666667
x_6 = 1.0
x_7 = 1.0
发现加入Stronger Cover Cut 1后, U B = 12.67 UB=12.67 UB=12.67,有所改善,说明Stronger Cover Cut 1有效。一个Stronger Cover Cut 1就比9个Cover Cut效果更好。
我们来生成所有的Stronger Cover Cut,可以得到
x 1 + x 2 + x 3 + x 4 ⩽ 2 x 1 + x 2 + x 3 + x 4 + x 5 + x 6 ⩽ 3 \begin{align*} &x_1 + x_2 + x_3 + x_4 \leqslant 2 \\ &x_1 + x_2 + x_3 + x_4 + x_5 + x_6 \leqslant 3 \end{align*} x1+x2+x3+x4⩽2x1+x2+x3+x4+x5+x6⩽3
加入所有的Stronger Cover Cut之后,求解结果没有进一步改进。
接下来我们继续尝试Separation的办法。
Separation for Cover Cuts
我们基于加入了所有Stronger Cover Cut之后的模型继续添加Cuts。
可知,当前解为
x ∗ = ( 1 3 , 0 , 1 , 0 , 2 3 , 1 , 1 ) . \begin{align} \mathbf{x}^* = \left(\frac{1}{3}, 0, 1, 0, \frac{2}{3}, 1, 1\right). \end{align} x∗=(31,0,1,0,32,1,1).
构建Separation模型,如下:
min 2 3 z 1 + z 2 + z 4 + 1 3 z 5 s . t . 10 z 1 + 7 z 2 + 7 z 3 + 5 z 4 + 4 z 5 + 4 z 6 + z 7 > 18. z 1 , z 2 , z 3 , z 4 , z 5 , z 6 ∈ { 0 , 1 } . \begin{align} \min \quad & \frac{2}{3}z_1 + z_2 + z_4 + \frac{1}{3}z_5 \\ s.t. &10z_1 + 7z_2 + 7z_3 + 5z_4 + 4z_5 + 4z_6 + z_7 > 18. \\ \quad &z_1, z_2, z_3, z_4,z_5, z_6 \in \{0, 1\}. \end{align} mins.t.32z1+z2+z4+31z510z1+7z2+7z3+5z4+4z5+4z6+z7>18.z1,z2,z3,z4,z5,z6∈{0,1}.
使用Python调用Gurobi求解上述模型,具体代码为:
from gurobipy import *
model = Model()
x = {}
for i in range(1, 8):
x[i] = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='z_'+str(i))
model.setObjective(0.67*x[1] + 1*x[2] + 0*x[3] + 1*x[4] + 0.33*x[5] + 0*x[6] + 0*x[7], GRB.MINIMIZE)
model.addConstr(10*x[1] + 7*x[2] + 7*x[3] + 5*x[4] + 4*x[5] + 4*x[6] + x[7] >= 17.9999999)
model.optimize()
print('Obj: {}'.format(model.ObjVal))
for i in range(1, 8):
print('{} = {}'.format(x[i].VarName, x[i].x))
求解结果为:
Obj: 0.67
z_1 = 1.0
z_2 = 0.0
z_3 = 1.0
z_4 = 0.0
z_5 = 0.0
z_6 = 1.0
z_7 = 1.0
可知,
Obj
∗
=
0.67
<
1
\text{Obj}^* = 0.67 < 1
Obj∗=0.67<1,因此可以生成一个Cover
C
=
{
1
,
3
,
6
,
7
}
C = \{1, 3, 6, 7\}
C={1,3,6,7},构造下面的Cover Cut:
x
1
+
x
3
+
x
6
+
x
7
⩽
3
\begin{align} &x_1 + x_3 + x_6 + x_7 \leqslant 3 \end{align}
x1+x3+x6+x7⩽3
加入该Cut,可得小数最优解依然为12.67,没有改进。说明没有生成新的有效割。
但是如果只加入 x 1 + x 3 + x 6 + x 7 ⩽ 3 x_1 + x_3 + x_6 + x_7 \leqslant 3 x1+x3+x6+x7⩽3,不加入Stronger Cover Cut,则该Cover Cut还是有效的,加入后 Obj ∗ = 12.8 \text{Obj}^* = 12.8 Obj∗=12.8,比不加任何Cut的界限紧。
小结
本文介绍了求解混合整数规划问题的Cutting plane method中的Cover Cut,具体包括基本的Cover Cut,以及加强版本的Stronger Cover Cut以及用于割去当前小数解的Separation的方法。
为了帮助读者直观理解这些方法,我们提供了相应的完整代码。每一种Cut的效率随问题而异,读者需要自行验证。
参考文献
[1]. Wolsey L A. Integer programming[M]. John Wiley & Sons, 2020.
[2]. Discrete Optimization: cover cuts branch and cut seven bridges traveling salesman.https://www.youtube.com/watch?v=8yajCJKezZQ