我们来看一个简单的数学规划模型:
max
Z
=
70
x
1
+
30
x
2
\max Z=70 x_{1}+30 x_{2}
maxZ=70x1+30x2
s
.
t
.
{
3
x
1
+
9
x
2
⩽
540
5
x
1
+
5
x
2
⩽
450
9
x
1
+
3
x
2
⩽
720
x
1
,
x
2
⩾
0
s.t. \left\{\begin{array}{l}3 x_{1}+9 x_{2} \leqslant 540 \\ 5 x_{1}+5 x_{2} \leqslant 450 \\ 9 x_{1}+3 x_{2} \leqslant 720 \\ x_{1}, x_{2} \geqslant 0\end{array}\right.
s.t.⎩⎪⎪⎨⎪⎪⎧3x1+9x2⩽5405x1+5x2⩽4509x1+3x2⩽720x1,x2⩾0
首先,我们需要把这个不规范的数学规划模型转换成标准型,标准型的要求有以下几点:
- 目标为求函数的最大值问题,即Maxmize问题
- 约束条件为等式约束
- 约束条件的右边常数项大于或者等于0
- 所有变量大于或者等于零
我们可以通过引入松弛变量的方式来进行非标准型的标准化转换,对于上式,我们可以通过变换得到它的标准型如下:
max Z = 70 x 1 + 30 x 2 \max Z=70 x_{1}+30 x_{2} maxZ=70x1+30x2 s . t . { 3 x 1 + 9 x 2 + x 3 = 540 5 x 1 + 5 x 2 + x 4 = 450 9 x 1 + 3 x 2 + x 5 = 720 x 1 , x 2 , x 3 , x 4 , x 5 ⩾ 0 s.t. \left\{\begin{array}{l}3 x_{1}+9 x_{2} +x_{3} = 540 \\ 5 x_{1}+5 x_{2} + x_{4} = 450 \\ 9 x_{1}+3 x_{2} + x_{5} = 720 \\ x_{1}, x_{2}, x_{3}, x_{4}, x_{5} \geqslant 0\end{array}\right. s.t.⎩⎪⎪⎨⎪⎪⎧3x1+9x2+x3=5405x1+5x2+x4=4509x1+3x2+x5=720x1,x2,x3,x4,x5⩾0
我们可以使用单纯性法来进行求解,首先我们需要建立单纯形表matrx,然后根据以下的步骤进行迭代,指导目标函数一行的系数没有正数为止:
- Step1:判断出基和入基:根据系数选入度、根据theta选出度,选取入度一列和出度一行"
- Step2:修改matrix,初等行变换,先归一化出基一行,然后归零其他行的入度一列;
- Step3:更新index,把入度变量替换掉index中的松弛变量
我可以使用以下代码来实现:
import pandas as pd
import numpy as np
def lp_solver(matrix: pd.DataFrame):
c = matrix.iloc[0,1:]
while c.max() > 0:
print("Step1:判断出基和入基:根据系数选入度、根据theta选出度,选取入度一列和出度一行")
#判断出基和入基:根据系数选入度、根据theta选出度,选取入度一列和出度一行
in_x = c.idxmax()
in_x_v = c[in_x]
b = matrix.iloc[1:,0]
in_x_a = matrix.iloc[1:][in_x]
out_x = (b/in_x_a).idxmin()
print(f"in_x={in_x},out_x={out_x}")
#修改matrix,初等行变换,先归一化出基一行,然后归零其他行的入度一列
print("Step2:修改matrix,初等行变换,先归一化出基一行,然后归零其他行的入度一列")
matrix.loc[out_x, :] = matrix.loc[out_x,:]/matrix.loc[out_x,in_x]
for idx in matrix.index:
if idx != out_x:
matrix.loc[idx,:] = matrix.loc[idx,:] - matrix.loc[out_x,:] * matrix.loc[idx,in_x]
#更新index,把入度变量替换掉index中的松弛变量
print("Step3:更新index,把入度变量替换掉index中的松弛变量")
index = matrix.index.tolist()
print(f"index before update ={index}")
#index可以认为是索引
i = index.index(out_x)
print(f"the in dex of out_x = {i}")
index[i] = in_x
print(f"index after update ={index}")
matrix.index = index
c = matrix.iloc[0,1:]
print(matrix)
if __name__ == '__main__':
matrix = pd.DataFrame(
np.array([
[0,70,30,0,0,0],
[540,3,9,1,0,0],
[450,5,5,0,1,0],
[720,9,3,0,0,1]
]),
index = ['obj','x3','x4','x5'],
columns = ['b','x1','x2','x3','x4','x5']
)
print(matrix)
lp_solver(matrix)
我们可以看到这个程序求解的全过程,最终,在x1=75、x2=15处,目标函数取得最大值5700.