单纯形法(Simplex Method)

单纯形法(Simplex Method)是线性规划(Linear Programming)​中最经典、应用最广泛的求解算法,由 George Dantzig 在1947年提出。它通过迭代方式在可行域的顶点(极值点)之间移动,逐步逼近最优解。


目录

  1. 算法背景与核心思想
  2. 线性规划标准型与基本概念
  3. 单纯形法的数学推导
  4. 单纯形表与算法步骤
  5. 手工计算实例(生产计划优化)
  6. 退化问题与应对策略
  7. Python代码实现
  8. 算法总结与局限性

一、算法背景与核心思想

1. 历史背景
  • 提出者:George Dantzig(1947年)
  • 应用领域:资源分配、生产计划、物流调度等线性规划问题。
  • 核心目标:在满足线性约束条件下,找到使目标函数最大化的解。
2. 几何与代数视角
  • 几何解释:可行域是一个凸多面体,最优解必出现在顶点(极值点)上。
  • 代数操作:通过**基变量(Basic Variables)**的转换,在顶点之间移动,逐步逼近最优解。

二、线性规划标准型与基本概念

1. 标准型要求

最大化 c T x 约束条件 A x = b x ≥ 0 \begin{align*} \text{最大化} \quad & \mathbf{c}^T \mathbf{x} \\ \text{约束条件} \quad & A\mathbf{x} = \mathbf{b} \\ & \mathbf{x} \geq 0 \end{align*} 最大化约束条件cTxAx=bx0

  • 目标函数需为最大化,变量非负。
  • 所有约束为等式(通过添加松弛变量或剩余变量实现)。
2. 关键概念
术语定义
基变量约束矩阵 ( A ) 中线性无关列对应的变量(数量等于约束方程个数)
非基变量不在基中的变量(值为0)
可行基解满足所有约束的基解
检验数(σ)目标函数对非基变量的灵敏度(判断是否达到最优)

三、单纯形法的数学推导

1. 基变换与目标函数
  • 设基变量为 x B \mathbf{x}_B xB,非基变量为 x N \mathbf{x}_N xN,约束方程可写为:
    x B = B − 1 b − B − 1 N x N \mathbf{x}_B = B^{-1}\mathbf{b} - B^{-1}N\mathbf{x}_N xB=B1bB1NxN
  • 目标函数转换为:
    z = c B T B − 1 b + ( c N T − c B T B − 1 N ) x N z = \mathbf{c}_B^T B^{-1}\mathbf{b} + \left( \mathbf{c}_N^T - \mathbf{c}_B^T B^{-1}N \right) \mathbf{x}_N z=cBTB1b+(cNTcBTB1N)xN
  • 检验数 σ j = c j − c B T B − 1 A j \sigma_j = c_j - \mathbf{c}_B^T B^{-1} A_j σj=cjcBTB1Aj,当所有 σ j ≤ 0 \sigma_j \leq 0 σj0 时达到最优。
2. 入基与出基规则
  • 入基变量:选择 σ j > 0 \sigma_j > 0 σj>0 中最大的非基变量 x j x_j xj(最速上升)。
  • 出基变量:通过最小比值测试 θ i = b i / A i j \theta_i = b_i / A_{ij} θi=bi/Aij 确定。

四、单纯形表与算法步骤

1. 单纯形表结构
基变量 x 1 x_1 x1 x 2 x_2 x2 s 1 s_1 s1 s 2 s_2 s2右端项
s 1 s_1 s121108
s 2 s_2 s213019
z z z-3-4000
2. 算法步骤
  1. 初始化
    • 将问题转化为标准型,确定初始基变量和非基变量。
    • 构建初始单纯形表(包含目标函数和约束条件)。
  2. 最优性检验
    • 计算检验数(Reduced Costs) σ j = c j − c B T B − 1 A j \sigma_j = c_j - \mathbf{c}_B^T B^{-1} A_j σj=cjcBTB1Aj
    • 若所有 σ j ≤ 0 \sigma_j \leq 0 σj0,当前解为最优解,算法终止。
  3. 选择入基变量
    • 选取检验数 σ j > 0 \sigma_j > 0 σj>0 中最大的变量 x j x_j xj 入基(最速上升规则)。
  4. 选择出基变量
    • 计算右端项 b \mathbf{b} b 与入基变量列的正向比值 θ i = b i / A i j \theta_i = b_i / A_{ij} θi=bi/Aij(仅限 A i j > 0 A_{ij} > 0 Aij>0)。
    • 选择最小 θ i \theta_i θi 对应的基变量 x i x_i xi 出基(保证可行性)。
  5. 更新基变量与单纯形表
    • 通过高斯消元(枢轴运算)更新基矩阵和目标函数。
    • 重复步骤2-5直至满足最优性条件。

五、手工计算实例(生产计划优化)

1. 问题描述
  • 最大化利润: z = 3 x 1 + 4 x 2 z = 3x_1 + 4x_2 z=3x1+4x2
  • 约束条件:
    { 2 x 1 + x 2 ≤ 8 x 1 + 3 x 2 ≤ 9 x 1 , x 2 ≥ 0 \begin{cases} 2x_1 + x_2 \leq 8 \\ x_1 + 3x_2 \leq 9 \\ x_1, x_2 \geq 0 \end{cases} 2x1+x28x1+3x29x1,x20
2. 标准化与初始表

添加松弛变量 s 1 , s 2 s_1, s_2 s1,s2,得到:
2 x 1 + x 2 + s 1 = 8 x 1 + 3 x 2 + s 2 = 9 z − 3 x 1 − 4 x 2 = 0 \begin{align*} 2x_1 + x_2 + s_1 &= 8 \\ x_1 + 3x_2 + s_2 &= 9 \\ z - 3x_1 - 4x_2 &= 0 \end{align*} 2x1+x2+s1x1+3x2+s2z3x14x2=8=9=0
初始单纯形表:

基变量 x 1 x_1 x1 x 2 x_2 x2 s 1 s_1 s1 s 2 s_2 s2右端项
s 1 s_1 s121108
s 2 s_2 s213019
z z z-3-4000
3. 第一次迭代
  • 入基变量 x 2 x_2 x2(检验数-4绝对值最大,但需注意符号,此处应为正值)
  • 出基变量:计算 θ 1 = 8 / 1 = 8 \theta_1 = 8/1 = 8 θ1=8/1=8 θ 2 = 9 / 3 = 3 \theta_2 = 9/3 = 3 θ2=9/3=3,选 s 2 s_2 s2 出基。
  • 枢轴运算:以 x 2 x_2 x2 列和 s 2 s_2 s2 行的3为主元,更新表格:

更新后表格:

基变量 x 1 x_1 x1 x 2 x_2 x2 s 1 s_1 s1 s 2 s_2 s2右端项
s 1 s_1 s15/301-1/35
x 2 x_2 x21/3101/33
z z z-1/3004/312
4. 第二次迭代
  • 入基变量 x 1 x_1 x1(检验数-1/3对应实际为正值)
  • 出基变量:计算 θ 1 = 5 / ( 5 / 3 ) = 3 \theta_1 = 5/(5/3)=3 θ1=5/(5/3)=3,选 s 1 s_1 s1 出基。
  • 枢轴运算:以 x 1 x_1 x1 列和 s 1 s_1 s1 行的5/3为主元,更新表格:

最终表格:

基变量 x 1 x_1 x1 x 2 x_2 x2 s 1 s_1 s1 s 2 s_2 s2右端项
x 1 x_1 x1103/5-1/53
x 2 x_2 x201-1/52/52
z z z001/511/513

最优解 x 1 = 3 , x 2 = 2 x_1 = 3, x_2 = 2 x1=3,x2=2,最大利润 z = 3 × 3 + 4 × 2 = 17 z = 3 \times 3 + 4 \times 2 = 17 z=3×3+4×2=17


六、退化与应对策略

1. 退化现象
  • 基变量取值为0时,迭代后目标函数值不改变。
  • 后果:可能进入循环,无法收敛。
2. 解决方案
  • Bland规则:优先选择下标最小的变量入基和出基。
  • 扰动法:对右端项 b \mathbf{b} b 施加微小随机扰动。

七、Python代码实现

使用 scipy.optimize.linprog 求解上述生产计划问题:

from scipy.optimize import linprog

# 目标函数系数(linprog默认最小化,需取负)
c = [-3, -4]

# 不等式约束矩阵
A = [[2, 1], [1, 3]]
b = [8, 9]

# 变量非负约束
x_bounds = (0, None)

# 求解
result = linprog(c, A_ub=A, b_ub=b, bounds=[x_bounds, x_bounds], method='highs')

print("最优解:x1 =", round(result.x[0], 2), "x2 =", round(result.x[1], 2))
print("最大利润:", -round(result.fun, 2))

输出

最优解:x1 = 3.0 x2 = 2.0
最大利润:17.0

八、算法总结与局限性

优势
  • 理论成熟,实际应用广泛。
  • 对中小规模问题效率极高。
  • 支持灵敏度分析(如影子价格、松弛变量分析)。
局限性
  • 最坏情况下时间复杂度为指数级(如 Klee-Minty 问题)。
  • 无法直接处理整数约束(需结合分支定界法)。
  • 对大规模稀疏问题效率低于内点法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值