炼油厂加拿大重质油加工量优化Python脚本问题排查
问题排查与优化方案
一、约束未生效的核心排查方向
1. 约束未实际加入求解模型
检查你使用的优化库(如PuLP、Gurobi、Scipy.optimize)是否将约束显式添加到模型:
- 错误示例:仅定义了约束表达式,但未调用
prob += constraint(PuLP)或model.addConstr()(Gurobi) - 验证方式:打印模型的约束列表(如PuLP的
prob.constraints),确认所有产能、停机约束都已存在
2. 约束逻辑错误
- 停机约束:若炼油厂当月停机,需设置加工量等于0,而非仅设置下限为0。比如错误写法:
x[i] >= 0,正确写法:x[i] == 0 - 产能约束:确认产能值是当月有效产能(需扣除停机天数折算,如当月运行25天则产能=额定产能*(25/31)),而非直接使用全年额定产能
- 数据类型校验:检查产能、总加工量是否为数值类型(而非字符串),避免因类型不匹配导致约束被求解器忽略
3. 目标函数覆盖约束优先级
若你的目标函数是强制均分(如min sum((x[i] - total/n)**2)),会优先满足均分逻辑,覆盖约束。需调整目标为在约束内满足总加工量,比如:
# 核心约束:总加工量必须达标 prob += lpSum(x[i] for i in refineries) == total_volume
4. 求解器配置问题
- 若使用Scipy的
linprog,检查约束类型(ineq/eq)是否设置正确,停机厂的边界需设为(0,0)而非默认的(0, inf) - 若求解器返回"不可行解",需检查总加工量是否超过所有有效产能之和,此时需添加松弛变量或调整约束
二、优化后的示例代码(基于PuLP)
import pulp # 2021年1月测试数据 refineries = ["炼油厂A", "炼油厂B", "炼油厂C"] # 当月有效产能:停机厂设为0,正常厂为折算后产能 monthly_capacity = {"炼油厂A": 12000, "炼油厂B": 0, "炼油厂C": 18000} total_required = 27000 # 总加工量要求 # 初始化模型 allocation_model = pulp.LpProblem("HeavyOil_Allocation", pulp.LpMinimize) # 定义变量:各厂加工量,下限为0 process_volume = pulp.LpVariable.dicts("Volume", refineries, lowBound=0) # 目标函数:最小化分配波动(可选,核心是满足约束) allocation_model += pulp.lpSum([(process_volume[i] - total_required/len(refineries))**2 for i in refineries]) # 核心约束1:总加工量达标 allocation_model += pulp.lpSum(process_volume[i] for i in refineries) == total_required # 核心约束2:不超过当月有效产能 for refinery in refineries: allocation_model += process_volume[refinery] <= monthly_capacity[refinery] # 求解(关闭日志输出) allocation_model.solve(pulp.PULP_CBC_CMD(msg=False)) # 输出结果 for refinery in refineries: print(f"{refinery} 加拿大重质油加工量: {round(pulp.value(process_volume[refinery]), 2)}")
三、验证步骤
- 检查停机炼油厂的加工量是否为0
- 确认各厂加工量未超过对应当月有效产能
- 校验所有厂加工量之和等于总加工量要求
内容的提问来源于stack exchange,提问作者jare2620
相关产品推荐
相关产品推荐

