
我在做配电网调度相关项目时最头疼的往往不是设备本身而是每天都要面对的那一摞调度方案。分布式光伏一多天气一变负荷曲线就跟着乱跳人工调度排出来的方案要么保守、要么不收敛反复试算下来一个上午就没了。后来我把粒子群优化算法引入到调度计划编制里用智能算法自动搜索可行且经济的出力组合实测效果比人工经验方案稳定得多。这篇博文就围绕粒子群优化在配电网调度中的实战应用来写从问题建模、算法原理、代码骨架到参数调优和算例验证尽量把关键细节讲透适合刚接触智能算法的电力专业学生也适合想在自己的项目里落地PSO的工程师参考。1. 先看懂问题再谈算法配电网调度到底在优化什么很多人一听到配电网调度第一反应是电网调度中心的大型系统跟自己没什么关系。实际上配电网调度的本质是一道资源分配题在某个调度周期内比如未来24小时系统里有若干台分布式光伏、风电、储能、可调负荷我们要决定每一台设备在每个时段出多少力、充多少电、切多少负荷使得整体运行成本最低、电压质量最好、设备不超载。1.1 传统调度为什么越来越吃力早期的配电网结构简单负荷也相对稳定调度规则可以做成查表或线性规划靠人工经验加Excel就能应付。但最近几年分布式电源大规模接入之后情况完全变了。光伏出力受云层影响可能短时间内剧烈波动电动汽车充电负荷集中在傍晚高峰储能系统又引入了充放电时序耦合的问题——这一秒的充放电决策会影响下一秒的荷电状态。整个问题变成高维度、非线性、带时序约束的复杂优化问题。传统方法处理这类问题通常要先把模型线性化把非线性的潮流方程近似成线性关系。这样做虽然求解快但误差在重负荷场景下会被放大得到的调度方案可能在真实潮流下根本不满足电压约束。这也是一些配电自动化系统算出来的方案不敢直接用的根本原因。1.2 一个可以量化的调度问题模型把问题落到数学上配电网调度的通用模型长这样目标函数以一天24小时、每小时一个时段为例min F Σ(购电成本t 储能运行成本t 弃光弃风惩罚t 网损折算t)其中购电成本是从上级电网买电的费用储能运行成本可以简单折算成充放电循环的损耗弃光弃风惩罚是为了防止算法为了省钱一味切除分布式电源网损折算则是希望调度方案本身更经济。约束条件包括功率平衡每个节点的注入功率等于流出功率加上该节点负荷和线损节点电压上下限配电网一般要求0.93 p.u.到1.07 p.u.支路容量约束每条线路的潮流不能超过额定容量储能SOC约束荷电状态保持在20%到90%之间且受充放电功率限制爬坡约束分布式电源和储能的出力变化率不能超过设备限制。这些约束里功率平衡和电压约束需要靠潮流计算来校验这也是配电网调度问题和一般数学优化问题最大的区别——评价一个解好不好不能只看代数公式必须跑一遍潮流。2. PSO凭什么能在调度问题里落地算法原理与选型理由粒子群优化算法简称PSO是Kennedy和Eberhart在1995年提出的群体智能算法。它的灵感来自鸟群觅食一群鸟在一片区域内找食物每只鸟知道自己当前的位置和发现过的食物最好的位置也知道整个群体发现过的最好的位置然后根据这两条信息调整自己的飞行方向和速度。对应到优化问题上每只鸟就是一个候选解食物最丰富的地方就是最优解。2.1 鸟群觅食的启发PSO的迭代逻辑PSO的数学描述其实非常简单。假设我们要优化D个变量那么一个粒子就是一个D维向量x (x1, x2, ..., xD)。每个粒子还维护一个速度向量v以及它自己的历史最优位置pbest。整个粒子群维护一个全局最优位置gbest。每一次迭代粒子的速度和位置按照下面两个公式更新v_i(t1) w·v_i(t) c1·r1·(pbest_i - x_i(t)) c2·r2·(gbest - x_i(t))x_i(t1) x_i(t) v_i(t1)这里面w是惯性权重c1和c2是学习因子r1和r2是0到1之间的随机数。用大白话解释第一项惯性让粒子保持原来的飞行趋势相当于不想突然转弯第二项自我认知让粒子飞向自己历史上发现的最好位置第三项群体认知让粒子飞向整个群体发现的最好位置。三个力一叠加粒子群就会在搜索空间里逐渐向最优区域靠拢。2.2 和遗传算法、模拟退火相比PSO的优势边界我在项目里做算法选型时主要从三个维度对比了遗传算法GA、模拟退火SA和粒子群优化结论如下表维度PSOGASA实现复杂度低核心公式一套就能写中需处理编码、交叉、变异低但参数敏感需要的调节参数3个w、c1、c2经验成熟较多种群规模、交叉率、变异率、选择策略退火温度曲线较难定对连续变量的适配天然贴合无需编码需要将连续变量离散编码适合但单点搜索效率偏低收敛速度较快群体信息共享明显中等依赖交叉变异算子慢本质是串行搜索全局搜索能力中等偏上配合参数衰减效果好强变异机制保多样性强理论上有概率跳出局部最优配电网调度里的核心决策变量——储能充放电功率、可调负荷削减量、分布式电源出力——基本都是连续变量PSO不需要编码解码直接拿实数向量表示调度方案这个优势在实现阶段非常省事。更重要的是PSO不要求目标函数可导、不要求约束是线性的非线性潮流约束可以直接通过外部潮流计算函数评估这正好命中配电网调度的痛点。当然PSO也有自己的短板离散变量比如联络开关的开合状态处理起来不顺手在超高维问题上容易陷入局部最优。所以我在实际工程里的策略是连续变量用PSO搜索离散变量要么枚举、要么先松弛成连续值再取整做可行性修复。下面会详细讲这个处理过程。3. 实战搭建从目标函数到PSO迭代的完整链路纸上谈兵讲了这么多下面进入正题。我以Python作为实现语言潮流计算用pandapower库搭建一个完整的PSO配电网调度求解器。整体结构分为三层决策变量编码层、目标函数评估层、PSO迭代层。3.1 决策变量的编码设计与初始化配电网调度周期的粒度一般取1小时一天就是24个时段。我在这个算例里设计的决策变量包括三组储能系统每个时段的充放电功率一个长度为24的向量正数表示放电负数表示充电可调负荷每个时段的削减比例同样是长度24的向量范围0到1分布式光伏每个时段的弃光比例长度24的向量范围0到1。这样每个粒子就是一个3×2472维的实数向量。粒子初始化时在各自的边界范围内随机取值即可。这里有一个很容易忽略的细节储能SOC的初始值通常给定为50%但一天的充放电量必须保证结束时SOC回到允许范围内。随机的初始粒子很可能不满足这个条件如果放任不管算法会把大量时间浪费在搜索不可行解上。我的做法是在初始化阶段做一个简单修正先随机生成储能功率序列然后按时间顺序累加计算SOC曲线如果SOC越界或者终点SOC偏离目标值就在整个序列上做一个统一的平移或缩放保证SOC始终在上下限内且终点回到50%左右。这个小操作能显著减少后续迭代的无效搜索。3.2 约束条件处理惩罚函数与时序耦合约束处理是配电网调度建模里的核心环节。我采用的方案是惩罚函数法把每个约束的违反量量化后乘以一个罚系数加进目标函数里。具体来说代码里的约束评估函数大致是这样def evaluate_constraints(net, solution): penalty 0.0 # 潮流计算后检查节点电压 for bus_idx in range(len(net.bus)): v_max max(0, voltage[bus_idx] - 1.07) v_min max(0, 0.93 - voltage[bus_idx]) penalty 1000 * (v_max v_min) # 检查支路负载率 for line_idx in range(len(net.line)): overload max(0, loading[line_idx] - 1.0) penalty 800 * overload # 检查储能SOC时序约束 for t in range(24): soc_low max(0, 0.2 - soc[t]) soc_high max(0, soc[t] - 0.9) penalty 500 * (soc_low soc_high) return penalty罚系数的设置有一个经验法则让正常目标函数值比如购电成本加网损跟罚项在数量级上匹配。如果目标函数值是几万元罚系数定在几百到一千就够如果罚系数定得太大比如一百万那么算法会优先满足约束而完全忽视经济性得到的方案虽然可行但成本很高。我习惯的做法是先跑一次没有约束的松弛解看看目标函数的大致量级再据此设定罚系数。约束类型罚系数量级参考说明电压越限目标函数量级的10~20倍电压越限对安全影响大优先级高支路过载目标函数量级的5~10倍过载可能触发保护跳闸SOC越限目标函数量级的3~5倍SOC越限会缩短电池寿命弃光弃风惩罚直接作为目标函数一部分反向激励不宜过大3.3 PSO核心迭代流程与代码骨架目标函数评估函数准备好之后PSO迭代层反而很薄。核心骨架如下import numpy as np def pso_schedule(eval_func, dim72, pop_size40, max_iter150): w_max, w_min 0.9, 0.4 c1, c2 2.0, 2.0 lb np.array([-0.5]*24 [0]*24 [0]*24) ub np.array([0.5]*24 [1]*24 [1]*24) x np.random.uniform(lb, ub, size(pop_size, dim)) v np.random.uniform(-0.1, 0.1, size(pop_size, dim)) pbest_x x.copy() pbest_score np.array([eval_func(xi) for xi in x]) gbest_idx np.argmin(pbest_score) gbest_x pbest_x[gbest_idx].copy() gbest_score pbest_score[gbest_idx] for t in range(max_iter): w w_max - (w_max - w_min) * t / max_iter r1, r2 np.random.rand(dim), np.random.rand(dim) v w * v c1 * r1 * (pbest_x - x) c2 * r2 * (gbest_x - x) x x v # 边界处理越界则拉回边界 x np.clip(x, lb, ub) # 评估新位置 scores np.array([eval_func(xi) for xi in x]) # 更新个体最优和全局最优 better scores pbest_score pbest_x[better] x[better] pbest_score[better] scores[better] if pbest_score.min() gbest_score: gbest_idx np.argmin(pbest_score) gbest_x pbest_x[gbest_idx].copy() gbest_score pbest_score[gbest_idx] return gbest_x, gbest_score这段代码看起来不长但已经把PSO的完整迭代逻辑都覆盖了。需要特别说明的是第12行的边界处理我直接用了np.clip把越界粒子拉回边界。这个处理方式对配电网调度很重要因为如果让粒子的位置跑到变量范围之外潮流计算很可能直接报错或者产生极其离谱的电压越限反而干扰搜索方向。4. 参数调优与踩坑实录让PSO不早熟、不振荡PSO算法本身只有三四个核心参数但恰恰是这些参数决定了一个调度系统能不能在150代内稳定收敛。这一节把我调参过程中积累的经验和踩过的坑分享出来。4.1 惯性权重衰减从0.9到0.4的讲究惯性权重w决定粒子保持原有速度的程度。w大粒子飞得快全局探索能力强w小粒子飞得慢局部开发能力强。早期版本PSO把w固定为常数效果不太好w偏大时后期在最优解附近来回振荡w偏小时前期快速陷入局部最优。我在配电网调度场景里全部采用线性递减策略w从0.9降到0.4。前30代让w保持在0.8以上相当于粒子群在广阔范围内搜寻各类可能的调度组合最后30代w降到0.5以下让粒子群集中精力在最优区域附近精调储能功率和可调负荷削减比例。这个策略对应到调度问题的直观理解是前期需要探索各种不同的充放电组合避免漏掉某个时段的最优策略后期则要收敛到一条具体的、满足所有约束的出力曲线。实践表明150代迭代下线性递减比固定w0.7的方案平均成本低3%到5%。4.2 越界粒子与约束违反的处理这是个非常实际的坑。刚开始我把粒子速度上限设得很大结果粒子一步就从可行域飞出去十万八千里潮流计算出来的电压全是下限值罚项暴涨粒子群彻底懵了前50代都在往回爬。后来我做了两件事第一对速度做钳制最大速度设为变量搜索范围的20%。比如储能功率范围是-0.5到0.5 MW速度范围就限制在-0.2到0.2 MW/步。第二对位置越界的处理从拉回边界改为拉回边界且速度反向减半。这个改动借鉴了物理碰撞反弹的思路避免粒子贴边后再次同方向冲出去。还有一种情况也值得提SOC的时序耦合约束。储能系统的SOC是一条按时间累加的曲线粒子更新后SOC可能在某些时段越界。单纯加罚函数能引导搜索但效率不高。我后来在评估函数里做了SOC修正当SOC低于下限时把对应时段的充电功率强制提高直到SOC回到最低值之上。这种约束修复和罚函数混合使用的策略比纯罚函数收敛快很多。4.3 陷入局部最优的典型信号与对策最让人头疼的问题是算法早熟gbest在30代以内就不再变化但目标函数值明显高于预期。我总结出两个典型信号一是粒子多样性快速丧失。所有粒子的位置迅速靠拢到gbest附近pbest更新频率急剧下降。这个时候不管迭代多少代都很难跳出当前局部最优。二是惩罚项长期不为零。gbest虽然不再变化但方案里仍然存在电压越限或SOC越限说明算法卡在了一个不可行的局部最优解上。针对第一种情况我在代码里加入了多样性监控随机扰动机制每隔10代计算一次所有粒子到gbest的平均归一化距离如果这个距离低于阈值0.01就对粒子的位置做一次小范围随机重置。针对第二种情况我倾向于增大罚系数或者减少设备变量的搜索范围先把约束满足度拉上来再逐步放松罚系数做精细优化。我最终沉淀下来的一组推荐参数如下参数推荐值调参说明粒子数40~5072维变量下40个粒子性价比最好再多收益不明显迭代次数150~200150代基本收敛200代更稳惯性权重w0.9→0.4线性递减前期探索、后期开发c1、c2均为2.0标准配置工程上够用速度钳制变量范围的20%防止飞越保持搜索稳定罚系数目标函数量级的5~20倍先跑松弛解估算量级5. 算例验证一个简化配电网的调度效果对比理论讲了一堆没有实际数字说服力还是不够。这里用一个基于IEEE 33节点系统简化而来的10节点配电网算例验证PSO调度方案在经济效益和电压质量两个维度的表现。5.1 算例设定与参数表算例网络为辐射状结构基准电压12.66 kV总负荷峰值约4.5 MW。系统内接入2台分布式光伏额定容量分别为1.2 MW和0.8 MW1台储能系统容量1 MWh最大充放电功率0.4 MW1组可调负荷最大可削减量为0.6 MW。调度周期24小时步长1小时。购电电价参考一般工商业分时电价峰时1.1元/kWh平时0.7元/kWh谷时0.4元/kWh。光伏出力曲线按典型晴天出力设定负荷曲线取典型夏季日负荷。我跑了150代PSO粒子数40参数按上一节的推荐值设置。5.2 结果对比PSO与传统等比例分配对照组采用传统调度方式所有分布式电源全额出力储能不充不放可调负荷不做削减。这种方案在负荷高峰时段严重依赖上级电网供电末端节点电压明显偏低。PSO调度组的结果由算法自动生成储能充放电曲线、光伏弃光策略和可调负荷削减计划。最终效果对比如下指标传统方案PSO调度方案改善幅度日运行总成本万元6.876.21降低9.6%末端最低电压p.u.0.9180.973电压质量显著提升网损电量MWh1.421.09降低23.2%可调负荷总削减量MWh01.87对应补偿成本计入总成本从表里可以明显看到PSO方案在降低成本的同时把末端最低电压从0.918 p.u.提升到0.973 p.u.稳稳落在0.93到1.07的允许区间内。这里面的原理其实很简单算法在峰时电价时段让储能放电、削减部分非关键负荷在谷时电价时段给储能充电同时适当弃掉一小部分光伏出力避免了局部电压越限换来的是整体运行成本的下降。5.3 收敛过程分析为了方便读者判断算法是否正常收敛我把每代gbest对应的目标函数值记录了下来几个关键节点是迭代代数gbest适应度值万元状态说明第1代7.86初始随机解约束违反较多第10代6.95约束基本满足成本快速下降第30代6.38已接近最优成本区间第60代6.27进入精细调整阶段第100代6.22基本收敛第150代6.21最终收敛值从代际数据看前30代是目标函数下降最快的区间这对应惯性权重较大的探索阶段30到100代逐步进入开发阶段成本下降幅度变缓100代之后基本平稳说明算法在150代内收敛是可靠的说法。如果读者在自己的项目里发现前10代成本就停止下降了多半是初始粒子质量太差或者罚系数设置失衡需要回到参数设置上做排查。6. 个人体会与后续扩展整套流程跑下来我对粒子群优化在配电网调度中的角色有了比较清晰的认识。它不是一个能解决所有调度问题的万能工具但在连续变量为主、约束非线性强、对求解速度有要求的场景里PSO确实是一个性价比极高的选择。6.1 在真实工程里部署PSO的几点提醒第一先跑通小算例再上大系统。我见过不少同行直接在几百节点的大网上调PSO参数结果跑一次潮流要好几分钟调参周期长到让人崩溃。正确做法是在10到30节点的简化网络上先把参数和行为摸透再迁移到大系统。第二每改一次约束条件都要回归验证。PSO对罚系数非常敏感把电压约束从0.93改到0.95可能整套罚系数都要重新调。建议把验证算例固化成回归测试每次改动自动跑一遍。第三不要迷信最优解。配电网调度模型里包含大量预测数据和近似假设所谓最优解本身就有误差。PSO能给到一条可行的、明显优于人工经验的调度曲线工程价值就已经达到了。第四把调度结果可视化地检查一遍。算法输出的储能出力曲线和可调负荷削减曲线要符合常识比如光伏出力应该在白天、储能充电应该在谷时。如果算法给出的曲线反常识往往不是算法错了而是模型里某个约束或者参数设置有问题。6.2 可以继续深挖的方向我用PSO解决了基础的调度问题之后又在两个方向上做了延伸。一个方向是把预测误差考虑进来用多个光伏出力场景代替单条确定性曲线每个场景给一个权重目标函数变成期望成本最小化PSO只需要在评估函数里多跑几次潮流改动很小但结果对不确定性更鲁棒。另一个方向是把多目标的需求加进来比如同时最小化运行成本和碳排放量这时可以引入多目标粒子群优化MOPSO维护一个Pareto前沿最终让调度人员根据偏好选点。这两个方向在代码架构上都是在现有PSO骨架上做扩展不改变整体流程这也是我当初选择PSO作为基础算法的另一个重要原因。