优化问题转变为强化学习问题(马尔科夫链决策)能源系统领域目前还处于学术探讨阶段,有相关的文献,也有一些课题组正在研究,但我在工业界的了解(电力系统相关),没有出现过已经落实的方案。

根据本人之前的帖子对以下优化求解问题进行强化学习建模:

  • 光储荷经济性调度,针对单个用户、单个光伏、单个储能设备,短周期内的经济最优目标

变量

  • 充电变量: X = ( x t ) ∈ [ 0 , α ] X = (x_t) \in [0, \alpha] X=(xt)[0,α]

  • 放电变量: Y = ( y t ) ∈ [ − α , 0 ] Y = (y_t) \in [-\alpha, 0] Y=(yt)[α,0]

  • 储能设备能量状态: S = ( s t ) ∈ [ 0 , 1 ] S = (s_t) \in [0, 1] S=(st)[0,1]

以上三个变量为 continuous_var_list 连续变量列表

参数

  • 负荷:load

  • 功率:power

  • 电价:price

  • 充电效率:charge_efficiency

  • 放电效率:discharge_efficiency

  • 储能单次充放电限制:nominal_power

目标函数

最小化经济性最优目标:

minimize  C o s t = ∑ t = 1 T ( l o a d ( t ) − p o w e r ( t ) + x ( t ) + y ( t ) ) × p r i c e ( t ) ÷ c o s t b a s e \text{minimize } Cost = \sum_{t=1}^T (load(t) - power(t) + x(t) + y(t)) \times price(t) \div costbase minimize Cost=t=1T(load(t)power(t)+x(t)+y(t))×price(t)÷costbase

其中 costbase 为不使用储能的情况下的花费:

c o s t b a s e = ∑ t = 1 T ( l o a d ( t ) − p o w e r ( t ) ) × p r i c e ( t ) costbase = \sum_{t=1}^T (load(t) - power(t)) \times price(t) costbase=t=1T(load(t)power(t))×price(t)

约束条件

  • 储能能量状态:

    • 储能初始状态为 0: s 0 = 0 s_0 = 0 s0=0

    • 储能状态更新: s t = s t − 1 + c 1 ⋅ x t + y t c 2 s_t = s_{t-1} + c_1 \cdot x_t + \frac{y_t}{c_2} st=st1+c1xt+c2yt

优化问题求解最优值:


To 马尔科夫链如下:

1. 状态空间(State Space)

状态由以下四个变量组成,表示在当前时间步 ( t ) 下的系统状态:

  • 用户负荷(user_load): 当前时间步用户的电力需求。
  • 电价(elec_price): 当前时间步的电价。
  • 光伏发电(pv_power): 当前时间步分布式光伏发电量。
  • 储能SOC(soc): 当前时间步储能的状态(State of Charge)。
2. 动作空间(Action Space)

动作空间表示储能系统的充电或放电功率(以连续值定义):

  • 充电功率: ( a t > 0 ) ( a_t > 0 ) (at>0),表示充电。
  • 放电功率: ( a t < 0 ) ( a_t < 0 ) (at<0),表示放电。
  • 动作取值范围: [ − P nominal , P nominal ] [-P_{\text{nominal}}, P_{\text{nominal}}] [Pnominal,Pnominal],其中 P nominal P_{\text{nominal}} Pnominal 是储能系统的最大充放电功率。
3. 状态转移(State Transition)

在当前时间步 t t t,根据动作 a t a_t at和当前状态 s t s_t st,下一个时间步的状态 s t + 1 s_{t+1} st+1.

4. 奖励函数(Reward Function)

奖励函数由以下部分组成,目标是最大化收益,最小化未满足需求和系统惩罚:

  • 能源花费奖励:负荷未被满足的成本(取负值表示减少花费带来的奖励)。
    R energy = − max ⁡ ( 0 , user_load t − ( pv_power t + a t ) ) R_{\text{energy}} = - \max(0, \text{user\_load}_t - (\text{pv\_power}_t + a_t)) Renergy=max(0,user_loadt(pv_powert+at))

  • SOC惩罚:如果SOC超出合理范围(如SOC过高或过低),引入惩罚项。

6. 时间步与终止条件(Time Step and Termination Condition)
  • 时间步: 每 10 分钟为一个时间步,全天共 144 步。
  • 终止条件: 模拟到一天结束(144步)或达到最大时间步。
7. 策略优化目标

目标是通过策略 ( \pi(a_t | s_t) ) 最大化未来累积奖励:
π ∗ = arg ⁡ max ⁡ π E [ ∑ t = 0 T γ t R t ] \pi^* = \arg \max_\pi \mathbb{E}\left[\sum_{t=0}^T \gamma^t R_t\right] π=argmaxπE[t=0TγtRt]

  • γ \gamma γ: 折扣因子,用于平衡短期和长期奖励

代码如下:

1. 生成和优化求解项目中相同的测试数据
import random
import pandas as pd

# 设置随机种子
random.seed(1234)

# 创建时间序列数据
sampling_interval = 10  # 每10分钟采样一次
minutes_per_day = 24 * 60  # 一天共有1440分钟
time = minutes_per_day // sampling_interval  # 采样点数量

# 生成随机的用户负荷、用户功率和电价
user_loads = [round(random.uniform(0, 1), 2) for _ in range(time)]
user_powers = [round(random.uniform(0, 1), 2) for _ in range(time)]
elec_price = [round(0.5 + random.uniform(-0.2, 0.2), 2) for _ in range(time)]

# 生成光伏发电数据(模拟分布式能源)
pv_power = [round(random.uniform(0, 1), 2) for _ in range(time)]

# 创建时间序列
time_index = [f"{i // 6:02d}:{(i % 6) * 10:02d}" for i in range(time)]

# 整理为 DataFrame
data = pd.DataFrame({
    "time": time_index,
    "user_load": user_loads,
    "user_power": user_powers,
    "elec_price": elec_price,
    "pv_power": pv_power
})

# 查看数据
print(data.head())

# 保存数据到文件(可选)
data.to_csv("time_series_data.csv", index=False)

2. 生成用于强化学习agent训练学习的数据
time_per_day = minutes_per_day // sampling_interval  # 一天的采样点数量
days = 30  # 训练集的天数
# 生成训练集数据
training_data = []
for day in range(days):
    user_loads = [round(random.uniform(0, 1), 2) for _ in range(time_per_day)]
    user_powers = [round(random.uniform(0, 1), 2) for _ in range(time_per_day)]
    elec_price = [round(0.5 + random.uniform(-0.2, 0.2), 2) for _ in range(time_per_day)]
    pv_power = [round(random.uniform(0, 1), 2) for _ in range(time_per_day)]
    time_index = [f"Day {day + 1} {i // 6:02d}:{(i % 6) * 10:02d}" for i in range(time_per_day)]
    
    day_data = pd.DataFrame({
        "time": time_index,
        "user_load": user_loads,
        "user_power": user_powers,
        "elec_price": elec_price,
        "pv_power": pv_power
    })
    training_data.append(day_data)

# 合并所有天的数据
training_data = pd.concat(training_data, ignore_index=True)

# 保存数据到文件(可选)
training_data.to_csv("training_data_30_days.csv", index=False)

# 显示前几行数据
training_data.head()
3. 模型创建和训练
import pandas as pd
from stable_baselines3 import SAC
from stable_baselines3.common.callbacks import EvalCallback
from stable_baselines3.common.vec_env import DummyVecEnv
import numpy as np
import gym
from gym import spaces
import torch
# 自定义强化学习环境
class EnergyStorageEnv(gym.Env):
    def __init__(self, data, charge_eff=0.91, discharge_eff=0.95, nominal_power=0.8, soc_min=0.0, soc_max=0.8):
        super(EnergyStorageEnv, self).__init__()
        self.data = data.reset_index(drop=True)
        self.timestep = 0
        self.max_timesteps = len(data)
        
        # 参数设置
        self.charge_eff = charge_eff
        self.discharge_eff = discharge_eff
        self.nominal_power = nominal_power
        self.soc_min = soc_min
        self.soc_max = soc_max
        self.soc_penalty_factor = 100
        
        # 状态空间:用户负荷、电价、光伏发电、储能SOC
        self.observation_space = spaces.Box(low=0, high=1, shape=(4,), dtype=np.float32)
        
        # 动作空间:充电或放电功率 [-nominal_power, nominal_power]
        self.action_space = spaces.Box(low=-nominal_power, high=nominal_power, shape=(1,), dtype=np.float32)
    
    def reset(self):
        self.timestep = 0
        self.soc = 0  # 初始SOC
        self.state = self._get_state()
        return self.state
    
    def _get_state(self):
        # 当前状态:用户负荷、电价、光伏发电、储能SOC
        return np.array([
            self.data.iloc[self.timestep]['user_load'],
            self.data.iloc[self.timestep]['elec_price'],
            self.data.iloc[self.timestep]['pv_power'],
            self.soc
        ])
    
    def step(self, action):
        # 解析当前状态
        user_load = self.data.iloc[self.timestep]['user_load']
        elec_price = self.data.iloc[self.timestep]['elec_price']
        pv_power = self.data.iloc[self.timestep]['pv_power']
        
        # 动作限制
        action = np.clip(action[0], -self.nominal_power, self.nominal_power)
        
        # 更新SOC
        if action > 0:  # 充电
            self.soc += action * self.charge_eff
        else:  # 放电
            self.soc += action / self.discharge_eff
        
        # SOC限制及惩罚
        soc_penalty = 0
        if self.soc > self.soc_max:
            soc_penalty = -self.soc_penalty_factor * (self.soc - self.soc_max)
            self.soc = self.soc_max
        elif self.soc < self.soc_min:
            soc_penalty = -self.soc_penalty_factor * (self.soc_min - self.soc)
            self.soc = self.soc_min
        
        # 计算花费
        renewable_supply = pv_power + action
        grid_demand = max(0, user_load - renewable_supply)
        energy_cost = -grid_demand * elec_price  # 花费越低奖励越高
        
        # 奖励函数
        reward = energy_cost + soc_penalty
        
        # 更新状态
        self.timestep += 1
        done = self.timestep >= self.max_timesteps

        if not done:
            self.state = self._get_state()
        else:
            self.state = None
        
        return self.state, reward, done, {}
    
    def render(self, mode='human'):
        pass

# 加载训练和测试数据
train_data = pd.read_csv("training_data_30_days.csv")
test_data = pd.read_csv("time_series_data.csv")

# 创建强化学习环境
train_env = DummyVecEnv([lambda: EnergyStorageEnv(train_data)])
test_env = DummyVecEnv([lambda: EnergyStorageEnv(test_data)])

policy_kwargs = dict(
    net_arch=dict(
        pi=[256, 128, 128],  # 策略网络(Actor)
        qf=[256, 128,128]   # 价值网络(Critic)
    ),
    activation_fn=torch.nn.ReLU
)

# 定义SAC模型
model = SAC("MlpPolicy", train_env,policy_kwargs=policy_kwargs, verbose=1)

eval_callback = EvalCallback(test_env, eval_freq=5000, n_eval_episodes=5, verbose=1)
model.learn(total_timesteps=100000, callback=eval_callback)


# 测试模型性能
obs = test_env.reset()
total_rewards = 0
steps = 0

while True:
    action, _ = model.predict(obs, deterministic=True)
    obs, reward, done, _ = test_env.step(action)
    total_rewards += reward[0]
    steps += 1
    if done:
        break

print(f"Total Reward on Test Data: {total_rewards:.2f}")
print(f"Total Steps: {steps}")

4. 结果可视化
import matplotlib.pyplot as plt

# 重置环境以便测试
obs = test_env.reset()
step_rewards = []  # 存储每一步的奖励
actions = []  # 存储每一步的动作
soc_values = []  # 存储每一步的 SOC 值
unmet_demands = []  # 存储每一步的未满足负荷
timestamps = []  # 存储时间戳
total_rewards = 0
steps = 0

while True:
    action, _ = model.predict(obs, deterministic=True)  # 使用训练好的模型预测动作
    obs, reward, done, info = test_env.step(action)  # 环境执行动作并返回新的状态
    total_rewards += reward[0]
    steps += 1

    # 保存每步的信息
    step_rewards.append(reward[0])
    actions.append(action[0][0])  # 动作是二维,需要取第一个值
    soc_values.append(obs[0][-1])  # 状态的最后一项是 SOC
    unmet_demand = max(0, obs[0][0] - (obs[0][2] + action[0][0]))  # 未满足负荷 = 用户负荷 - (光伏 + 动作)
    unmet_demands.append(unmet_demand)
    timestamps.append(steps)

    if done:
        break

# 绘制结果
plt.figure(figsize=(14, 10))

# 1. 奖励值变化
plt.subplot(3, 1, 1)
plt.plot(timestamps, step_rewards, label="Step Rewards", color="b")
plt.xlabel("Time Step")
plt.ylabel("Reward")
plt.title("Step Rewards Over Time")
plt.legend()

# 2. 充放电决策
plt.subplot(3, 1, 2)
plt.plot(timestamps, actions, label="Charging/Discharging Power", color="g")
plt.axhline(0, color="r", linestyle="--", linewidth=0.7, label="Neutral Power")
plt.xlabel("Time Step")
plt.ylabel("Action (kW)")
plt.title("Charging (+) and Discharging (-) Decisions Over Time")
plt.legend()

# 3. SOC 变化和未满足负荷
plt.subplot(3, 1, 3)
plt.plot(timestamps, soc_values, label="SOC (State of Charge)", color="purple")
plt.plot(timestamps, unmet_demands, label="Unmet Demand", color="orange")
plt.xlabel("Time Step")
plt.ylabel("Value")
plt.title("SOC and Unmet Demand Over Time")
plt.legend()

plt.tight_layout()
plt.show()

print(f"Total Reward on Test Data: {total_rewards:.2f}")
print(f"Total Steps: {steps}")

5. 结果如图:

在这里插入图片描述

这里最终的求解结果Total Reward on Test Data: -5.67。和利用优化求解器求解是有区别的,包括约束并非每次都能很好的转化成奖励&惩罚。显而易见,求解器是从数学约束的角度找到了最优解(收敛点),而强化学习本身只是趋于最优解的一个代理。
Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐