线性规划例子
啤酒厂问题
- 每日销售上限:100箱啤酒
- 营业时间:14小时
- 生产1箱生啤需1小时
- 生产1箱黑啤需2小时
- 生啤售价:20美元/箱
- 黑啤售价:30美元/箱
目标:最大化利润
我们可以根据上述描述,建立数学模型。假设生啤生产
x
1
x_1
x1箱,黑啤生产
x
2
x_2
x2箱,那么就有如下的线性规划式子。
M
a
x
x
1
,
x
2
20
×
x
1
+
30
×
x
2
s
.
t
.
x
1
+
2
×
x
2
<
=
14
x
1
+
x
2
<
=
100
x
1
,
x
2
>
=
0
Max_{x_1,x_2} \qquad20 \times x_1 + 30 \times x_2 \\ \qquad s.t. \qquad \qquad x_1 + 2\times x_2<=14 \\\qquad \qquad \qquad x_1+x_2<=100 \\\qquad \qquad \qquad x_1,x_2>=0
Maxx1,x220×x1+30×x2s.t.x1+2×x2<=14x1+x2<=100x1,x2>=0
图解法
通过求解上述的线性规划问题即可得到最优的生产计划。那么如何求解呢?根据图解法可以看出最优值为2400。而且可以观察到随着z的上下平移,最终取到的最优值必定是z与凸多边形(约束域)的某一个顶点相交得到。这样的话如果想求解一个线性规划问题,只需要遍历这个凸多边形(在高维空间中是凸多面体)的每一个顶点,对目标函数值大小进行比较即可。

单纯形法数学推导
将问题标准化并转为矩阵形式
那么如何将遍历各个顶点的过程转化为数学语言来表述呢,且是否真的需要将所有顶点遍历一遍,有没有更高效的遍历方法?
还是上述的问题,我们可以把问题先化为标准型再写成矩阵形式。
标准型:
M
i
n
x
1
,
x
2
−
20
×
x
1
−
30
×
x
2
s
.
t
.
x
1
+
2
×
x
2
+
x
3
=
14
x
1
+
x
2
+
x
4
=
100
x
1
,
x
2
,
x
3
,
x
4
>
=
0
Min_{x_1,x_2} \qquad-20 \times x_1 - 30 \times x_2 \\ \qquad s.t. \qquad \qquad x_1 + 2\times x_2 + x_3=14 \\\qquad \qquad \qquad x_1+x_2 + x_4 =100 \\\qquad \qquad \qquad x_1,x_2,x_3,x_4>=0
Minx1,x2−20×x1−30×x2s.t.x1+2×x2+x3=14x1+x2+x4=100x1,x2,x3,x4>=0
这个问题的矩阵形式为:
Minimize
c
⊤
x
Subject to:
A
x
=
b
and
x
≥
0
\text{Minimize} \quad \mathbf{c}^\top \mathbf{x}\\ \text{Subject to:} \quad \mathbf{Ax} = \mathbf{b} \quad \text{and} \quad \mathbf{x} \geq \mathbf{0}
Minimizec⊤xSubject to:Ax=bandx≥0
其中:
c = [ − 20 − 30 0 0 ] , x = [ x 1 x 2 x 3 x 4 ] , b = [ 14 100 ] \mathbf{c} = \begin{bmatrix} -20 \\ -30 \\ 0 \\ 0 \\ \end{bmatrix}, \quad \mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ x_3 \\ x_4 \\ \end{bmatrix}, \quad \mathbf{b} = \begin{bmatrix} 14 \\ 100 \\ \end{bmatrix} c= −20−3000 ,x= x1x2x3x4 ,b=[14100]
约束矩阵 A \mathbf{A} A为:
A
=
[
1
2
1
0
1
1
0
1
]
\mathbf{A} = \begin{bmatrix} 1 & 2 & 1 & 0 \\ 1 & 1 & 0 & 1 \\ \end{bmatrix}
A=[11211001]
这里的变量
x
3
x_3
x3 和
x
4
x_4
x4 是松弛变量,用于将不等式约束转换为等式约束。
开始推导
令
x
=
[
x
B
,
x
N
]
,
A
=
[
B
,
N
]
,
c
=
[
c
B
,
c
N
]
T
x = [x_B,x_N],A = [B,N],c = [c_B,c_N]^T
x=[xB,xN],A=[B,N],c=[cB,cN]T(注意这里的B一定要是一个可逆矩阵),初始化时令
x
N
x_N
xN全为0.
那么原问题可以转化为如下形式
M
i
n
i
m
i
z
e
c
B
×
x
B
+
c
N
×
x
N
s
.
t
.
B
×
x
B
+
N
×
x
N
=
b
x
B
>
=
0
,
x
N
>
=
0
Minimize \qquad c_B\times x_B + c_N\times x_N \\ s.t.\qquad \qquad \qquad B\times x_B + N\times x_N = b \\ \qquad \qquad \qquad x_B>=0,x_N>=0
MinimizecB×xB+cN×xNs.t.B×xB+N×xN=bxB>=0,xN>=0
将约束条件
B
×
x
B
+
N
×
x
N
=
b
B\times x_B + N\times x_N = b
B×xB+N×xN=b可以等价变形为
x
B
=
B
−
1
(
b
−
N
×
x
N
)
=
B
−
1
b
x_B = B^{-1}(b - N\times x_N) = B^{-1}b
xB=B−1(b−N×xN)=B−1b
注意:上面用到了
B
−
1
B^{-1}
B−1,这也是为什么说B得是可逆矩阵的原因,在后面的转化还用到了
x
N
x_N
xN初始全为0。
将变换之后的式子带回目标函数
c
B
×
x
B
+
c
N
×
x
N
c_B\times x_B + c_N\times x_N
cB×xB+cN×xN就有
c
B
×
B
−
1
(
b
−
N
×
x
N
)
+
c
N
×
x
N
c_B\times B^{-1}(b - N\times x_N) + c_N\times x_N
cB×B−1(b−N×xN)+cN×xN,进一步化简可以得到如下式子(由于在初始化时
x
N
x_N
xN全为0)
c
B
B
−
1
b
+
(
c
N
−
c
B
B
−
1
N
)
x
N
=
c
B
B
−
1
b
c_BB^{-1}b +(c_N - c_BB^{-1}N)x_N = c_BB^{-1}b
cBB−1b+(cN−cBB−1N)xN=cBB−1b
可以观察到,目标函数还有进一步变小的可能,那就是
(
c
N
−
c
B
B
−
1
N
)
x
N
(c_N - c_BB^{-1}N)x_N
(cN−cBB−1N)xN之前由于
x
N
x_N
xN全为0,所以这一项也为0,但如果
x
N
x_N
xN中某一项的系数为负,将该项从0变为非0即可进一步减小目标函数。那么如何变更高效呢?就是找到负系数中,负系数绝对值最大的那一项(在x变化量一致的情况下,负系数绝对值越大,目标函数值下降的就越多)。
那么也可以推出,如果 ( c N − c B B − 1 N ) (c_N - c_BB^{-1}N) (cN−cBB−1N)全部为正,即使将 x N x_N xN的任意一项由0变为非0,目标函数值也不会降低,这时就可以说已经找到了目标函数的最小值,这也是算法的收敛准则: ( c N − c B B − 1 N ) > = 0 (c_N - c_BB^{-1}N)>=0 (cN−cBB−1N)>=0。
那么假如
(
c
N
−
c
B
B
−
1
N
)
i
(c_N - c_BB^{-1}N)_i
(cN−cBB−1N)i是负系数中系数绝对值最大的的那一项,对应这一项的变量为
x
N
i
x_{N_{i}}
xNi,我们要将其由0变为非0,那么要变为多少呢?
注意到对于
x
B
x_B
xB还有
x
B
>
=
0
x_B>=0
xB>=0的约束。且有
x
B
=
B
−
1
(
b
−
N
×
x
N
)
x_B = B^{-1}(b - N\times x_N)
xB=B−1(b−N×xN),
x
N
x_N
xN的变化也会引起
x
B
x_B
xB的变化,我们应该使变化之后的
x
B
x_B
xB仍然满足非负性。在
x
B
>
=
0
x_B>=0
xB>=0的情况下,
x
N
x_N
xN要变得尽可能大。那么就有如下式子:
B
−
1
(
b
−
N
×
x
N
)
>
=
0
b
−
N
×
x
N
>
=
0
B^{-1}(b - N\times x_N)>=0 \\b - N\times x_N>=0 \\
B−1(b−N×xN)>=0b−N×xN>=0
为了满足上述式子,而
x
N
i
x_{N_{i}}
xNi变得又要尽可能多,那么
x
N
i
=
m
i
n
{
b
N
}
=
b
j
N
j
x_{N_{i}} = min\{\frac{b}{N} \} = \frac{b_j}{N_j}
xNi=min{Nb}=Njbj,这样的话同时就把
x
B
j
x_{B_j}
xBj变为0.
如此就完成了一轮迭代,不断迭代知道达到收敛准则为止。迭代的过程其实也是从一个端点替换到另一个端点的过程。
实例
对于线性规划问题
m
a
x
2
x
1
+
3
x
2
s
.
t
.
4
x
1
+
x
2
<
=
16
−
x
1
+
x
2
<
=
6
x
1
,
x
2
>
=
0
max \qquad 2x_1 + 3x_2 \\s.t. \qquad 4x_1 + x_2<=16 \\ \qquad -x_1+x_2<=6 \\ \qquad x_1,x_2>=0
max2x1+3x2s.t.4x1+x2<=16−x1+x2<=6x1,x2>=0
图解法
利用图解法可以看到红色的线是最优的等值线,
x
1
=
2
,
x
2
=
8
x_1 = 2,x_2 = 8
x1=2,x2=8.

单纯形法
将原来的线性规划化为标准型并写为矩阵形式
m
i
n
−
2
x
1
−
3
x
2
s
.
t
.
4
x
1
+
x
2
+
x
3
=
16
−
x
1
+
x
2
+
x
4
=
6
x
1
,
x
2
,
x
3
,
x
4
>
=
0
min \qquad -2x_1 - 3x_2 \\s.t. \qquad 4x_1 + x_2+x_3=16 \\ \qquad -x_1+x_2+x_4=6 \\ \qquad x_1,x_2,x_3,x_4>=0
min−2x1−3x2s.t.4x1+x2+x3=16−x1+x2+x4=6x1,x2,x3,x4>=0
其中,
x
3
x_3
x3 和
x
4
x_4
x4是松弛变量。
矩阵形式为:
目标函数:
Maximize
c
⊤
x
\text{Maximize} \quad \mathbf{c}^\top \mathbf{x}
Maximizec⊤x
其中,
c
=
[
−
2
−
3
0
0
]
\mathbf{c} = \begin{bmatrix} -2 \\ -3 \\ 0 \\ 0 \end{bmatrix}
c=
−2−300
为目标函数的系数向量。
约束条件:
A
x
=
b
\mathbf{Ax} = \mathbf{b}
Ax=b,其中
A
=
[
4
1
1
0
−
1
1
0
1
]
\mathbf{A} = \begin{bmatrix} 4 & 1 & 1 & 0 \\ -1 & 1 & 0 & 1 \end{bmatrix}
A=[4−1111001]是约束系数矩阵,
x
=
[
x
1
x
2
x
3
x
4
]
\mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ x_3 \\ x_4 \end{bmatrix}
x=
x1x2x3x4
是决策变量向量,
b
=
[
16
6
]
\mathbf{b} = \begin{bmatrix} 16 \\ 6 \end{bmatrix}
b=[166]是约束右端项向量。
因此,标准型的线性规划问题可以表示为:
Maximize
c
⊤
x
Subject to
A
x
=
b
x
≥
0
\begin{align*} \text{Maximize} \quad & \mathbf{c}^\top \mathbf{x} \\ \text{Subject to} \quad & \mathbf{Ax} = \mathbf{b} \\ & \mathbf{x} \geq 0 \end{align*}
MaximizeSubject toc⊤xAx=bx≥0
那么根据上述单纯形法的推导,
x
B
=
[
x
3
,
x
4
]
,
x
N
=
[
x
1
,
x
2
]
,
N
=
[
4
1
−
1
1
]
,
B
=
[
1
0
0
1
]
,
c
B
=
[
0
,
0
]
,
c
N
=
[
−
2
,
−
3
]
x_B = [x_3,x_4],x_N = [x_1,x_2],N = \begin{bmatrix} 4 & 1 \\ -1 & 1 \end{bmatrix},B = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix},c_B = [0,0],c_N = [-2,-3]
xB=[x3,x4],xN=[x1,x2],N=[4−111],B=[1001],cB=[0,0],cN=[−2,−3]
初始时令
x
N
=
[
0
,
0
]
x_N = [0,0]
xN=[0,0]
第一轮迭代:
此时
c
N
−
c
B
B
−
1
N
=
[
−
2
,
−
3
]
c_N - c_BB^{-1}N = [-2,-3]
cN−cBB−1N=[−2,−3]因此选择
x
2
x_2
x2作为入基变量更为高效,且
b
−
N
x
N
=
[
16
−
4
x
1
−
x
2
6
+
x
1
−
x
2
]
>
=
0
b - Nx_N =\begin{bmatrix} 16 - 4x_1 - x_2 \\ 6 +x_1-x_2 \end{bmatrix}>=0
b−NxN=[16−4x1−x26+x1−x2]>=0故
x
2
=
6
x_2 = 6
x2=6并令
x
4
=
0
x_4 = 0
x4=0,
x
2
x_2
x2入基,
x
4
x_4
x4出基.
经过此轮迭代后,各变量如下
x
B
=
[
x
3
,
x
2
]
,
x
N
=
[
x
1
,
x
4
]
,
N
=
[
4
0
−
1
1
]
,
B
=
[
1
1
0
1
]
,
c
B
=
[
0
,
−
3
]
,
c
N
=
[
−
2
,
0
]
x_B = [x_3,x_2],x_N = [x_1,x_4],N = \begin{bmatrix} 4 & 0 \\ -1 & 1 \end{bmatrix},B = \begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix},c_B = [0,-3],c_N = [-2,0]
xB=[x3,x2],xN=[x1,x4],N=[4−101],B=[1011],cB=[0,−3],cN=[−2,0]
第二轮迭代:
此时
c
N
−
c
B
B
−
1
N
=
[
−
5
,
3
]
c_N - c_BB^{-1}N = [-5,3]
cN−cBB−1N=[−5,3],选择
x
1
x_1
x1作为入基变量更为高效,且
b
−
N
x
N
=
[
16
−
4
x
1
6
+
x
1
]
>
=
0
b - Nx_N =\begin{bmatrix} 16 - 4x_1 \\ 6 +x_1 \end{bmatrix}>=0
b−NxN=[16−4x16+x1]>=0 故
x
1
=
4
x_1 = 4
x1=4并令
x
3
=
0
x_3 = 0
x3=0,
x
1
x_1
x1入基,
x
3
x_3
x3出基.
经过此轮迭代后,各变量如下
x
B
=
[
x
1
,
x
2
]
,
x
N
=
[
x
3
,
x
4
]
,
N
=
[
1
0
0
1
]
,
B
=
[
4
1
−
1
1
]
,
c
B
=
[
−
2
,
−
3
]
,
c
N
=
[
0
,
0
]
x_B = [x_1,x_2],x_N = [x_3,x_4],N = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix},B = \begin{bmatrix} 4 & 1 \\ -1 & 1 \end{bmatrix},c_B = [-2,-3],c_N = [0,0]
xB=[x1,x2],xN=[x3,x4],N=[1001],B=[4−111],cB=[−2,−3],cN=[0,0]
第三轮迭代:
此时
c
N
−
c
B
B
−
1
N
=
[
1
,
2
]
c_N - c_BB^{-1}N = [1,2]
cN−cBB−1N=[1,2]都大于0,达到收敛条件,此时令
x
N
=
[
0
,
0
]
x_N = [0,0]
xN=[0,0]解得
x
B
=
[
2
,
8
]
x_B = [2,8]
xB=[2,8]最小值为28.
附:图解法绘图代码
import numpy as np
import matplotlib.pyplot as plt
# 定义约束条件
x = np.linspace(0, 10, 400) # 创建x轴的值
eq1 = 16 - 4*x # 约束条件1: 4x1 + x2 <= 16 => x2 <= 16 - 4x1
eq2 = 6 + x # 约束条件2: -x1 + x2 <= 6 => x2 >= -x1 + 6
# 画出约束条件
plt.plot(x, eq1, label=r'$4x_1 + x_2 \leq 16$')
plt.plot(x, eq2, label=r'$-x_1 + x_2 \leq 6$')
plt.xlim((0, 10))
plt.ylim((0, 20))
plt.xlabel(r'$x_1$')
plt.ylabel(r'$x_2$')
# 标记可行域
plt.fill_between(x, np.minimum(eq1, eq2), where=(eq1 >= 0) & (eq2 >= 0), alpha=0.3)
# 添加等值线
x_vals = np.linspace(0, 10, 100)
y_vals = np.linspace(0, 20, 100)
X, Y = np.meshgrid(x_vals, y_vals)
Z = 2*X + 3*Y
max_val = np.max(Z)
# 调整等值线范围
plt.contour(X, Y, Z, levels=[28], colors='red')
plt.contour(X, Y, Z, levels=np.linspace(0, 50, 10), colors='grey', linestyles='dashed')
# 添加标签和图例
plt.title('Feasible Region with Contour Lines')
plt.legend()
plt.grid(True)
plt.show()
2778

被折叠的 条评论
为什么被折叠?



