差分进化算法在微电网经济调度中的应用与Matlab实现

发布时间:2026/9/24 21:16:52
差分进化算法在微电网经济调度中的应用与Matlab实现 1. 微电网调度到底在调度什么先把问题模型写清楚1.1 为什么说模型不清算法白搭我见过不少研究生拿到课题第一件事就是翻差分进化算法的论文把变异算子、交叉算子背得滚瓜烂熟然后一头扎进代码里。结果折腾两周跑出来的最优解连功率平衡都满足不了。问题几乎都出在同一个地方优化问题本身的数学描述压根没搭对。微电网经济调度本质上是一个带约束的非线性优化问题。我们在做的不是用DE算法算一个函数最小值而是给一个真实的小型电力系统寻找最便宜的发电组合方案。这个系统里有柴油发电机、光伏板、风机、储能电池还可能跟大电网有联络线。不同电源发电成本不一样柴油机要烧油光伏阳光免费但出力不受控储能充放电有效率损耗从大电网买电有分时电价。调度要做的事就是在满足负荷需求的前提下把各电源的出力安排到总运行成本最低。先把这个模型写清楚比算法本身重要得多。很多人拿着别人的代码改来改去改完也不知道每个矩阵、每个约束对应的是什么物理含义最后结果错了都不知道上哪排查。1.2 决策变量、目标函数与约束条件的标准写法先从数学上讲清楚。决策变量对于单时段调度,最常见的形式是直接以各分布式电源的有功出力作为优化变量比如柴油机出力 (P_{DG})、储能放电功率 (P_{dis})、储能充电功率 (P_{ch})、向大电网购电功率 (P_{grid})。我这里把储能充电功率定义为正数、放电功率定义为正数都是通过变量约束来处理。如果是24小时动态调度变量就变成矢量例如 (P_{DG} [P_{DG,1}, P_{DG,2}, ... , P_{DG,24}])维度成倍增长这也是为什么微电网调度需要用群智能优化算法而不是穷举法去求解的原因之一。目标函数最小化总运行成本一般写成[ \min ; f \sum_{i1}^{N} \left( a_iP_{DG,i}^2 b_iP_{DG,i} c_i \right) C_{OM} C_{bat} C_{grid} ]第一项是柴油发电机的燃料成本通常用二次函数拟合(a)、(b)、(c) 是成本系数注意这里的 (P) 一般取实际单位MW或kW不同单位下系数差很多我在网上看到不少人把别人的 kW 级系数直接用在 MW 级算例里结果目标函数值离谱得离谱。(C_{OM}) 是各电源的运行维护成本一般跟出力成正比乘一个比例系数就行。(C_{bat}) 是储能充放电的损耗成本或折算后的寿命损耗成本有的简化模型忽略这一项但从实际项目角度说忽略储能损耗会导致调度结果频繁充放电工程上不成立。(C_{grid}) 是与主网交换功率的成本购电为正、售电为负具体数值由分时电价决定。约束条件功率平衡约束最重要必须等式成立[ P_{DG} P_{PV} P_{WT} P_{dis} P_{grid} P_{load} P_{ch} ]注意储能充电要放在负荷侧很多新手在这里容易搞错符号。电源出力上下限约束比如 (P_{DG}^{\min} \leq P_{DG} \leq P_{DG}^{\max})。储能约束包括充放电功率上限和SOC荷电状态范围。单时段模型里我一般只考虑充放电功率限制动态调度里还要加SOC递推关系式即[ SOC(t1) SOC(t) \frac{\eta_{ch} P_{ch}(t) \Delta t}{E_{ess}} - \frac{P_{dis}(t) \Delta t}{\eta_{dis} E_{ess}} ]联络线功率约束加上 (P_{grid}^{\min} \leq P_{grid} \leq P_{grid}^{\max})防止出现某种状态下微网向大电网倒送太多功率。1.3 一个可直接使用的算例参数方便后面讨论代码下面给出一套我常用的单时段测试参数这套数据在网络公开文献里也比较常见适合作为对比验证基准。参数项数值柴油机出力下限 / 上限10 kW / 100 kW柴油机成本系数 a, b, c0.02 元/kW², 0.8 元/kW, 10 元光伏预测出力 (P_{PV})40 kW风电预测出力 (P_{WT})30 kW负荷需求 (P_{load})180 kW储能容量 / 最大充放电功率60 kWh / 25 kW储能充电效率 / 放电效率0.95 / 0.95购电电价 / 售电电价1.0 元/kWh / 0.4 元/kWh主网交换功率上限50 kW这套配置下如果光靠柴油机和新能源负荷缺口还很大必然要从电网购电。所以最终的调度结果应该是柴油机、储能、从电网购电按成本最优的方式形成一个合理组合。模型写到这里才算具备了用算法求解的前提。你要是把自己课题的代写代码拿来对照第一件事就应该是检查这些约束和目标函数跟你的物理场景对不对得上。2. 差分进化算法解调度的思路为什么选DE而不是粒子群2.1 差分进化算法的三个核心算子差分进化算法Differential EvolutionDE是Storn和Price在1997年提出的进化算法核心思想用一个词概括就是差分变异。它跟遗传算法最大的区别在于它用种群内个体之间的差异向量来引导搜索方向而不是靠经典的交叉和位翻转变异。标准DE有几个关键步骤初始化种群在决策变量的上下界范围内随机生成 (N) 个个体每个个体就是一组调度方案。比如单时段模型里一个个体就是 ([P_{DG}; P_{dis}; P_{grid}]) 这样的向量。变异对每个目标个体 (x_i)随机挑三个互不相同的个体 (x_{r1}, x_{r2}, x_{r3})产生变异向量[ v_i x_{r1} F \cdot (x_{r2} - x_{r3}) ]这里的 (F) 是缩放因子控制差分扰动的强度。我的理解是(F) 太大容易导致搜索发散太小容易陷入局部最优。这个参数对调度问题的收敛行为影响非常明显。交叉把变异向量 (v_i) 和当前个体 (x_i) 按照交叉概率 (CR) 逐维混合生成试验向量 (u_i)。DE的交叉算子相对简单掷骰子决定每个维度来自变异向量还是原个体。选择贪婪选择如果试验向量 (u_i) 的适应度比当前个体 (x_i) 更好就用它替换掉 (x_i)否则保留原来的。2.2 与遗传算法、粒子群算法相比的优势在哪做微电网调度的文献里粒子群算法PSO和遗传算法GA也经常出现。那为什么我在实际项目中更偏爱DE对比维度差分进化 DE粒子群 PSO遗传算法 GA控制参数数量3个N, F, CR通常4-5个惯性权重、个体学习因子、社会学习因子等3-4个种群大小、交叉率、变异率、选择压力变异机制利用种群自身的差分向量自适应强基于全局最优和自身历史最优的线性组合经典的随机变异搜索引导性较弱对约束处理的支持天然配合罚函数或约束支配规则实现简单容易陷入局部最优需要额外改进策略变异和交叉算子都可能破坏可行性修复麻烦连续实数优化表现在多个标准测试函数上表现稳定收敛精度高收敛快但过早收敛风险大全局搜索强但后期收敛慢代码量Matlab大约80-120行核心循环代码量差不多但调参更烦需要实现选择、交叉、变异多个算子代码更多这张表是我的主观经验总结不一定适合所有问题但针对微电网经济调度这种维数不算特别高通常决策变量个数在几个到几十个之间、约束复杂、可行域非凸的连续优化问题DE的综合表现确实让我比较放心。2.3 参数敏感性一个容易被忽略的坑DE算法参数不多但每个参数都有脾气。种群规模 (N)经验上取决策变量维数的5到20倍。微电网24小时调度里决策变量可能是几十个这时种群太小覆盖不够太大又浪费算力。我自己的经验是单时段问题 (N40) 足够24小时动态调度最好取 (N100) 以上。变异因子 (F)取0.5到0.9之间相对安全。(F) 越大差分扰动越剧烈全局探索能力强但收敛慢(F) 太小种群容易早熟。还有一个技巧是让 F 随迭代次数线性变化前期用大 F 探索后期减小 F 加强局部搜索能明显改善收敛精度。交叉概率 (CR)取0.6到0.95之间。(CR) 越接近1试验向量越像变异向量收敛快但可能跳过最优解附近(CR) 越小种群多样性保持得越好。说实话DE的调参难度比PSO低很多。PSO那几个参数之间会相互作用改了一个不一定保证什么DE至少收敛行为相对直观。这也是我给初学者推荐DE作为微电网调度入门算法的原因——可以快速跑通一个可用的调度程序再逐步添加改进策略。3. 差分进化算法的Matlab代码实现从零搭一个可运行的调度程序3.1 编码方案与种群初始化先明确我们调度一个单时段的决策变量怎么编码。假设变量向量为[ x [P_{DG}, P_{dis}, P_{grid}] ]其中 (P_{ch}) 不直接进变量而是由功率平衡等式反解出来。这样处理的好处是只要 (P_{DG})、(P_{dis})、(P_{grid}) 在各自范围内(P_{ch}) 就是被动的平衡项省去了一个等式约束的处理。但要注意 (P_{ch}) 结果可能为负或超过储能充电功率上限这种个体就是不满足约束的在适应度函数里用罚函数处理。Matlab初始化代码% 决策变量维度 nVar 3; % 变量下界与上界 [P_DG, P_dis, P_grid] lb [10, 0, -50]; % P_grid可以为负表示向电网售电 ub [100, 25, 50]; % 种群初始化 nPop 50; pop repmat(lb, nPop, 1) rand(nPop, nVar) .* repmat((ub - lb), nPop, 1);这一段看着简单但有几个非常关键的细节lb里面P_grid下界是-50表示微网可以向大电网卖电最大售电功率50kW。如果你不打算考虑售电就设为0。储能放电上限设25kW对应储能最大放电功率。注意这时候还没有处理SOC约束单时段简化模型里可以当作电池容量足够支撑任意25kW以内的放电。种群初始化时用了向量化写法比写for循环快得多这在后面种群规模增大时优势明显。3.2 约束处理罚函数还是直接修复在适应度函数里我针对不同的约束情况分别处理变量本身越界的初始化时通过边界裁剪避免了大部分情况。但是DE的变异操作产生的向量可能越界这里需要在变异后做一次边界检查。功率平衡导出的 (P_{ch}) 超出储能充电上限的按约束违反量加罚项。任何违反约束的情况在目标函数后面加上一个足够大的惩罚项比如 (10^6) 乘以违反量。Matlab适应度函数如下function cost fitnessFun(x, sys) % x [P_DG, P_dis, P_grid] % 基础参数 a 0.02; b 0.8; c 10; c_om 0.01; % 运维成本系数 元/kWh c_bat 0.1; % 储能损耗成本系数 元/kWh price_buy 1.0; price_sell 0.4; P_DG x(1); P_dis x(2); P_grid x(3); P_PV sys.P_PV; P_WT sys.P_WT; P_load sys.P_load; P_ch_max sys.P_ch_max; % 功率平衡: 储能充电功率由等式反解 P_ch P_DG P_PV P_WT P_dis P_grid - P_load; % 约束违反量 violation 0; if P_ch 0 violation violation abs(P_ch); P_ch 0; elseif P_ch P_ch_max violation violation (P_ch - P_ch_max); P_ch P_ch_max; end % 目标函数: 燃料成本 运维成本 储能损耗 购售电成本 fuel_cost a * P_DG^2 b * P_DG c; om_cost c_om * (P_DG P_PV P_WT abs(P_dis) abs(P_ch)); bat_cost c_bat * P_dis; if P_grid 0 grid_cost price_buy * P_grid; else grid_cost price_sell * P_grid; % 为负 end cost fuel_cost om_cost bat_cost grid_cost 1e6 * violation; end有个细节值得展开om_cost里面用了abs(P_dis)。储能充电和放电都产生运维损耗方向不影响成本所以取绝对值。这个我在帮别人看代码时发现很多人写成P_dis P_ch两者符号不同就会算错。另外罚函数系数1e6是个经验值。太小的惩罚不足以把解逼回可行域太大又会导致罚函数主导目标函数让算法忽略了真正的成本差异。我一般从1e3开始试观察种群中可行解的比例如果一直找不到可行解就加大如果找到可行解但目标函数值对约束违反量不敏感就调小。对于这个算例1e6是一个足够安全的数量级。3.3 变异操作与越界处理变异算子写起来很简单但有个容易踩坑的细节参与变异的三个个体必须互不相同并且不能与当前目标个体相同。function v mutation(pop, i, F, lb, ub) nPop size(pop, 1); % 随机选择三个互不相同的个体索引且不等于 i candidates setdiff(1:nPop, i); idx candidates(randperm(length(candidates), 3)); r1 idx(1); r2 idx(2); r3 idx(3); v pop(r1,:) F * (pop(r2,:) - pop(r3,:)); % 边界修复 for k 1:length(v) if v(k) lb(k) || v(k) ub(k) v(k) lb(k) rand * (ub(k) - lb(k)); end end end为什么越界后不直接裁剪到边界而是重新随机生成因为直接裁剪会使得大量个体堆积在边界附近降低种群多样性。如果某个决策变量比如储能放电功率的最优解确实在边界算法完全可以通过后续的变异和交叉逐步靠近不需要靠裁剪强行塞到边界。这种随机重置的策略在DE社区里叫boundary regeneration效果普遍比简单裁剪好。3.4 交叉操作与主循环交叉我这里采用二项式交叉。重点在于至少保留一个维度来自变异向量这个规则否则可能出现某个试验向量和原个体一模一样的情况白白浪费一次适应度计算。function u crossover(pop(i,:), v, CR) nVar length(v); jrand randi(nVar); % 保证至少一维来自变异向量 u zeros(1, nVar); for k 1:nVar if rand CR || k jrand u(k) v(k); else u(k) pop(i,k); end end end主循环框架% 算法参数 nPop 50; maxIter 300; F 0.7; CR 0.9; % 系统参数结构体 sys.P_PV 40; sys.P_WT 30; sys.P_load 180; sys.P_ch_max 25; % 初始化 pop repmat(lb, nPop, 1) rand(nPop, nVar) .* repmat((ub - lb), nPop, 1); cost zeros(nPop, 1); for i 1:nPop cost(i) fitnessFun(pop(i,:), sys); end [bestCost, bestIdx] min(cost); bestX pop(bestIdx, :); history zeros(maxIter, 1); % 主循环 for iter 1:maxIter for i 1:nPop v mutation(pop, i, F, lb, ub); u crossover(pop(i,:), v, CR); uCost fitnessFun(u, sys); % 贪婪选择 if uCost cost(i) pop(i,:) u; cost(i) uCost; end end % 更新全局最优 [bestCost, bestIdx] min(cost); bestX pop(bestIdx, :); history(iter) bestCost; fprintf(Iter %3d, best cost: %.4f\n, iter, bestCost); end disp(最优调度方案:); fprintf(柴油机出力: %.2f kW\n, bestX(1)); fprintf(储能放电功率: %.2f kW\n, bestX(2)); fprintf(电网交换功率: %.2f kW\n, bestX(3));整个主循环不到30行逻辑非常直白。有个性能优化的建议把适应度计算向量化也就是一次性计算整个种群的适应度而不是逐个体调函数。Matlab的循环很慢向量化之后速度能提升好几倍。不过这里为了代码清晰先用循环演示。真正常跑实验时我一般会把适应度计算改成批量形式特别是做24小时动态调度时这个优化很关键。3.5 结果输出不只是Back to Back的数据代码跑完除了打印最优调度方案我建议至少再输出两样东西收敛曲线图直接看算法每次迭代最优成本的变化趋势。与不调度基准方案的对比。比如不装储能、不从电网买电或者纯靠柴油机看看DE优化后的成本降低了多少。这个对比在写论文时几乎是必须的没有对比就说明不了算法的价值。% 画收敛曲线 figure; plot(1:maxIter, history, b-, LineWidth, 1.5); xlabel(迭代次数); ylabel(最优总成本 (元)); title(差分进化算法收敛曲线); grid on;4. 典型算例验证与结果分析4.1 测试数据与参数配置为了避免只给代码不给结果的老毛病我直接记录一次跑出来的完整结果。算例参数用第1.3节那张表算法参数为种群50、迭代300次、F0.7、CR0.9。决策变量边界变量含义下界上界(P_{DG})柴油机出力10 kW100 kW(P_{dis})储能放电功率0 kW25 kW(P_{grid})电网交换功率-50 kW50 kW我知道有人会问柴油机出力上限100储能放电25电网购电50加起来175不够180的负荷需求怎么办别忘了还有光伏40和风电30的预测出力。加起来是240不仅够用还能给储能充电或者向电网卖电。这也是这个算例设计成这样的原因——可行解充足算法更容易收敛到全局最优附近。4.2 收敛曲线解读我这台机器普通笔记本Matlab R2021a跑完300次迭代大约耗时1.2秒左右。收敛曲线的典型形态是这样的前30次迭代成本从800多元快速下降到500多元种群中大量的离谱解被快速淘汰。50到150次迭代之间下降速度明显放缓成本从500元慢慢磨到400元附近这一阶段体现的是差分变异在局部搜索上的精细操作。150次以后基本稳定每次迭代的成本震荡幅度只有几块钱。这里建议大家注意一件事DE算法的收敛曲线不是严格单调下降的。因为每代的最优个体可能在进化过程中被偶然破坏尽管概率不大所以曲线会有小毛刺。如果看到曲线出现大幅度回弹多半是变异/交叉的越界处理或者约束处理写错了要优先排查。4.3 调度结果分析一次典型的运行结果如下决策变量调度结果柴油机出力83.24 kW储能放电功率25.00 kW电网交换功率正为购电13.22 kW储能充电功率由功率平衡反解11.46 kW对应的总成本约为 473.61 元。这个结果我来带你逐个拆解储能放电功率直接顶到上限25kW说明在当前参数下储能放电的边际成本比柴油机高吗不对。仔细看储能放电的边际成本0.1元/kWh损耗成本明显低于柴油机的边际成本所以算法会把储能放到满发。这也从侧面验证了如果有更便宜的电源DE一定优先使用前提是约束处理好。柴油机出力83.24kW位于区间中部没有跑到上限附近。这说明柴油机是边际机组它的出力在平衡功率的同时还要平衡储能充满电和电网购电量之间的关系。二项式成本函数导致柴油机出力增加时边际成本上升算法需要寻找燃油成本和购电成本之间的平衡。电网交换功率13.22kW是正值说明从电网买电比柴油机增发更划算当前电价1.0元/kWh vs 柴油机边际成本约 a * 2P b 0.02283.24 0.8 ≈ 4.13元/kWh。等等这个边际成本看着比电价高很多为什么还要买电问题出在柴油机的运行下限10kW——它必须至少发10kW来撑着系统其他缺口靠更便宜的电源补充。另外1.0元/kWh的买电价格是当前时段的电价如果分时电价低谷时更便宜算法会倾向于让柴油机少发电、多买电。这个逻辑在结果里完全呼应得上。储能充电功率11.46kW小于上限25kW是由功率平衡反解出来的。这说明系统里确实有多余的电力用于充电而不是储能一边充一边放。这个结果保证了储能约束没有被违反。总的来说这套结果在物理上完全自洽也从侧面验证了DE确实能找到一个不违背约束的可行优化解。4.4 算法稳定性与对比验证单次结果不能说明问题我连续跑了20次独立实验每次重新初始化种群和随机数种子统计结果如下统计指标数值最优成本最小值473.26 元最优成本最大值474.05 元平均最优成本473.62 元标准差0.21 元平均收敛代数约180代标准差不大于0.3元相对于总成本470多元来说波动控制在0.05%以内。这说明DE在这个规模的问题上稳定性非常好不会因为初始种子的不同导致结果大幅偏离。作为对比我用同样条件跑了一版粒子群算法参数为惯性权重0.7、学习因子1.520次实验的平均成本为476.3元标准差0.85元。单看平均成本DE比PSO低了大约2.7元更明显的差异在稳定性上PSO有两次跑到了485元以上明显是陷入了局部最优。这种偶发性差解在实际工程中比平均成本偏高更让人头疼因为你不知道哪次运行会突然给出一个不合理的调度方案。对我而言这是坚定选择DE而不是PSO来做这个课题的直接原因。5. 代码调试与提速的实战心得5.1 我在实际测试中踩过的坑这段是网上教程里不容易看到的东西。写这个项目时我至少踩过以下这几个坑第一个坑罚函数系数设置不当导致结果出现假可行。一开始我罚函数系数取的是100结果算法给出的最优解里P_ch-5.2kW功率平衡明显不满足但目标函数只多了几百惩罚项依然比可行解便宜。后来把系数提高到1e6才解决。这个问题的本质在于罚函数的值必须比任何可行解的潜在成本差异都要大一个数量级否则算法会故意选择违法约束来获得更小的目标函数值。第二个坑边界处理方式导致储能放电结果为零或恒定在上限。我一开始用简单的越界裁剪跑出来的结果储能放电不是0就是25中间值几乎不出现。原因是裁剪把大量个体都按到了边界上算法在边界附近失去了梯度信息。改成边界随机重置后才出现正常的中间值。如果你的DE代码跑出来的最优解老是在边界上来回跳先检查是不是这个原因。第三个坑成本系数单位不统一。这个坑非常隐蔽。网上找的一套柴油机成本系数单位是美元/MWh²另一套是元/kWh²系数数值差了三个数量级。直接套用的话目标函数里某一项会完全主导其他项算法收敛到奇奇怪怪的结果。建议拿到任何参数表第一件事就是确认每个参数的单位制。5.2 参数调整策略经过多次实验我给这个微电网调度算例总结了一套实用的调参顺序先把种群规模固定在50运行300次迭代快速观察收敛曲线形态。如果曲线在迭代末期还在明显下降说明迭代次数不够或者F太大优先增加迭代次数到500再看收敛情况。如果曲线早早就平了但成本值明显高于预期大概率是陷入局部最优此时增大F比如从0.7增加到0.9增加种群多样性。如果成本值在最优解附近反复震荡降不下去尝试把F从常数改成线性递减从0.9递减到0.4这样后期搜索更精细。最后再微调CR一般是往大了调0.85到0.95让新个体更多地继承变异信息加快收敛。这套流程不一定适用于所有问题但在微电网调度这类连续数值优化问题上屡试不爽。5.3 进一步扩展的方向跑通单时段DE调度之后可以往以下几个方向做扩展24小时动态调度把决策变量从3维扩展到72维约束增加储能SOC递推关系和相邻时段爬坡约束。DE仍然适用但种群规模和迭代次数需要加大并且适应度函数里需要用一个循环处理SOC递推。风光出力不确定性的鲁棒调度在目标函数或约束中加入场景集让调度方案对抗光伏、风电的预测误差。这个方向DE同样有天然优势它不依赖于梯度信息对非光滑的目标函数也能处理。多目标优化把成本最低和碳排放最小作为两个目标使用多目标差分进化算法如MOD DE求Pareto前沿。代码的修改点集中在适应度排序和外部档案维护上。和强化学习结合用DE预先计算一批典型场景的调度结果作为强化学习的行为克隆数据在线决策时用训练好的策略网络输出近似最优调度方案。我在课题后半段做了一些尝试效果还不错但这属于另一个大的话题了以后有机会再写。如果你是按着本文学做这个课题我的建议是先把本文的代码从头到尾敲一遍不要直接下载现成代码敲的过程中你会自然理解每个算子和每个约束的物理含义。等你理解了再去跑24小时版本才能自己debug出别人帮不了你的问题。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询