PuLP构建生产采购成本最小化模型约束出错,如何修复?
PuLP生产采购决策模型错误排查与修复
核心错误汇总
- 物料消耗约束逻辑完全错误
原代码将所有物料的总消耗和所有物料的总可用库存做对比,相当于允许不同物料之间的库存通用,自然会出现不采购物料也能超额生产的问题。正确逻辑应该是每种物料单独约束:该物料的总生产消耗 ≤ 原有库存 + 该物料采购量
- 物料消耗约束逻辑完全错误
- 所有约束都存在循环变量重复定义的问题
原代码在多个约束的内层循环重复使用了外层的i变量,导致求和逻辑完全不符合预期,相当于把所有产品的消耗量重复累加了4次(产品数量)
- 所有约束都存在循环变量重复定义的问题
- 产能约束逻辑错误
原代码对每个产品单独做了不超过300的限制,实际是总产能300,应该约束所有产品的总产量 ≤ 300
- 产能约束逻辑错误
- 利润约束、库存约束逻辑错误
原代码循环每个产品单独校验利润和库存限制,实际这两个都是全局约束,不需要按产品循环
- 利润约束、库存约束逻辑错误
- 目标函数的剩余库存持有成本计算错误
原代码先算所有物料总剩余再乘所有物料成本,相当于重复计算了持有成本,正确逻辑是单种物料剩余乘对应成本后求和
- 目标函数的剩余库存持有成本计算错误
修复后完整代码
from pulp import * product = ['S1', 'S2', 'S3', 'S4'] material = ['A', 'B', 'C', 'D', 'E', 'F', 'I', 'G', 'H', 'J', 'K', 'L', 'M'] margin = {'S1': 25.68, 'S2': 25.68, 'S3': 25.68, 'S4': 25.68} capacity = 300 inv_bf = 42753.63 product_cost = {'S1': 4.28, 'S2': 4.28, 'S3': 4.28, 'S4': 4.28} usage = {'S1': {'A': 12.24, 'D': 12.24, 'E': 0.014, 'F': 0.095, 'G': 12.24, 'H': 0.589, 'J': 24.24, 'K': 0.005, 'L': 0.0105}, 'S2': {'A': 12.24, 'D': 12.24, 'E': 0.014, 'F': 0.095, 'G': 12.24, 'H': 0.589, 'J': 24.24, 'K': 0.005, 'L': 0.0105}, 'S3': {'H': 0.26, 'K': 0.014, 'B': 12.24, 'C': 12.24, 'I': 0.624, 'G': 12.18, 'J': 24.24, 'M': 0.005}, 'S4': {'H': 0.26, 'K': 0.014, 'B': 12.24, 'C': 12.24, 'I': 0.624, 'G': 12.18, 'J': 24.24, 'M': 0.005}} inv = {'A': 7645.8, 'B': 2470, 'C': 4526, 'D': 6678, 'J': 4180.92, 'G': 6879, 'E': 159.5, 'F': 717.4, 'I': 764.1, 'H': 1302.69, 'K': 248.79, 'L': 235, 'M': 179.4} cost = {'A': 0.03, 'B': 0.03, 'C': 0.056, 'D': 0.151, 'J': 0.024, 'G': 0.88, 'E': 5.156, 'F': 13.04, 'I': 11.09, 'H': 6.833, 'K': 11.261, 'L': 10.118, 'M': 11.914} # 定义变量 produce = LpVariable.dicts("produce", product, lowBound=0, cat='Integer') order = LpVariable.dicts("order", material, lowBound=0, cat='Integer') # 定义并初始化模型 model = LpProblem("total_cost", LpMinimize) # 目标函数 Total_ProCost = lpSum(product_cost[i]*produce[i] for i in product) Total_MatCost = lpSum(order[m]*cost[m] for m in material) # 修正持有成本计算:单种物料剩余*对应成本求和 Hold_Cost = lpSum((inv[m] + order[m] - lpSum(produce[i] * usage[i][m] for i in product if m in usage[i])) * cost[m] for m in material) objective = Total_ProCost + Total_MatCost + Hold_Cost model.setObjective(objective) # 修正物料用量约束:每个物料单独校验 for m in material: total_used = lpSum(produce[i] * usage[i][m] for i in product if m in usage[i]) model += total_used <= inv[m] + order[m], f"material_{m}_constraint" # 修正产能约束:总产能限制 model += lpSum(produce[i] for i in product) <= capacity, "capacity_constraint" # 修正利润约束:全局总毛利≥总成本 model += lpSum(produce[i]*margin[i] for i in product) >= Total_ProCost + Total_MatCost, "profit_constraint" # 修正库存约束:全局剩余库存总价值不超过上限 model += lpSum((inv[m] + order[m] - lpSum(produce[i] * usage[i][m] for i in product if m in usage[i])) * cost[m] for m in material) <= inv_bf, "inventory_constraint" model.solve() # 输出 print("求解状态:", LpStatus[model.status]) for v in model.variables(): print(v.name,'=',v.varValue) print("Total cost = ", value(model.objective))
修复后效果
修复后模型会严格按照每种物料的库存限制计算产量,若现有库存无法支撑产量会自动计算需要采购的物料数量,不会再出现无物料采购却超额生产的逻辑问题。
内容的提问来源于stack exchange,提问作者Kudadas
相关产品推荐
相关产品推荐

