Pyomo多地点小时级优化为何所有输出变量均为零
问题根因
- 结果导出代码存在低级错误:导出风电装机
Pwind、电解槽功率Ph2时,变量全部错误赋值为instance.Psolar,没有读取对应变量的求解结果,是导出值全0的直接原因。 - 模型打印逻辑错误:
model.pprint()调用的是未实例化的抽象模型模板,不是求解完成的实例化对象instance,因此会显示组件Size=0、未构建状态,和模型本身构建是否正确无关。 - 目标函数存在数值奇点:分式结构的目标在全0点分子分母均为0,属于数值未定义区域,初始点靠近0时梯度爆炸,求解器容易坍缩到全0的退化解;且你没有给分母加极小值平滑,求解过程中一旦碰到年制氢量接近0的迭代步,就会触发数值错误导致收敛方向偏移。
- 模型规模偏高属于正常现象:全年共8760小时,单地点配置4个逐小时索引的辅助变量时,仅辅助变量就有8760*4=35040个,加3个地点级核心决策变量刚好匹配你统计的35043个变量规模,5地点变量数乘5为175215也和统计值一致,不是建模逻辑错误导致的规模异常。
修复方案
1. 修正基础代码错误
- 修正结果导出段的变量引用:
Pwind=instance.Pwind、Ph2=instance.Ph2,不要全部引用光伏装机变量。 - 将模型打印语句改为
instance.pprint(),查看实例化、求解后的真实模型结构。 - 给目标函数分母加极小平滑项避免除零:将分母位置的年制氢项从
(sum(model.Y_h2[l,h] for h in model.H))*Sy改为(sum(model.Y_h2[l,h] for h in model.H))*Sy + 1e-6,1e-6的偏移量不会对最优解结果产生可感知的影响,但能彻底规避迭代过程中的除零奇点。
2. 压缩模型规模(可将求解速度提升4倍以上)
你当前定义的4个逐小时辅助变量全部可以被核心决策变量线性表出,无需全部定义为决策变量,可直接消元砍掉冗余变量和约束:
- 直接删除
E_res、E_curt、Y_h2三个逐小时辅助变量,仅保留E_h2作为唯一逐小时变量即可。 - 逐小时约束仅需保留2个不等式:
由于优化目标是最小化单位制氢成本,最优解下def eh2_upper1_rule(model, l, h): return model.E_h2[l,h] <= model.Psolar[l]*model.CFsolar[l,h] + model.Pwind[l]*model.CFwind[l,h] def eh2_upper2_rule(model, l, h): return model.E_h2[l,h] <= model.Ph2[l]E_h2会自然取到两个上限的最小值,不需要额外加电量平衡、发电量、制氢量的等式约束,也不需要定义弃电变量——弃电本身无成本,不需要显式建模。 - 目标函数可直接简化为:
改完后单地点变量数会降到8763个,约束数降到17521个,规模直接砍半,求解速度提升明显。def objective_function(model): return sum( (K_solar*model.Psolar[l] + K_wind*model.Pwind[l] + K_h2*model.Ph2[l]) / (effi*Sy*sum(model.E_h2[l,h] for h in model.H) + 1e-6) for l in model.L )
3. 求解配置优化
- 调整变量初始值:不要统一用5000作为初始化值,可先计算各地点光伏、风电的年平均容量因子,按土地约束上限的30%-50%给核心变量赋初值,让初始点远离全0奇点。
- 拆分独立子问题:由于各选址点优化完全独立,不需要把所有地点放在同一个模型里求解,可以循环单个地点的模型逐点求解,求解时间和内存占用会随地点数线性下降,不会出现多地点超时的问题。
- 求解器参数适配:用IPOPT求解时可开启自适应障碍参数
mu_strategy=adaptive,对分式非线性目标的收敛性提升明显;用Octeract时可适当提高数值精度阈值,避免小数值触发的收敛判定错误。
内容的提问来源于stack exchange,提问作者Levidas
相关产品推荐
相关产品推荐

