如何用Python与Scipy求解物料配比线性规划优化问题
用Python和Scipy求解物料混合线性规划问题
问题背景
现有三种含不同化学元素的物料,每千克的元素含量与单价如下:
- 物料A:含0.02g铜(cu)、0.3g镁(mg)、0.005g nc,单价1000美元/千克
- 物料B:含0.033g铜、0.2g镁、0g nc,单价1500美元/千克
- 物料C:含0.05g铜、0.35g镁、0g nc,单价1700美元/千克
需混合这三种物料制造10千克的产品Pr_1,目标是最小化总成本,同时满足以下元素含量约束:
- 10千克Pr_1中铜含量:0.00g ≤ 总铜量 ≤ 1.2g
- 10千克Pr_1中镁含量:1.2g ≤ 总镁量 ≤ 1.9g
- 10千克Pr_1中nc含量:0g(完全不含)
- 所有物料重量非负
线性规划模型
目标函数(最小化总成本)
设x_A、x_B、x_C分别为Pr_1中物料A、B、C的重量(千克),目标函数为:
min 1000*x_A + 1500*x_B + 1700*x_C
约束条件
- 铜含量约束:
0 ≤ 0.02*x_A + 0.033*x_B + 0.05*x_C ≤ 1.2 - 镁含量约束:
1.2 ≤ 0.3*x_A + 0.2*x_B + 0.35*x_C ≤ 1.9 - nc含量约束(等式):
0.005*x_A = 0 → x_A = 0 - 总重量约束(等式):
x_A + x_B + x_C = 10 - 非负约束:
x_A ≥ 0, x_B ≥ 0, x_C ≥ 0
Scipy linprog的正确实现
Scipy的linprog默认处理最小化问题,约束分为三类:不等式约束(A_ub @ x ≤ b_ub)、等式约束(A_eq @ x = b_eq)、变量边界(bounds)。需注意原代码的两处错误:将等式约束误设为不等式,遗漏总重量约束。
完整代码
from scipy.optimize import linprog # 目标函数系数(各物料单价) c = [1000, 1500, 1700] # 不等式约束矩阵A_ub:转换为"≤"形式 A_ub = [ [0.02, 0.033, 0.05], # 铜上限:0.02x_A + 0.033x_B + 0.05x_C ≤ 1.2 [-0.02, -0.033, -0.05], # 铜下限:0 ≤ ... → 等价于 -0.02x_A -0.033x_B -0.05x_C ≤ 0 [0.3, 0.2, 0.35], # 镁上限:0.3x_A + 0.2x_B + 0.35x_C ≤ 1.9 [-0.3, -0.2, -0.35] # 镁下限:1.2 ≤ ... → 等价于 -0.3x_A -0.2x_B -0.35x_C ≤ -1.2 ] # 不等式约束右侧b_ub b_ub = [1.2, 0, 1.9, -1.2] # 等式约束矩阵A_eq A_eq = [ [0.005, 0, 0], # nc含量约束:0.005x_A = 0 [1, 1, 1] # 总重量约束:x_A + x_B + x_C = 10 ] # 等式约束右侧b_eq b_eq = [0, 10] # 变量边界:所有物料重量≥0 x_bounds = (0, None) bounds = [x_bounds, x_bounds, x_bounds] # 求解线性规划(推荐使用highs方法) result = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs') # 输出结果 print("最优物料重量(千克):") print(f"物料A: {result.x[0]:.4f}") print(f"物料B: {result.x[1]:.4f}") print(f"物料C: {result.x[2]:.4f}") print(f"最小总成本(美元):{result.fun:.2f}") print(f"求解状态:{'成功' if result.success else '失败'}") if not result.success: print(f"失败原因:{result.message}")
结果说明
由于nc约束强制x_A=0,最优解仅由物料B和C组成。代码会自动计算满足所有约束的最低成本组合,确保总重量为10千克且元素含量符合要求。
内容的提问来源于stack exchange,提问作者Ali Majed HA
相关产品推荐
相关产品推荐

