Pyomo命令行求解报错:'Series'对象无'is_expression_type'属性
问题场景
开发大规模储能优化模型时,直接用python3 my_model.py运行脚本一切正常,但注释掉opt.solve语句改用pyomo solve my_model.py --solver='gurobi'求解时,抛出以下错误:
ERROR: Rule failed when generating expression for constraint storing_constraint with index (0, 'phs'): AttributeError: 'Series' object has no attribute 'is_expression_type'
ERROR: Constructing component 'storing_constraint' from data=None failed:
AttributeError: 'Series' object has no attribute 'is_expression_type'
排查发现两种运行方式下charge变量结构不一致:
- 直接运行:正常的MultiIndex Series,结构符合预期
- Pyomo Solve运行:变为包含多个小Series的object类型Series,顺序混乱
原因分析
Pyomo Solve命令在加载模型脚本时,会对全局变量进行序列化与反序列化操作。Pandas的MultiIndex Series在这个过程中无法被正确还原,导致其结构被破坏,变成了存储子Series的object类型序列,最终在约束规则中引用时触发类型错误。
解决方案
将存储小时级充电数据的Pandas Series替换为Pyomo原生的Param组件。Pyomo会自行管理Param的数据,避免序列化带来的结构异常问题。
修改后的完整代码
# -*- coding: utf-8 -*- import pyomo.environ as pyo from pyomo.opt import SolverFactory import pandas as pd model = pyo.ConcreteModel() charge_daily = pd.read_csv("input.csv") # 小时范围 model.h = pyo.RangeSet(0,23) # 储能技术类型 model.str = pyo.Set(initialize=["phs"]) # 先处理输入数据转为Series(业务需求) days=charge_daily.iloc[:,0].values value=charge_daily.iloc[:,1].values charge_daily = pd.Series(value, index=[days]) # 转换为小时级数据,直接构建Pyomo Param charge_data = {} for str_tec in model.str: for h in model.h: day = int(h/24) charge_data[(str_tec, h)] = charge_daily[day]/24 # 定义Pyomo Param存储充电数据 model.charge = pyo.Param(model.str, model.h, initialize=charge_data) # 每小时存储量变量 model.stored = pyo.Var(((storage, h) for storage in model.str for h in model.h), within=pyo.NonNegativeReals, initialize=0) # 每小时放电量变量 model.gene = pyo.Var(((tec,h) for tec in model.str for h in model.h), within=pyo.NonNegativeReals, initialize=0) def objective_rule(model): """目标函数规则""" return (sum(sum(model.gene[tec, h] for h in model.h) for tec in model.str)) model.objective = pyo.Objective(rule=objective_rule) def storing_constraint_rule(model, h, tec): """存储约束规则""" hPOne = h+1 if h < model.h.last() else 0 return model.stored[tec, hPOne] == model.stored[tec, h] + model.charge[tec, h] - model.gene[tec,h] model.storing_constraint = pyo.Constraint(model.h, model.str, rule=storing_constraint_rule) # 注释掉直接求解的代码,改用pyomo solve命令 # opt = SolverFactory('gurobi') # results = opt.solve(model)
关键修改点
- 把原来构建
chargeSeries的逻辑改为构建字典charge_data,键为(储能类型, 小时)的元组 - 用
pyo.Param定义model.charge,传入集合model.str和model.h以及初始化字典 - 在约束规则
storing_constraint_rule中,将charge[tec, h]替换为model.charge[tec, h]
这样修改后,无论是直接运行脚本还是用pyomo solve命令求解,Pyomo都能正确识别充电数据的类型,避免结构异常导致的报错。
内容的提问来源于stack exchange,提问作者Qnbt

