Pyomo电池优化建模约束报错:非恒定表达式无法转布尔值
电池充放电优化模型Pyomo报错原因分析
问题背景
我正在构建一个电池充放电优化模型以实现最优充放电,建模代码如下:
model = pyo.ConcreteModel() #Set time period model.timesteps = pyo.Set(initialize=pyo.RangeSet(len(pv)),ordered=True) #Parameters model.b_efficiency = pyo.Param(initialize=etta) model.b_cap = pyo.Param(initialize=battery_capacity) model.b_min_soc = pyo.Param(initialize=battery_soc_min) model.b_max_soc = pyo.Param(initialize=battery_soc_max) model.b_charging_rate = pyo.Param(initialize=battery_charge_rate) model.Ppv = pyo.Param(model.timesteps,initialize=dict(enumerate(pv,1)),within=pyo.Any) model.Pdemand = pyo.Param(model.timesteps, initialize=dict(enumerate(demand,1)),within=pyo.Any) #Variables model.Pbat_ch = pyo.Var(model.timesteps, within = pyo.NonNegativeReals) model.Pbat_dis = pyo.Var(model.timesteps, within = pyo.NonNegativeReals) model.Ebat = pyo.Var(model.timesteps, within = pyo.NonNegativeReals) model.Pgrid = pyo.Var(model.timesteps, within = pyo.NonNegativeReals) # Define the constraints of the model def BatEnergyBounds(model, t): return model.b_min_soc * model.b_cap <= model.Ebat[t] <= model.b_max_soc * model.b_cap model.cons1 = pyo.Constraint(model.timesteps, rule = BatEnergyBounds) def BatChargingBounds(model, t): return 0 <= model.Pbat_ch[t] <= model.b_charging_rate model.cons2 = pyo.Constraint(model.timesteps, rule = BatChargingBounds) def BatDischargingBounds(model, t): return 0 <= model.Pbat_dis[t] <= model.b_charging_rate model.cons3 = pyo.Constraint(model.timesteps, rule = BatDischargingBounds) def BatEnergyRule(model, t): if t == model.timesteps.first(): return model.Ebat[t] == model.b_cap/2 else: return model.Ebat[t] == model.Ebat[t-1] + (model.b_efficiency * model.Pbat_ch[t] - model.Pbat_dis[t]/model.b_efficiency) model.cons4 = pyo.Constraint(model.timesteps, rule = BatEnergyRule) def PowerBalanceRule(model, t): return model.Pgrid[t] == model.Ppv[t] - model.Pdemand[t] + model.Pbat_dis[t] - model.Pbat_ch[t] model.cons5 = pyo.Constraint(model.timesteps, rule = PowerBalanceRule) # Define the objective function def ObjRule(model): return sum(model.Pgrid[t] for t in model.timesteps) model.obj = pyo.Objective(rule = ObjRule, sense = pyo.minimize)
运行时出现如下错误:
PyomoException: Cannot convert non-constant Pyomo expression (1.0 <= Ebat[1]) to bool. This error is usually caused by using a Var, unit, or mutable Param in a Boolean context such as an "if" statement, or when checking container membership or equality. For example, >>> m.x = Var() >>> if m.x >= 1: ... pass and >>> m.y = Var() >>> if m.y in [m.x, m.y]: ... pass would both cause this exception.
怀疑是cons4约束中的if语句导致该错误,请问具体原因是什么?
原因分析
问题确实出在BatEnergyRule函数里的if t == model.timesteps.first()判断上。
核心原因是:Pyomo在处理约束规则函数时,t是集合成员对象而非普通整数,直接用==比较t与model.timesteps.first()会被Pyomo转换为一个包含变量依赖的表达式,而非布尔值。而if语句需要明确的布尔值判断,无法解析这种Pyomo表达式,因此触发报错。
修正方案
解决思路是将初始时刻的约束与其他时刻的约束分离,避免在规则函数内部用if处理集合成员的比较:
方法1:拆分约束分别定义
# 初始时刻电池能量约束 def BatEnergyInitRule(model): return model.Ebat[model.timesteps.first()] == model.b_cap/2 model.cons4_init = pyo.Constraint(rule=BatEnergyInitRule) # 其余时刻电池能量变化约束 def BatEnergyDynamicRule(model, t): if t == model.timesteps.first(): return pyo.Constraint.Skip # 跳过已单独定义的初始时刻 return model.Ebat[t] == model.Ebat[t-1] + (model.b_efficiency * model.Pbat_ch[t] - model.Pbat_dis[t]/model.b_efficiency) model.cons4_dynamic = pyo.Constraint(model.timesteps, rule=BatEnergyDynamicRule)
方法2:使用Pyomo条件表达式
如果不想拆分约束,也可以用Pyomo原生的条件表达式处理:
def BatEnergyRule(model, t): return pyo.conditional( t == model.timesteps.first(), model.Ebat[t] == model.b_cap/2, model.Ebat[t] == model.Ebat[t-1] + (model.b_efficiency * model.Pbat_ch[t] - model.Pbat_dis[t]/model.b_efficiency) ) model.cons4 = pyo.Constraint(model.timesteps, rule=BatEnergyRule)
内容的提问来源于stack exchange,提问作者Kosmylo
相关产品推荐
相关产品推荐

