使用Python和Pulp求解巧克力工厂日利润最大化问题遇困
巧克力工厂日利润最大化问题
问题背景
工厂可生产单个巧克力(每个有对应利润和日产能上限)和特惠装(每个含3种巧克力及对应利润),需最大化日利润。示例数据如下:
# Limit Variables # n - 巧克力种类数 # p - 特惠装种类数 # max_chocolates - 单日总巧克力生产上限 n = 5 p = 2 max_chocolates = 150 # 单个巧克力:利润和单日产能上限 profit_chocolates = [50, 30, 45, 40, 35] capacity_chocolates = [27, 33, 30, 37, 35] # 特惠装:每个包含的巧克力种类(编号1-5)和对应利润 pack_components = [(1, 3, 5), (2, 3, 4)] profit_packs = [130, 130]
现有代码问题
你编写的代码得到的日利润为6035,与预期的6440存在差距,核心问题出在特惠装的约束逻辑上:
- 未关联特惠装生产与巧克力消耗:现有代码没有考虑生产特惠装会消耗对应巧克力的产能,导致模型无法正确计算生产特惠装的实际成本。
- 错误的利润约束:手动添加的“特惠装利润不低于组件单卖利润之和”约束完全错误,且对于第二个特惠装(组件单卖利润和为115,低于装的利润130),这个约束直接限制了该特惠装的生产,错失更高利润。
- 重复约束:变量定义时已设置
lowBound=0,无需再添加非负约束;同时重复添加了单个巧克力产能约束,无意义。
修正后的代码
from pulp import LpProblem, LpMaximize, LpVariable, lpSum # 问题初始化 prob = LpProblem("Maximize_chocolates_and_packs_profit", LpMaximize) # 决策变量: # x_i:第i种巧克力单卖的数量(i从0到4对应编号1到5) chocolate_vars = [LpVariable(f"x{i}", lowBound=0, cat="Integer") for i in range(n)] # p_j:第j种特惠装的生产数量 packs_vars = [LpVariable(f"p{j}", lowBound=0, cat="Integer") for j in range(p)] # 目标函数:总利润 = 单卖巧克力利润 + 特惠装利润 prob += lpSum(profit_chocolates[i] * chocolate_vars[i] for i in range(n)) + \ lpSum(profit_packs[j] * packs_vars[j] for j in range(p)) # 约束1:单日总巧克力生产上限(单卖的 + 特惠装包含的所有巧克力) prob += lpSum(chocolate_vars[i] for i in range(n)) + lpSum(3 * packs_vars[j] for j in range(p)) <= max_chocolates # 约束2:每种巧克力的总消耗量(单卖 + 用于特惠装的)不超过其单日产能 for i in range(n): # 计算用于所有特惠装的该巧克力数量:sum(p_j 当该巧克力在第j个装的组件中) used_in_packs = lpSum(packs_vars[j] for j in range(p) if (i+1) in pack_components[j]) prob += chocolate_vars[i] + used_in_packs <= capacity_chocolates[i] # 求解模型 prob.solve() # 输出结果 print("单卖巧克力数量:") for i in range(len(chocolate_vars)): print(f"巧克力{i+1}: {int(chocolate_vars[i].varValue)}") print("\n特惠装生产数量:") for i in range(len(packs_vars)): print(f"特惠装{i+1}: {int(packs_vars[i].varValue)}") print(f"\n最大日利润:{int(prob.objective.value())}")
修正说明
- 核心约束修正:新增了“每种巧克力总消耗量(单卖+特惠装用)不超过产能”的约束,正确关联了特惠装生产与巧克力消耗。
- 删除错误约束:移除了错误的利润约束,让模型自动根据利润高低选择是否生产特惠装(比如第二个特惠装利润130高于组件单卖总和115,模型会优先生产)。
- 简化冗余代码:删除重复的非负约束和重复的产能约束,让代码更简洁。
运行修正后的代码,将得到预期的最大日利润6440。
内容的提问来源于stack exchange,提问作者Jay Craig
相关产品推荐
相关产品推荐

