资讯动态

粒子群算法求解多微网优化调度:蓄电池-发电机-交互功率协同

发布时间:2026/9/30 8:37:02 来源:尧图企业网站定制
1. 多微网优化调度的核心问题与建模思路1.1 两个微网之间调度到底在优化什么做过多微网调度的人都知道单微网调度已经够折腾了一旦变成两个微网互联问题就从怎么让自己活好变成了怎么让大家一起活好。这个项目的标题很直接——用粒子群算法分析两个微网的优化调度核心产出是蓄电池、发电机和微网间交互功率的调度方案。说白了就是在一个小时级的调度周期内通常是24小时决定每台蓄电池充多少放多少、发电机发多少电、微网A和微网B之间交换多少功率让整个系统在经济性、可靠性和新能源消纳之间达到平衡。我拿到这类问题后的第一反应从来不是急着写代码而是先把物理模型理清楚。两个微网各带什么负荷光伏和风电装机多大蓄电池容量和功率限制是多少柴油发电机有几台、最小出力是多少微网之间联络线的功率上限是多少这些问题不搞清楚算法写得再花哨也是白搭。常见的设定是微网A和微网B各有一套光伏、负荷和储能设备中间通过一条联络线相连允许功率双向流动。因为光伏出力有波动性负荷也有高峰低谷如果两个微网各自独立运行遇到光伏出力大而负荷小的时段只能想办法消纳或者弃光遇到负荷高峰而光伏不足就只能靠蓄电池硬扛或者让发电机多烧油。但互联之后A的富余电量可以送到BB的富余电量也可以反哺A整体上就能减少发电机启停次数、降低运行成本。这个项目的落点蓄电池、发电机以及微网间交互功率恰好就是多微网调度里最核心的三类变量。蓄电池解决时间维度上的能量搬移发电机解决容量不足时的兜底出力联络线功率解决空间维度上的互补互济。三者协同优化才是多微网调度的价值所在。1.2 目标函数与约束条件的拆解多微网优化调度一般建模成一个约束优化问题。目标函数最常见的是最小化总运行成本包括发电机燃料成本、蓄电池充放电折算成本或者老化成本、从上级电网购电成本也有的版本把微网间交互功率产生的交易费用算进去。为了突出新能源消纳还可以在目标函数里加上弃光、弃风的惩罚项。目标函数写成数学形式大致是这样[ \min F \sum_{t1}^{T} \left[ \sum_{g} C_g(P_{g,t}) C_{bat}(P_{bat,t}) C_{buy}(P_{grid,t}) C_{penalty}(P_{curtail,t}) \right] ]其中 (C_g(P_{g,t})) 是发电机在时段的燃料成本通常简化为 (aP^2 bP c) 的二次函数形式。(C_{bat}) 是蓄电池充放电的折算成本(C_{buy}) 是向上级电网购电的费用最后一项是弃光弃风惩罚。约束条件就比较多了每一条都是实际物理限制的体现功率平衡约束每个微网任意时刻必须满足出力负荷交互功率这是最基本也是绝对不能违反的条件。蓄电池约束包括SOC上下限一般0.1~0.9、充放电功率限制、充放电效率有的模型还会约束SOC连续变化避免频繁充放切换。发电机约束出力上下限、爬坡速率限制还有最小启停时间不过粒子群做离散启停变量会比较麻烦常见做法是假设发电机全天在线只优化出力。联络线约束交互功率不能超过联络线容量这是很多人容易忽略的。弃光弃风约束如果允许丢弃新能源出力需要把弃电量定义成变量并加上惩罚系数。我在最开始做这个模型时曾经只关注功率平衡而忽略了联络线容量结果算出来的结果非常理想——A微网凭空给B送了好几百千瓦。仔细一查才发现是自己没加约束这种低级错误如果不是回头检查物理合理性很容易漏过去。1.3 为什么选粒子群算法而不是线性规划很多做调度的人第一反应是这明明是个可以线性化的优化问题为什么不用cplex、gurobi或者单纯形法非线性成本函数分段线性化之后用商业求解器几分钟就能出结果。但实际情况是粒子群算法在这个场景下有自己的独特优势。首先蓄电池充放电效率、发电机燃料成本曲线等往往是强非线性的虽然可以分段线性化但分段多了模型规模会暴涨尤其在日内滚动调度场景下求解时间可能反而不如启发式算法稳定。其次粒子群算法对目标函数的要求很低——不需要可导不需要凸性甚至不需要明确的数学表达式。工程上经常遇到那种跑一次仿真要半分钟评估一个解就要调用一次仿真的黑盒模型这时候解析优化方法根本无从下手粒子群反而可以硬算。不过我必须说句公道话如果这个项目只是为了写论文、算一个离线最优解商业求解器确实更靠谱最优性和求解速度都有保障。粒子群算法的优势在于灵活、实现简单、不需要额外工具箱而且方便后续扩展——比如加上需求响应、考虑不确定性场景、或者把微网数从两个扩展到五个代码改动量都不大。作为教学和工程验证粒子群是个很好的切入点。2. 粒子群算法原理与在微网调度中的用法2.1 粒子群的核心机制用大白话讲清楚粒子群算法的思想其实很简单想象一个鸟群在一片未知区域里找食物每只鸟不知道食物在哪但知道当前位置离食物有多远。它们会记住自己飞过的最好位置也会观察群体里其他鸟发现的最好位置然后综合这两个方向调整自己的飞行速度和方向。在数学上每个粒子就是优化问题的一个候选解用一个位置向量表示。每个粒子有一个速度向量决定它在解空间里怎么移动。每次迭代分三步更新速度、更新位置、更新个体和全局最优。速度更新公式是[ v_{i}(k1) w \cdot v_{i}(k) c_1 r_1 (pbest_i - x_i(k)) c_2 r_2 (gbest - x_i(k)) ]其中 (w) 是惯性权重控制粒子沿原方向飞行的惯性(c_1) 和 (c_2) 是学习因子分别控制向个体最优和全局最优学习的强度(r_1) 和 (r_2) 是[0,1]之间的随机数。位置更新更简单(x_i(k1) x_i(k) v_i(k1))。这个算法最迷人的地方就是没有梯度计算只靠适应度值就能搜索。对于多微网调度这种决策变量多、约束复杂的问题粒子群不需要对模型做太多改动只需要把决策变量编成粒子定义好适应度函数跑起来就行了。2.2 粒子怎么编码这是粒子群调度的关键粒子编码方式决定了问题的维度和搜索效率。多微网调度里常见的做法有两种一种是把所有决策变量全部编码进粒子另一种是用粒子群优化部分变量其余变量通过潮流计算或约束推导求出。我自己偏向于全变量编码虽然维度更高但实现简单、不容易出逻辑错误。假设两个微网各有一台蓄电池、一台发电机加上一个联络线功率变量调度周期24小时每个决策变量对应24个时段微网A蓄电池充放电功率24个维度微网B蓄电池充放电功率24个维度微网A发电机出力24个维度微网B发电机出力24个维度微网间交互功率正方向A送B24个维度总维度 5 × 24 120维。这个维度对粒子群来说是中等规模能处理但要特别注意收敛速度。还有一种更聪明的编码方式只把蓄电池出力作为粒子变量发电机出力通过功率平衡反推。因为功率平衡约束是等式约束如果蓄电池和交互功率确定了发电机出力就是唯一确定的值。这样做可以把120维砍到48维搜索效率翻倍。代价是发电机出力的上下限约束需要在适应度计算时额外判断如果反推出的发电机出力超限要靠罚函数处理。我建议初学者先用全变量编码逻辑清晰、调参方便等模型跑通了再尝试降维编码对比一下收敛效果。两种方式我都试过降维之后迭代次数大概能减少20%~30%。2.3 参数选择惯性权重、学习因子和种群规模粒子群算法的参数没有绝对标准但根据大量实操经验有一些比较稳妥的初始值。惯性权重 (w) 建议取线性递减策略从0.9递减到0.4。前期大惯性权重有利于全局探索避免粒子过早扎堆后期小惯性权重有利于局部精细搜索提高收敛精度。实际代码里这么写w w_max - (w_max - w_min) * iter / max_iter;学习因子 (c_1) 和 (c_2) 建议取2.0。有的文献推荐 (c_1 c_2 \leq 4)这个经验值是经过大量测试得到的比较稳妥。种群规模方面120维的问题建议80~120个粒子。太小了容易早熟太大了计算量成倍增长。迭代次数一般在200~500次对于离线调度300次是个比较均衡的选择。速度限幅也一定要做。粒子的速度过大会导致位置震荡、无法收敛过小又容易陷入局部最优。一种常用的做法是把每个维度的速度限制在该维度变量取值范围的20%~30%之间。比如蓄电池出力范围是-50kW到50kW速度就限制在±20kW以内。我自己用过一组比较实用的参数粒子数100、最大迭代300、(w)从0.9线性降到0.4、(c_1c_22.0)、速度限幅取变量范围的25%。这组参数在我跑过的三四个微网调度模型上表现都比较稳定可以作为起点再微调。3. MATLAB实现步骤与代码框架3.1 数据准备光伏、负荷和蓄电池参数写MATLAB代码之前先把数据准备好。这个项目的输入数据包括24小时的光伏出力、负荷曲线以及蓄电池和发电机的技术参数。数据可以自己生成也可以用实际数据。我习惯用一个结构体把参数打包方便管理% 系统基础参数 para.T 24; % 调度时段数 para.dt 1; % 时段间隔小时 % 微网A参数 para.load_a [40, 38, 35, 34, 36, 42, 50, 65, 80, 85, 82, 78, ...]; % 24h负荷kW para.pv_a [0, 0, 0, 0, 0, 5, 18, 35, 50, 58, 55, 45, ...]; % 24h光伏出力kW % 蓄电池参数 para.bat_cap_a 100; % 容量kWh para.bat_pmax_a 50; % 最大充放电功率kW para.bat_eff_a 0.95; % 充放电效率 para.soc_min_a 0.1; % SOC下限 para.soc_max_a 0.9; % SOC上限 para.soc_init_a 0.5; % 初始SOC % 发电机参数 para.gen_pmin_a 10; % 最小出力kW para.gen_pmax_a 80; % 最大出力kW para.gen_a 0.02; % 燃料成本二次项系数 para.gen_b 0.5; % 燃料成本一次项系数 para.gen_c 5; % 燃料成本常数项 % 联络线参数 para.line_max 60; % 联络线最大传输功率kW微网B的参数结构完全对称只是数值不同。这里多说一句负荷和光伏数据最好画个图看一眼确认没有明显的异常值。我遇到过一组数据凌晨3点的光伏出力是35kW明显是测量错误如果不清洗直接带入模型粒子群会给这段莫名其妙的出力安排一堆调整动作白白浪费迭代次数。3.2 适应度函数与罚函数的设计粒子群的适应度函数就是目标函数加罚函数。罚函数是约束处理的关键。多微网调度里的约束大多是不等式约束出力上下限、SOC范围、联络线容量少数是等式约束功率平衡。罚函数的常规写法是把每个约束的违反量标准化然后乘一个惩罚系数累加到目标函数里。function fitness calc_fitness(x, para) % x是粒子位置向量按预定义顺序拆解出各变量的24小时序列 [Pbat_a, Pbat_b, Pgen_a, Pgen_b, Plink] decode(x, para); % 目标函数发电成本 蓄电池折算成本 购电成本 cost_total 0; for t 1:para.T cost_gen_a para.gen_a * Pgen_a(t)^2 para.gen_b * Pgen_a(t) para.gen_c; cost_gen_b para.gen_b * Pgen_b(t)^2 para.gen_b * Pgen_b(t) para.gen_c; cost_total cost_total cost_gen_a cost_gen_b; end % 约束违反量计算 penalty 0; % 功率平衡违反 for t 1:para.T % 微网APgen Ppv Pbat P_link 负荷 imbalance_a Pgen_a(t) para.pv_a(t) Pbat_a(t) Plink(t) - para.load_a(t); imbalance_b Pgen_b(t) para.pv_b(t) Pbat_b(t) - Plink(t) - para.load_b(t); penalty penalty 1000 * (abs(imbalance_a) abs(imbalance_b)); end % SOC约束、出力上下限等类似处理 fitness cost_total penalty; end罚函数系数的取值很讲究。我一开始把功率平衡的惩罚系数取成10结果粒子群完全无视约束因为违反约束能省更多发电成本。后来调到1000效果好了很多但收敛变慢了。实际情况中这个系数可以通过试凑法确定一般从100开始如果约束违反量迟迟降不下来就增大惩罚系数如果粒子群陷入局部最优再适当调小。3.3 主程序框架初始化、迭代、收敛判断主程序逻辑不复杂但有一个细节容易踩坑粒子位置的初始化方式。如果采用随机均匀初始化很多粒子会初始就违反大量约束导致前期适应度值巨大收敛很慢。更好的做法是让一部分粒子从可行解附近出发——比如用启发式规则生成几个初始解例如蓄电池全天不出力、联络线功率为0、发电机按负荷比例分配然后在这个解附近加随机扰动生成初始种群。这样能显著加快收敛。主程序框架如下% 参数设置 num_particles 100; max_iter 300; dim 120; w_max 0.9; w_min 0.4; c1 2.0; c2 2.0; % 初始化粒子位置和速度 x zeros(num_particles, dim); v zeros(num_particles, dim); for i 1:num_particles x(i,:) init_particle(para); % 启发式随机扰动 v(i,:) (rand(1,dim) - 0.5) * 2 .* vmax; end % 计算初始适应度 fitness zeros(num_particles, 1); for i 1:num_particles fitness(i) calc_fitness(x(i,:), para); end pbest x; % 个体最优 pbest_fitness fitness; [gbest_fitness, best_idx] min(fitness); gbest x(best_idx,:); % 迭代优化 for iter 1:max_iter w w_max - (w_max - w_min) * iter / max_iter; for i 1:num_particles v(i,:) w * v(i,:) c1 * rand(1,dim) .* (pbest(i,:) - x(i,:)) c2 * rand(1,dim) .* (gbest - x(i,:)); v(i,:) bound_velocity(v(i,:), vmax); % 速度限幅 x(i,:) x(i,:) v(i,:); x(i,:) bound_position(x(i,:), para); % 位置边界处理 fit calc_fitness(x(i,:), para); if fit pbest_fitness(i) pbest(i,:) x(i,:); pbest_fitness(i) fit; end if fit gbest_fitness gbest_fitness fit; gbest x(i,:); end end fprintf(Iter %d: fitness %.4f\n, iter, gbest_fitness); end % 结果解码与绘图 [Pbat_a, Pbat_b, Pgen_a, Pgen_b, Plink] decode(gbest, para); plot_schedule(Pbat_a, Pbat_b, Pgen_a, Pgen_b, Plink, para);值得提醒的是我在很多代码里见过一个低级错误位置边界处理后直接把粒子值截断到边界但没有同步处理速度。这样会导致粒子在边界附近反复碰撞速度累积到很大影响收敛。正确的做法是如果某个维度超出了边界就把该维度的速度也清零或者反向置一个较小的值。3.4 结果输出SOC曲线和功率曲线怎么画粒子群跑完之后输出结果通常包括四张图微网A的功率平衡图、微网B的功率平衡图、蓄电池SOC曲线、微网间交互功率曲线。画图是MATLAB的强项但很多人画出来的图堆叠太多信息阅读体验很差。我常用的画法是把每个微网的图拆成上下两部分上面画发电机出力、光伏出力和负荷下面画蓄电池出力和交互功率。SOC曲线单独画一张图标注出上下限。这样一张图包含功率平衡的全部信息同时SOC的变化趋势一目了然。figure(1); subplot(2,1,1); bar(1:24, [Pgen_a, para.pv_a], stacked); hold on; plot(para.load_a, r-, LineWidth, 2); legend(发电机, 光伏, 负荷); xlabel(时段h); ylabel(功率kW); title(微网A功率平衡);画完图以后一定要肉眼检查几个关键点SOC是否在限值范围内每个时段的功率是否满足平衡交互功率是否超过联络线容量这些检查看起来笨但能抓住很多隐藏问题。4. 典型调度结果分析蓄电池、发电机和微网间功率4.1 蓄电池SOC曲线的典型形态调通模型之后最有意思的部分就是看结果。蓄电池SOC的曲线形态在很大程度上能反映调度策略的合理性。正常情况下蓄电池的SOC应该呈现早晚低、中间波动的特征——白天光伏出力大、负荷相对低的时候充电晚上负荷高峰的时候放电。如果微网间有交互功率SOC曲线还会叠加一个与相邻微网互济的波形。比如A微网光伏出力大可能白天不仅自己充电还给B充电到了晚上负荷高峰A自身蓄电池可能提前放完转而从B购电这时候B的SOC曲线就会在晚高峰时段出现明显下降。如果看到SOC曲线在0.1附近长时间停留说明蓄电池被压榨得太狠了——可能罚函数设置过松导致粒子群更喜欢把蓄电池往极限用。如果SOC一直贴着0.9则说明蓄电池放电太少没有充分发挥储能的价值。这两种情况都需要检查目标函数中蓄电池相关成本项的设计。还有一种常见问题是SOC曲线抖动剧烈每隔一两个时段就充放切换。这种方案在仿真里看着没问题实际运行时蓄电池寿命会大打折扣。解决办法是在目标函数里加一个充放电切换惩罚项或者设置蓄电池的最小连续充放时段。4.2 发电机的出力曲线与成本权衡发电机出力曲线是最能反映经济性考量的部分。按理说发电机应该尽量避免在负荷低谷期满负荷运行而在高峰期作为备用电源顶上。我在跑一个案例时发现发电机出力曲线出现了午间低谷现象——中午光伏出力大发电机出力几乎降到最小值。这符合预期说明模型学会了优先消纳新能源。但紧接着我又发现另一个问题发电机从80kW骤降到10kW再升回去爬坡速率明显超过了柴油机的物理限制。这是因为粒子群没有显式处理爬坡约束导致出力序列变化过快。处理这个问题的办法有两种。一是把爬坡约束直接写成罚函数项违反一次罚一次二是在粒子编码时做文章不让每个时段的独立出力作为变量而是让发电机出力作为上一时段出力加上增量形式。增量编码能天然满足爬坡约束是我后来项目中比较推荐的做法。4.3 微网间交互功率的规律微网间交互功率是最能体现互联价值的变量。在结果里如果某条联络线的功率长时间为零说明两个微网的负荷和发电曲线没有互补性互联形同虚设。如果交互功率频繁正负切换说明两个微网在互相博弈——这本身没问题但要注意实际运行中频繁切换会对联络线保护和变压器寿命产生影响。我跑过一个典型场景A微网的负荷峰值在上午B微网的负荷峰值在晚上。优化结果中上午时段联络线功率为正A向B送电因为A在上午有光伏余电晚上时段联络线功率为负B向A送电因为B的蓄电池此时还有余量。这种双向互济的调度结果就是多微网优化调度最理想的形态。另一个值得关注的指标是交互功率的峰值利用率。如果联络线容量是60kW而优化结果中峰值功率长期只有20kW说明两个微网的互补性没有充分发挥可能是不需要那么大功率也可能是蓄电池SOC约束太紧限制了交互能力。这时候可以适当放宽蓄电池的SOC范围观察系统总成本能否进一步下降。4.4 与单微网独立运行的对比验证多微网模型价值的常用手段是把两个微网解耦分别做单微网调度然后把总成本与多微网优化结果做对比。我跑过一次对比实验独立运行时两个微网的总成本是1420元/天多微网协同优化后降到1290元/天降幅约9%。这个数字主要由两部分贡献一是光伏余电的跨微网消纳减少了弃光二是两个微网共用发电机容量降低了高峰期的边际购电成本。这个对比不只是为了写论文好看它其实验证了模型的正确性——如果多微网优化结果比独立运行还差那大概率是模型本身写错了而不是互联没有价值。5. 实操中的常见问题与排查经验5.1 粒子群收敛太慢或陷入局部最优多微网调度是120维的非线性问题粒子群很容易陷入局部最优。最常见的表现是迭代到100代之后适应度值还在缓慢下降但每次下降的幅度非常小或者迭代几十代就完全停止下降提前收敛。排查顺序是这样的先看种群规模——粒子数太少是早熟的第一大嫌疑从80加到150试试再看惯性权重——如果用的是固定权重就改成线性递减再看速度限幅——速度上限太小会让粒子走不出局部区域。还有一个技巧是多次运行取最优。粒子群本质是随机算法单次运行的最优解有偶然性。我一般跑10次每次记录最优适应度最终取10次中的最优值作为结果。如果10次运行的结果差距很大说明算法稳定性差需要继续调参如果10次结果接近说明已经比较稳妥了。5.2 罚函数系数的调整方法罚函数系数是粒子群约束处理里最痛的点。系数太小约束被无视系数太大适应度函数里约束惩罚项压制了真实目标函数粒子群会只顾着满足约束而忽略经济性优化。我总结了一套实用的调整流程先把所有约束的惩罚系数统一设成100跑一次看约束违反量。如果违反量还很大按10倍递增如果完全满足约束了但收敛精度变差就逐步降低。在功率平衡这个等式约束上惩罚系数通常要比不等式约束大一个数量级因为等式约束一旦被违反物理上就完全不可行。我见过一些文献里用动态罚函数来处理这个问题——迭代前期惩罚系数小允许粒子群探索更广的区域迭代后期惩罚系数逐渐增大把粒子往可行域上逼。这个方法效果好但参数更多建议先把静态罚函数调明白了再去试。5.3 蓄电池SOC越限问题SOC越限是储能调度里最常见的约束违反类型。原因通常有两个一是变量初始化时SOC初值和充放电功率不匹配导致前几个时段SOC就被推出边界二是迭代过程中粒子位置更新越界后只截断位置但没有约束SOC的递推关系。这里有个容易忽视的细节SOC是累积量(SOC(t) SOC(t-1) P_{bat}(t) \cdot \eta \cdot \Delta t)。即使每个时段蓄电池功率都在限制范围内SOC经过一天累积也可能越过边界。比如初值0.5、持续小功率放电一天到夜里可能就跌破0.1了。解决方法是把SOC越限也加入罚函数但更要紧的是在初始化时做好合理性检查先随机生成充放电功率序列然后递推计算SOC序列如果SOC越限就重新生成。初始种群质量提高了后续迭代会省很多事。5.4 参数灵敏度与结果稳定性验证优化模型跑通之后建议做一组参数灵敏度分析验证结果的稳健性。我常做的实验包括把光伏出力整体增减10%看系统总成本的变化比例——如果成本波动太大说明系统对新能源依赖过强调度方案偏脆弱。把蓄电池容量增减20%看总成本的边际改善——如果容量增加但成本下降不明显说明现有调度方案中蓄电池利用率偏低可以考虑适当减小容量配置。把联络线容量从60kW改成30kW和100kW对比总成本差异——联络线容量扩大带来的收益递减规律是否明显。这类分析对工程决策很有价值也是论文或者报告里比较加分的部分。但要注意不要把所有参数都做全因子实验挑三四个关键参数足够了。做太多反而会让结果看起来像随机噪声抓不住重点。另外还要强调的是粒子群算法本身有随机性任何一次运行的最优解都只是近似解。在做灵敏度分析时每个场景至少跑5次取最优或平均值保证结论不是某个随机种子带来的偶然结果。实操总结与后续扩展建议这个多微网优化项目做到后面我的体会是模型本身并不复杂真正的瓶颈在于把物理约束表达准确、把算法参数调得顺手、把结果检查机制做好。粒子群算法作为启发式方法跑通很容易跑得好需要在细节上花功夫——罚函数系数怎么取、速度限幅怎么设、初始种群怎么生成这些细节决定了最终方案的实用价值。最后分享一个扩展方向当前模型是离线优化也就是假设光伏出力和负荷曲线是完全已知的。实际工程中光伏预测有误差负荷会波动下一步可以做日内滚动优化——每30分钟滚动一次用最新实测数据更新调度策略粒子群每次重新优化未来4小时到8小时的出力方案。这个扩展做下来项目的实用性会大大提升也更有说服力。

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

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

免费获取报价 →
↑