资讯动态

MOPSO在微电网多目标日前调度中的应用实践

发布时间:2026/10/16 15:14:36 来源:尧图企业网站定制
微电网调度这件事凡是碰过电力系统优化的人都知道它从来不是“发电成本最低”一句话能交代的。光伏和风电出力波动、柴油机燃料消耗和排放、储能电池寿命损耗、与主网功率交换的分时电价每个环节都有自己的目标函数而且这些函数之间天然互相打架。这篇文章想聊的就是用粒子群算法去处理多目标微电网调度问题把经济性、环保性、可靠性放进同一个优化框架里找折中解。我前阵子用多目标粒子群算法MOPSO做过一个微电网日前调度项目从建模、编码、算法调试到最终画出Pareto前沿一路踩了不少坑。这篇文章把完整思路、代码骨架和问题排查经验都梳理出来给准备碰这块的同行做参考。1. 微电网调度为什么天然是个多目标问题很多人一开始会想调度不就是“该开几台机组、储能什么时候充电放电”吗把它变成一个单目标优化不就行了真做起来就会发现单目标模型只能回答“怎么最省钱”但一个真正能落地的调度方案还要考虑排了多少碳、对电网的冲击大不大、极端天气下能不能保证供电。多目标不是锦上添花的学术要求而是微电网运行本身就有多重身份它是用户侧的供电单元也是配电网里的可调节资源同时还得承担一定的环保指标。1.1 三个目标之间的冲突关系微电网里的主要优化目标至少有三个。第一个是经济性也就是系统总运行成本最低。成本包括柴油发电机的燃料费和运维费、从主网购电的电费、储能充放电循环造成的折算损耗以及弃风弃光带来的机会成本。光伏和风电的边际发电成本接近零所以经济性最优的方案往往会尽可能买便宜电、用便宜时段充电而不是把所有新能源出力都全额消纳。第二个是环保性目标函数可以写成系统总碳排放最低。柴油机是直接排放大户从主网购电也要按电网平均排放因子折算碳排放。环保最优的方案会优先压柴油机出力尽量用新能源但这就可能导致某些时段需要储能大功率放电或者让联络线功率剧烈波动经济性反而变差。第三个是可靠性或稳定性工程上常用的替代指标是功率波动最小、电压偏差最小、负荷缺电率最低等。这个目标要求各时段出力尽量平滑不要一会儿从主网购电、一会儿猛送出去。但这又和“电价低谷多买电、电价高峰多放电”的经济性策略直接冲突。这三个目标互相掣肘成本最低的方案往往碳排放高或者收购波动大碳排放最低的方案通常要依赖储能成本上不划算稳定性最好的方案又可能牺牲经济性。所以不能说哪个目标绝对优先实际调度需要给出一组“谁也不能完全压制谁”的折中解再由运行人员根据场景挑一个最合适的。1.2 每类目标背后都躲着物理约束除了目标函数之间的冲突微电网调度还必须满足一系列物理约束这些约束是算法最后能不能落地的关键。功率平衡是最基本的要求任意时刻所有电源出力加储能放电功率再加联络线购电功率必须等于负荷功率。柴油机、光伏、风电、储能、联络线这几个决策变量之间不是独立的只要其中一个变了其他变量必须跟着调整否则等式约束就打破了。设备功率约束也很好理解光伏和风电出力不能超过预测值柴油机有最小稳定出力和最大额定功率储能充放电功率有上限与主网交换的联络线功率也有安全限额。储能电池还得多关心一个状态量——SOC荷电状态。它存在一个递推关系下一时刻的SOC等于当前SOC减去充放电电量除以电池容量还要考虑充放电效率。SOC不能超过上下限否则电池寿命会受到严重影响。这个约束在时间序列上具有记忆性不是每个时段独立的。柴油机还有爬坡约束相邻时段出力变化不能超过一定速率。如果某天早上负荷突然上升柴油机没法瞬间从低出力跳到满发必须考虑它的爬坡特性。这些约束叠加在一起调度问题的可行域变得相当复杂。好在粒子群算法对约束处理比较灵活后面会详细说怎么做。1.3 典型调度周期与数据准备做日前调度最基本的周期是未来24小时时间粒度常用1小时目前有不少项目细化到了15分钟。时间粒度越细决策变量越多计算量也越大。1小时粒度的好处是数据和分时电价天然对齐迭代速度也快适合先跑通算法框架。数据准备上需要四类东西。一是负荷预测曲线一般来自历史负荷数据的回归或深度学习预测二是新能源出力预测光伏看辐照度、风电看风速工程上通常直接给预测功率序列三是分时电价或实时电价数据决定了储能“低充高放”的收益空间四是设备参数柴油机的燃料成本系数、排放因子、爬坡速率储能电池的容量、SOC上下限、充放电效率联络线的最大交换功率等。这块我建议提前把数据单位统一。很多项目跑出来的结果怪怪的最后发现是功率单位混用了一会儿用kW、一会儿用MW成本函数里价格单位又用了元/MWh整个优化结果差了好几个数量级。多目标优化里目标函数归一化本来就脆弱单位不一致会让Pareto前沿的分布完全乱掉。2. 粒子群从单目标走到多目标的关键改造粒子群算法PSO最初是为了解决单目标连续优化问题而提出的拿来直接跑微电网调度必须先把它改造成多目标版本。这中间不是简单改两个函数而是要对整个算法的选择机制动刀子。2.1 单目标粒子群的基本记忆机制粒子群算法的灵感来自鸟群觅食一个粒子就是解空间里的一个候选解。每个粒子有位置向量X和速度向量V位置表示一组决策变量速度表示下一轮移动的方向和幅度。粒子在进化过程中会记住两件事自己历史上找到过的最好位置pbest以及整个种群目前找到的最好位置gbest。每次迭代时粒子根据自己的速度惯性、向pbest的认知学习、向gbest的社会学习来更新位置。速度更新公式是v(t1) w * v(t) c1 * r1 * (pbest - x(t)) c2 * r2 * (gbest - x(t))x(t1) x(t) v(t1)这里w是惯性权重控制粒子保持当前飞行趋势的程度c1和c2是学习因子分别控制向个体历史最优和群体最优靠近的强度r1和r2是[0,1]之间的随机数给搜索引入随机性。w很大的时候粒子倾向于到处飞适合全局探索w很小的时候粒子倾向于在当前区域精细搜索适合局部开发。常用的做法是让w从0.9线性递减到0.4前期找大方向后期精细收敛。2.2 Pareto支配与外部档案集单目标PSO里只有一个gbest谁的目标函数值最小谁就是群体最优。但多目标问题里没有唯一最优解只有一组互不支配的解这时候需要引入Pareto支配的概念。假设有两个解X和Y它们都有多个目标值。如果X在所有目标上都不比Y差并且至少有一个目标严格优于Y那么就说X支配Y。反之如果X在成本上更低但碳排放更高Y在成本上更高但碳排放更低那么X和Y互相都不支配两者都可以保留在候选解集中。最终得到的一组互相都不被支配的解就是Pareto最优解集把它们画在目标空间里就得到Pareto前沿。多目标粒子群算法会在种群之外维护一个外部档案集专门存放当前找到的非支配解。每轮迭代后把粒子的新位置和档案集里的解做支配关系判断新解支配了档案集里的某些解就替掉它们新解被档案集里的某个解支配就丢弃互不支配就把新解加进去。档案集解决了“群体最优是谁”的问题。单目标里gbest是唯一的多目标里Pareto前沿上所有解都是“最优”的候选者因此算法的领导者可以每次从档案集里挑选而不是固定为某个唯一的全局最优。我最初做多目标改造时想过直接把所有目标的加权和作为单目标函数跑多次不同权重来生成Pareto前沿。这个方法在目标函数都较为线性、Pareto前沿是凸集的时候勉强可用但一旦前沿是非凸的就有一部分折中解永远扫不出来。MOPSO用档案集加支配关系本质上是在“同时优化多个目标”而非“把多个目标揉成一个”前沿完整性会好很多。2.3 领导者选择与拥挤度距离档案集建好之后怎么选leader是个容易影响结果但又经常被忽略的细节。如果每次迭代固定选档案集里编号最小的解当leader所有粒子都朝那一个方向飞种群多样性很快会退化最终前沿会缩成一小块区域。常见的做法有两种。第一种是简单随机法每次从档案集里随机选一个解作为leader实现非常容易实际效果也还行。第二种是网格法把目标空间划分成很多网格统计每个网格里有多少个档案解然后从“解数量较少”的网格里随机选leader。这样算法会倾向于探索稀疏区域让最终前沿更均匀地铺满整个边界。为了控制档案集规模还需要用到拥挤度距离。拥挤度是衡量档案集里某个解周围“有多少其他解”的指标先把目标值归一化再按某个目标排序计算相邻两个解在这个目标上的距离把每个目标上的距离加起来得到拥挤度。拥挤度小说明这个解周围已经很密删掉它对前沿分布影响最小。档案集容量有限时每次都挤掉拥挤度最小的解保留尽可能分散的非支配解。这个思路和NSGA-II里的拥挤度排序很相似区别在于NSGA-II是每一代都重新排序MOPSO则是在外部档案集维护过程中动态处理。3. 微电网调度的MOPSO落地细节有了算法框架接下来就是把微电网调度问题塞进这个框架里的过程。这一部分我从决策变量编码、目标函数计算、约束处理一直到主流程逐层拆开讲给出一套可以直接搬过去改的代码骨架。3.1 决策变量编码与数据准备先确定调度模型的决策变量。假设系统里有柴油机、储能、联络线和已知的风光出力一天分成24个时段。一个最直接的做法是编码柴油机出力P_d(k)、储能功率P_b(k)、联络线功率P_g(k)共3个变量乘以24个时段得到72维的粒子位置向量。每个粒子就是一个完整的调度计划。但如果把三个变量都当成独立决策变量功率平衡约束就必须用罚函数来处理因为随机初始化出来的粒子几乎不可能天然满足等式约束。我在实际项目中更推荐一种“消元编码法”。既然功率平衡方程是 P_pv(k)P_wt(k)P_d(k)P_b(k)P_g(k)P_load(k)光伏和风电是已知量那么在编码时只把柴油机和储能功率作为决策变量联络线功率通过功率平衡直接解出来。P_g(k) P_load(k) - P_pv(k) - P_wt(k) - P_d(k) - P_b(k)算出来之后检查联络线功率是否在上下限范围内越限的话再做约束处理。这种编码方式的优点是让等式约束几乎天然满足决策变量从72维降到了48维维数降低对粒子群这种随机搜索算法是很大的帮助。储能功率的编码要特别注意充放电方向。我习惯用一个变量P_b表示储能出力正数表示放电负数表示充电上下限设为[-Pb_max, Pb_max]。这个约定在目标函数和SOC递推里都要统一否则很容易把充电算成放电成本计算结果完全错误。3.2 适应度计算和约束处理策略第一个目标函数是系统总运行成本按24个时段累加C_total Σ( C_fuel(k) C_om(k) C_grid(k) C_bat(k) )C_fuel是柴油燃料成本等于柴油机出力乘以燃料成本系数C_om是运维成本可以按出力乘比例系数C_grid是购电或售电费用从主网购电时为正向主网售电时为负分别用购电价和上网电价计算C_bat是按储能循环寿命折算的损耗成本通常按放电量乘以一个等效折旧单价。第二个目标函数是总碳排放E_total Σ( EF_diesel * P_d(k) EF_grid * P_g_buy(k) ) * ΔtEF_diesel和EF_grid分别是柴油机和电网购电的排放因子。储能本身不直接排碳但如果储能充电的电是柴油机发的那么这部分排放已经算在柴油机或购电项里了放电时不需要再重复计算。风光发电的排放近似取零。第三个目标我建议不要急着选“停电概率”这种离散指标因为粒子群的搜索过程对连续函数更友好。工程上常用联络线功率波动平方和把每相邻时段联络线功率差值的平方累加起来数值连续、梯度平缓有利于粒子群在决策空间里平滑搜索。如果微电网允许一定负荷卸载也可以把“负的供电满意度”作为第三个目标但需要额外的可靠性计算模块前期会复杂不少。约束处理是最影响算法稳定性的环节。我采用“可行性优先”的规则档案集只接受满足约束的可行解粒子的pbest更新时如果新解不可行就直接保留旧解初始化时尽量在变量可行域内均匀采样。再加上对联络线功率越限的惩罚项让不可行解虽然可能参与迭代但很难进入档案集。这种处理方式比单独调一个惩罚系数要稳得多也省去了为罚函数系数反复试错的麻烦。3.3 算法主流程与关键参数推荐我把MOPSO的主流程整理成下面的代码骨架。这里省去具体的目标函数实现只保留算法逻辑方便你替换成自己的微电网模型。# 多目标粒子群算法主流程伪代码风格 pop_size 100 max_iter 300 archive_size 40 w_max, w_min 0.9, 0.4 c1 c2 1.8 # 初始化粒子群 particles initialize_population(pop_size, dim48) for p in particles: p.pbest p.position.copy() evaluate(p) # 初始化档案集找出当前种群中的非支配可行解 archive get_non_dominated(particles) for t in range(max_iter): w w_max - (w_max - w_min) * t / max_iter for p in particles: # 从档案集中选择leader可用随机法或网格法 leader select_leader(archive) # 更新速度与位置 r1, r2 random(), random() p.velocity (w * p.velocity c1 * r1 * (p.pbest - p.position) c2 * r2 * (leader - p.position)) p.position p.position p.velocity # 越界修复 p.position boundary_repair(p.position) # 评估并更新pbest evaluate(p) if dominates(p, p.pbest) or not dominates(p.pbest, p): p.pbest p.position.copy() # 合并新解并更新档案集 archive update_archive(archive particles, archive_size) # 可选记录HV指标或前沿分布关于参数直接给出一套经过验证的推荐值供参考。种群规模一般取80到120决策变量维数越高越要偏大我这里48维用100粒子迭代次数取300到500迭代太少前沿没收敛太多对24小时调度来说又没必要惯性权重从0.9线性降到0.4学习因子c1和c2都取1.8经典设置档案集容量取40左右太小容易丢失极端解太大计算量上升但分布未必更好。速度上限Vmax通常取变量范围的10%到20%。Vmax太大会让粒子飞得太猛容易跳出可行域太小则收敛太慢、探索不足。这里我取柴油机和储能出力范围差值的15%效果还不错。4. 实操中的坑与排查方法算法框架跑通不难难的是结果不合理时不知道怎么改。我把实际项目中反复踩过的几个问题整理出来这些问题你在复现时大概率也会遇到。4.1 粒子“早熟”收敛Pareto前沿缩成一个点表现是运行多次最终档案集里的解在目标空间里都挤在一小片区域Pareto前沿明显没有铺开甚至在极端情况下所有非支配解就是同一个方案。这类问题基本都是Leader选择策略和种群多样性不足导致的。粒子群向一个强leader过度集中很快就把所有粒子“吸”到一起档案集里虽然保存了解但种群本身失去了继续探寻新区域的能力。排查顺序我建议这样先检查惯性权重起始值是不是太小低于0.8很容易前期就陷入局部区域再看leader选择如果是从档案集固定取第一个解的代码立刻改成随机选择或网格法最后可以给算法加点变异操作每迭代几轮随机挑一个粒子把它的某一维位置重置到可行域内随机值模拟遗传算法的突变效果对跳出局部区域很管用。实际测试中加了变异算子后前沿完整性明显改善。4.2 等式约束打破之后怎么办微电网调度里的功率平衡是强约束如果采用“把所有决策变量都放进粒子位置再罚函数”的写法大量粒子的等式约束违反度很高罚函数系数很难调到合适。系数太小不可行解混进档案集系数太大可行域边界附近的本来很好的解也被误判淘汰。我强烈建议改成前面提到的“消元编码法”只编柴油机和储能出力联络线由平衡方程反解。这样粒子群在迭代过程中虽然会暂时打破功率平衡而让联络线越限但违反的是联络线上下限是一个相对容易处理的边界约束而不是严格的等式约束整个搜索空间的质量会好很多。如果在遗留代码里不方便改编码可以试试动态惩罚系数约束违反量乘以一个随迭代次数增大的权重前期允许粒子在不可行区域探索后期强制收束到可行域。但这个方法对参数敏感度高不建议作为首选方案。4.3 时间序列与储能SOC的几个隐蔽问题储能SOC的递推是最容易出bug的地方。如果直接把SOC当作独立的决策变量编码进粒子粒子更新可能让SOC序列前后矛盾比如第5时段SOC是0.6、第6时段变成0.4但按储能功率递推公式算出来第6时段应该是0.8这种解物理上根本不成立。正确做法是SOC不作为决策变量而是在评估每个粒子时根据初始SOC和粒子携带的储能充放电功率序列逐时段递推得到SOC(k)。递推过程要区分充电和放电效率充电时SOC上升要乘充电效率放电时SOC下降要除以放电效率。如果某个时段的SOC越限就把越限总量计入约束违反度再按可行性规则处理。数据对齐问题也很隐蔽。分时电价有低谷、平段、高峰如果电价时间点和负荷曲线错位一个小时储能会按照错误信号充放电结果经济性差好几个点。还有柴油机爬坡约束的时间单位Δt到底是1小时还是15分钟爬坡速率单位是kW/min还是kW/h这些细节在写约束函数时都要仔细核对不然得到的调度方案在工程上完全不可执行。4.4 多目标解的评价与最终折中解选择算法跑完得到一堆档案集里的非支配解最后到底选哪一个很多第一次接触多目标优化的人会卡在最后一步。我的做法是先用“模糊隶属度函数”做折中决策。对每个目标找出所有Pareto解中该目标的最小值和最大值然后给每个解在每个目标上计算隶属度数值越大越接近该目标的最优值再把某个解在所有目标上的隶属度取平均平均值最大的就是综合折中最好的解。这种方法主观性相对小也方便运行人员根据不同偏好调整权重。评价算法本身的性能也很重要。如果拿不到理论最优前沿可以计算档案集的超体积指标HV用所有解对参考点围成的超立方体体积来衡量覆盖性和收敛性。HV值越高说明这套参数下的优化结果越好。我在调参时会把每次迭代的HV记录下来如果HV在前半段涨得很慢说明参数选择可能有方向性偏差。最后再分享一个我的经验多目标粒子群解决微电网调度算法本身的难度远比问题建模和约束处理的难度低。粒子群代码网上很多但换一个系统、换一组数据就能跑出有意义结果靠的是把物理约束理解透、把编码方式选对、把数据单位对齐。我实际调这个项目时真正花费时间的不是粒子群公式而是储能SOC递推逻辑和联络线越限处理这两块。如果你刚起步建议先用一个很小的算例比如两个目标、三个决策变量的规模把Pareto支配、档案集更新、拥挤度排序这些逻辑用单步调试看清楚再上完整的24时段微电网模型。很多人在大代码里找bug找得头大反而失去了对算法本身的感觉。粒子群加多目标是个非常好用的组合尤其适合微电网调度这种连续变量多、Pareto前沿相对光滑的问题。希望这篇文章能帮你少踩几个我已经踩过的坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑