You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化问题中电池初始值异常:Ebat初始值不符定义的求助

电池优化模型初始能量不符合预期问题排查

问题描述

构建了一个基于Pyomo的电池充放电优化模型,目标是最小化外购能源成本。模型中设定初始时刻(t=1)电池能量Ebat为容量的一半(8.3/2=4.15kWh),但求解后初始Ebat值为0.415kWh(刚好是电池最小SOC对应的能量),与预期不符。

模型代码

import pyomo.environ as pyo
import numpy as np  # 补充原函数遗漏的导入

def self_consumption(pv, demand, prices):

    pv.index = np.arange(1, len(pv) + 1)
    demand.index = np.arange(1, len(demand) + 1)
    prices.index = np.arange(1, len(prices) + 1)

    # 定义模型
    model = pyo.ConcreteModel()

    # 定义时间步集合
    model.timesteps = pyo.Set(initialize = pyo.RangeSet(len(pv)), ordered = True)

    # 定义模型参数
    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 = pv.to_dict()['value'], within = pyo.Any)
    model.Pdemand = pyo.Param(model.timesteps, initialize = demand.to_dict()['value'], within = pyo.Any)
    model.day_ahead_prices = pyo.Param(model.timesteps, initialize = prices.to_dict(), within = pyo.Any)

    # 定义决策变量
    model.Pbat_ch = pyo.Var(model.timesteps, within = pyo.NonNegativeReals, bounds = (0, model.b_charging_rate))
    model.Pbat_dis = pyo.Var(model.timesteps, within = pyo.NonNegativeReals, bounds = (0, model.b_charging_rate))
    model.Ebat = pyo.Var(model.timesteps, within = pyo.NonNegativeReals, bounds = (model.b_min_soc * model.b_cap, model.b_max_soc * model.b_cap))
    model.Pgrid = pyo.Var(model.timesteps)
    model.is_charging = pyo.Var(model.timesteps, within = pyo.Binary)
    model.AbsPgrid = pyo.Var(model.timesteps, within=pyo.NonNegativeReals)

    # 定义约束
    def BatEnergyRule(model, t):
        if t == 1:
            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.cons1 = pyo.Constraint(model.timesteps, rule = BatEnergyRule)

    def PowerBalanceRule(model, t):
        return model.Pgrid[t] == model.Pdemand[t] - model.Ppv[t] + model.Pbat_ch[t] - model.Pbat_dis[t]

    model.cons2 = pyo.Constraint(model.timesteps, rule = PowerBalanceRule)

    # 充放电互斥约束
    def charge_discharge_rule(model, t):
        return model.Pbat_ch[t] <= model.is_charging[t] * model.b_charging_rate

    model.charge_constraint = pyo.Constraint(model.timesteps, rule=charge_discharge_rule)

    def discharge_charge_rule(model, t):
        return model.Pbat_dis[t] <= (1 - model.is_charging[t]) * model.b_charging_rate

    model.discharge_constraint = pyo.Constraint(model.timesteps, rule=discharge_charge_rule)

    # 电网功率绝对值约束
    def AbsPgridRule1(model, t):
        return model.AbsPgrid[t] >= model.Pgrid[t]

    model.cons6 = pyo.Constraint(model.timesteps, rule=AbsPgridRule1)

    def AbsPgridRule2(model, t):
        return model.AbsPgrid[t] >= -model.Pgrid[t]

    model.cons7 = pyo.Constraint(model.timesteps, rule=AbsPgridRule2)

    # 目标函数:最小化外购能源成本
    def ObjRule(model):
        return sum(model.day_ahead_prices[t] * model.AbsPgrid[t] for t in model.timesteps)

    model.obj = pyo.Objective(rule=ObjRule, sense=pyo.minimize)
    
    # 选择求解器
    opt = pyo.SolverFactory('glpk')

    # 求解优化问题
    result = opt.solve(model, tee = True)

    solution = {
        "Pbat_ch": {t: model.Pbat_ch[t].value for t in model.timesteps},
        "Pbat_dis": {t: model.Pbat_dis[t].value for t in model.timesteps},
        "Ebat": {t: model.Ebat[t].value for t in model.timesteps},
        "Pgrid": {t: model.Pgrid[t].value for t in model.timesteps},
        }
    
    return solution

运行代码

import numpy as np
import pandas as pd

# 电池参数
BATTERY_CAPACITY = 8.3 # 电池容量(kWh)
BATTERY_CHARGE_RATE = 2.6  # 充放电功率(kW)
BATTERY_SOC_MAX = 1 # 最大SOC比例
BATTERY_SOC_MIN = 0.05 # 最小SOC比例
ETTA = 0.96 # 电池充放电效率

# 生成模拟数据
pv = pd.DataFrame({'value': np.random.uniform(0, 5, 24)})
demand = pd.DataFrame({'value': np.random.uniform(0, 5, 24)})
prices = pd.Series(np.random.uniform(0.1, 0.5, 24), name='prices')

# 运行优化
optimization_results = self_consumption(pv, demand, prices)

原因分析

核心问题是初始约束中使用Param对象的除法表达式model.b_cap/2时,Pyomo未正确将其解析为固定数值(4.15),导致初始约束未生效。求解器在无法满足失效约束的情况下,选择了满足变量边界条件的可行解——即电池最小SOC对应的能量值(0.05*8.3=0.415kWh)。

另外,原模型函数中遗漏了numpy的导入语句,虽然运行代码中已全局导入,但函数内直接使用np存在潜在报错风险,需补充。

解决方案

方案1:直接使用固定数值设置初始约束

修改BatEnergyRule函数中t=1的分支,直接用全局变量的数值定义初始能量,避免Param表达式解析问题:

def BatEnergyRule(model, t):
    if t == 1:
        return model.Ebat[t] == BATTERY_CAPACITY / 2  # 直接使用固定数值4.15
    else:  
        return model.Ebat[t] == model.Ebat[t-1] + (model.b_efficiency * model.Pbat_ch[t] - model.Pbat_dis[t]/model.b_efficiency)

方案2:将初始能量定义为独立Param

在模型的Param定义部分添加初始能量参数,再用于约束:

# 在Param定义区域添加
model.b_initial_energy = pyo.Param(initialize=BATTERY_CAPACITY / 2)

# 修改BatEnergyRule
def BatEnergyRule(model, t):
    if t == 1:
        return model.Ebat[t] == model.b_initial_energy
    else:  
        return model.Ebat[t] == model.Ebat[t-1] + (model.b_efficiency * model.Pbat_ch[t] - model.Pbat_dis[t]/model.b_efficiency)

额外优化:补充函数内的numpy导入

在self_consumption函数开头添加:

import numpy as np

验证方法

修改后重新运行模型,查看optimization_results["Ebat"][1]的值,应为预期的4.15kWh。

内容的提问来源于stack exchange,提问作者Kosmylo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:44:51