1. 线性规划生产计划建模与求解
问题设定与数据
某车间生产三种产品 A、B、C,共用两类关键资源:设备工时与熟练工工时。单件消耗、单件利润与资源可用量如下表(示例数据,单位统一为“小时/件”与“元/件”)。
| 产品 | 设备工时 | 人工工时 | 单件利润 | 市场需求上限 |
|---|---|---|---|---|
| A | 2 | 1 | 40 | 60 |
| B | 1 | 3 | 50 | 50 |
| C | 3 | 2 | 60 | 40 |
设备可用工时 240 h,人工可用工时 300 h。决策变量 xA、xB、xC 为各产品产量(件),目标为最大化总利润。
线性规划模型
标准形式如下,约束均为“≤”型,右端项非负,可直接进入单纯形法或调用求解器。
max Z = 40·xA + 50·xB + 60·xC
s.t. 2·xA + 1·xB + 3·xC ≤ 240 (设备工时)
1·xA + 3·xB + 2·xC ≤ 300 (人工工时)
1·xA ≤ 60 (A 需求上限)
1·xB ≤ 50 (B 需求上限)
1·xC ≤ 40 (C 需求上限)
xA, xB, xC ≥ 0
注意需求上限约束的系数矩阵中每行只有一个 1,这类约束在单纯形表中对应松弛变量即为“天然基变量”,是后续影子价格分析的重要观察点。
求解实现(Python + SciPy)
使用 scipy.optimize.linprog 求解,采用 HiGHS 求解器,并通过 res.ineqlin.marginals 直接读取各约束的对偶值(影子价格)。
import numpy as np
from scipy.optimize import linprog
c = np.array([-40.0, -50.0, -60.0]) # linprog 求最小化,取负号
A_ub = np.array([
[2.0, 1.0, 3.0], # 设备工时
[1.0, 3.0, 2.0], # 人工工时
[1.0, 0.0, 0.0], # A 上限
[0.0, 1.0, 0.0], # B 上限
[0.0, 0.0, 1.0], # C 上限
])
b_ub = np.array([240.0, 300.0, 60.0, 50.0, 40.0])
bounds = [(0, None)] * 3
res = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method="highs")
print("状态:", res.message)
print("最优产量 xA, xB, xC =", np.round(res.x, 4))
print("最大利润 Z =", round(-res.fun, 4))
print("各约束影子价格 =", np.round(res.ineqlin.marginals, 4))
print("各约束松弛量 =", np.round(res.ineqlin.residual, 4))
运行后应得到一组最优解与对偶值。示例数据下,设备工时与人工工时约束均为紧约束(松弛量为 0),而三条需求上限约束存在正松弛量,其影子价格为 0——这正是“非紧约束对偶值为零”的互补松弛性体现。
结果判读与影子价格分析
影子价格表示对应资源每增加 1 单位时目标函数(总利润)的边际增量,仅在当前基不变的邻域内有效。判读要点:
- 紧约束(松弛量 = 0)的影子价格通常为正,说明该资源是瓶颈,扩产应优先投入此类资源。
- 非紧约束(松弛量 > 0)的影子价格为 0,增加该资源不改变最优利润。
- 影子价格只在右端项变化不引起基变换的范围内成立,超出该范围需重新求解。
下面的图示把“资源投入 → 约束 → 最优解 → 影子价格判读”这条关系链与两类资源的瓶颈状态并列呈现,便于对照理解。
验证与灵敏度检查
求解结果需做两项基本验证:其一,把最优解代回全部约束,确认无违反且紧约束松弛量为 0;其二,对瓶颈资源右端项做小步扰动(如设备工时 +1),重新求解观察利润增量是否与影子价格一致。若扰动后基发生改变,利润增量会偏离影子价格,此时应记录基变换的临界点,作为扩产决策的边界条件。
影子价格是“边际价值”而非“平均价值”,不能直接用总利润除以总工时来估算资源价值;两者在非紧约束存在时差异明显。