优化| 割平面算法(2): Cover Cuts, Strengthening, Separation及其拓展(理论与实战详解)

作者:刘兴禄,清华大学,清华大学深圳国际研究生院,清华-伯克利深圳学院,博士在读

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.iNcixiiNaixib,xiZ,iI.
其中, 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.iNcixiiNaixib,xi{0,1},iN.

下面我们基于该模型来介绍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=1najxjb,

是否可以找到上面约束的一个有效割平面?

可以基于Cover来生成有效的割平面。首先我们来介绍Cover的概念。

Cover
集合 C ⊆ N = { 1 , 2 , ⋯   , n } C\subseteq N = \{1, 2, \cdots, n\} CN={1,2,,n}被称之为一个Cover,当
∑ j ∈ C a j > b \begin{align} \sum_{j \in C} a_j > b \end{align} jCaj>b

Minimal Cover
如果 C C C是一个Cover,并且对于任意的 j ∈ C j \in C jC,而言,集合 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\} CN={1,2,,n}是一个Cover,则下面的表达式是原问题的一个有效不等式:
∑ j ∈ C x j ⩽ ∣ C ∣ − 1. \begin{align} \sum_{j \in C} x_j \leqslant |C| - 1. \end{align} jCxjC1.

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+x718.

我们可以很轻易地找到一个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+x32.

类似地,我们可以很轻易地找到一个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+x63.

Stronger Cover Cuts及其案例

Stronger Cover cut
如果集合 C ⊆ N = { 1 , 2 , ⋯   , n } C\subseteq N = \{1, 2, \cdots, n\} CN={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} jE(C)xjC1.
其中,
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{jajai,iC}
即,将比 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+x63.

上面的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} jCxjC1.
上面的约束是说, 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} jC(1xj)1.

  • 注意: x j x_j xj表示 j j j是否被选, ( 1 − x j ) (1-x_j) (1xj)就表示 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} jCaj>bjC(1xj)<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.iN(1xj)zjiNajzj>b,zj{0,1},iN.
其中 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={jzj=1,jN}. 即,若 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+125x6178.
假设我们得到的解为:
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.iN(1xj)zjiNajzj>b,zj{0,1},iN.

写成具体的形式即:

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+x52.

此外,我们可以继续探讨上面的Separation model,我们将 z j z_j zj 1 − y j 1-y_j 1yj代替,则得到:

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.iN(1xj)(1yj)iNaj(1yj)>b,yj{0,1},iN.

进一步,模型可以转化为

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.iN(1xj)yjiNajyj<iNajb,yj{0,1},iN.

这就可以转化为一个背包问题

调用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+x718.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+x32.

发现加入后, 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+x63.
发现加入后, 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+x32x1+x2+x42x1+x2+x52x1+x2+x62x1+x3+x42x1+x3+x52x1+x3+x62x2+x3+x42x3+x4+x5+x63

将上述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+x63.

代码如下:

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+x42x1+x2+x3+x4+x5+x63

加入所有的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+x73
加入该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+x73,不加入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

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
C# 电子锯优化算法通常用于解决优化问题,如在切木材、金属等材料时,如何最大程度地减少浪费和提高效率。这个算法的目标是找到一种最佳的切方案,以最大化利用材料并减少浪费。 在C#中实现电子锯优化算法,你可以使用数学规划或启发式算法来解决这个问题。以下是一个简单的示例代码,展示了如何使用贪婪算法来实现电子锯优化: ```csharp using System; using System.Collections.Generic; class Program { static void Main(string[] args) { int stockLength = 120; // 材料的长度 List<int> cutPieces = new List<int> { 40, 30, 20, 15, 10 }; // 需要切的长度 List<int> optimalCuts = CalculateOptimalCuts(stockLength, cutPieces); Console.WriteLine("Optimal cuts: " + string.Join(", ", optimalCuts)); } static List<int> CalculateOptimalCuts(int stockLength, List<int> cutPieces) { List<int> optimalCuts = new List<int>(); int remainingLength = stockLength; while (cutPieces.Count > 0 && remainingLength > 0) { int bestCut = -1; int bestCutIndex = -1; for (int i = 0; i < cutPieces.Count; i++) { if (cutPieces[i] <= remainingLength && cutPieces[i] > bestCut) { bestCut = cutPieces[i]; bestCutIndex = i; } } if (bestCutIndex >= 0) { optimalCuts.Add(bestCut); remainingLength -= bestCut; cutPieces.RemoveAt(bestCutIndex); } else { break; } } return optimalCuts; } } ``` 在上面的示例中,我们假设材料的长度为120,需要切的长度为40、30、20、15和10。程序会根据贪婪算法找到最佳的切方案,并返回最佳的切长度列表。 请注意,这只是一个简单的示例,实际上电子锯优化算法可能涉及到更复杂的问题和算法。你可以根据具体的需求来调整和扩展该算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值