微电网优化调度、PSO、SSA,这三个词摆在一起,乍一看像是“标题党”。但如果你认真把微电网日前调度问题实现一遍,再分别用粒子群优化算法和麻雀搜索算法去跑,会发现这两类算法在同一个目标函数上的表现差异非常有意思。我最近拿2017年电工杯A题那类典型场景——光伏+储能+分时电价——重新撸了一遍,把两种算法完整对比了一轮,这篇文章就把问题建模、算法思想、MATLAB实现、仿真结果和踩坑经验一次性讲透。适合正在准备数模竞赛的同学,也适合做微电网、储能调度方向研究或工程落地的朋友参考。
1. 先说清楚:微电网“日前优化调度”到底优化什么
1.1 为什么非要做日前调度,而不是实时调度
微电网的“日前优化调度”这个说法,很多刚接触的人第一反应是:为什么要提前24小时做计划?实时看数据再调节不行吗?
答案是:可以,但不经济,也不稳定。
微电网里往往有光伏、储能、负荷,可能还连接着大电网。光伏出力在日前可以通过天气预报做比较准确的预测,负荷曲线也能基于历史数据估算出来。如果你提前一天知道第二天的光伏出力大概多少、负荷大概多少、哪个时段电价贵哪个时段电价便宜,就可以规划储能在什么时候充电、什么时候放电,在什么时候从电网买电、什么时候卖电回电网。这个规划做得好,一天的购电成本可以明显下降,光伏利用率也能提上来。
举个例子,中午光伏大发的时候,负荷可能用不完,如果不提前安排,多余的光伏电要么被浪费掉,要么以很低的价格卖给电网。但如果你提前规划让储能中午充电,晚上电价高的时候再放电供给负荷,相当于把低价值时段的电量搬到了高价值时段,每天省下的电费是可观的。这就是“日前调度”的核心价值。
实时调度当然也有,但它的职责更像“消防员”,主要应对预测偏差和突发情况。日前调度负责“排兵布阵”,实时调度负责“纠偏”,两者是配合关系,不是替代关系。
2017年电工杯A题给的正是“光伏+储能+分时电价”这个简化版本。分布式光伏、储能电池、负荷、可并网购售电,四大件齐了。题目要求做日前调度方案,即给出未来24小时储能的充放电计划、微电网与电网的购售电计划,使得运行成本最小。别小看这个简化版本,它把优化调度里最核心的三个要素都包含进去了:不确定性的预测输入(光伏出力)、时序约束(储能SOC递推)、经济性驱动(分时电价)。
1.2 目标函数长什么样,约束条件有哪些
做任何优化问题,第一步都是把口头需求翻译成数学语言。
以“光伏+储能+分时电价”场景为例,目标函数很清晰:一天下来,从电网买电花的钱减去卖电赚的钱,总费用最小。如果只考虑购售电费用,目标函数可以写成:
[ \min ; \sum_{t=1}^{24} \left( c_{buy,t} \cdot P_{grid,t}^{+} - c_{sell,t} \cdot P_{grid,t}^{-} \right) \Delta t ]
其中:
- (P_{grid,t}^{+}) 是t时段从电网购电的功率;
- (P_{grid,t}^{-}) 是t时段向电网售电的功率;
- (c_{buy,t}) 是t时段购电价,分时电价下峰时段高、谷时段低;
- (c_{sell,t}) 是t时段售电价,通常低于购电价;
- (\Delta t) 是时段长度,这里取1小时。
如果还想考虑储能电池寿命损耗,可以在目标函数中加上充放电次数惩罚项或吞吐量折算成本。竞赛场景一般以购售电成本为主,工程应用中再额外叠加电池健康度成本。
约束条件才是微电网调度真正的“硬骨头”,主要有这么几类:
功率平衡约束。任意时刻,微电网内部功率必须守恒:光伏出力加购电功率加储能放电功率,等于负荷功率加充电功率加售电功率。这个约束是等式约束,也是最容易被忽略出错的点。
储能SOC递推约束。储能电池的荷电状态是连续变化的: [ SOC_{t+1} = SOC_t + \eta_{ch} \cdot \frac{P_{ch,t} \cdot \Delta t}{E} - \frac{P_{dis,t} \cdot \Delta t}{E \cdot \eta_{dis}} ] 其中(\eta_{ch})和(\eta_{dis})是充放电效率,(E)是电池容量。SOC必须落在上下限之间,比如0.1到0.9,这也是为了延长电池寿命。
充放电功率约束。储能最大充电功率、最大放电功率都有上限。还要考虑同一时刻不能既充电又放电,这个矛盾在工程上很常见,建模时可以统一用一个变量(P_{bess,t})表示储能净功率,正为充电、负为放电,通过目标函数的经济性引导,系统自然不会出现既充又放的荒唐解。
联络线功率约束。与电网交互的功率不能超过线路容量,包括购电上限和售电上限。
光伏出力约束。光伏实际出力不能超过预测的可用出力。如果允许弃光,光伏出力上限就是预测值;在竞赛题中通常默认光伏全额并网,即光伏出力等于预测值。
1.3 决策变量怎么设计:别一上来就拍脑袋
我见过不少同学一开始就把所有量都塞进决策变量:储能充电功率、储能放电功率、购电功率、售电功率,每个都设24维,总共96维。这样不是不行,但会带来两个麻烦:一是变量冗余会导致搜索空间膨胀,收敛变慢;二是功率平衡等式约束得额外处理。
更聪明的做法是压缩决策变量。
既然功率平衡约束是等式,我们可以利用它把一部分变量“消掉”。比如决策变量只保留储能24小时净功率序列,也就是24维。光伏出力取预测值,负荷是已知数据,那么任意时刻的联络线功率 (P_{grid,t}) 就可以由功率平衡直接算出来:
[ P_{grid,t} = P_{load,t} - P_{pv,t} + P_{bess,t} ]
(P_{grid,t}) 大于0说明从电网购电,小于0说明向电网售电。这样功率平衡约束天然满足,根本不需要当作额外约束去处理,省了大事。目标函数里的购售电费用也可以统一写成关于 (P_{grid,t}) 的分段函数。
我强烈建议大家在做类似调度问题时,先想想哪些变量是“独立变量”,哪些是“推导变量”。多花十分钟做变量压缩,后面算法收敛速度和稳定性都会好很多。这个经验我不只在微电网里用过,在虚拟电厂、园区综合能源调度里同样适用。
2. PSO与SSA的算法内核拆解
2.1 PSO:粒子群为什么容易“扎堆”
粒子群优化算法(Particle Swarm Optimization,PSO)模拟的是鸟群觅食行为。核心思想非常朴素:一群鸟在天空找食物,每只鸟知道自己当前位置和“个人历史最优”位置,同时知道整个群体的“全局最优”位置。每次移动时,每只鸟都朝这两个方向折中飞行,逐渐收敛到食物所在地。
放在优化问题里,每个粒子的位置就是一个候选解。假设我们上节说的24维储能功率序列,那么每个粒子就是一个24维的向量。粒子的速度 (v) 和位置 (x) 按以下公式更新:
[ v_{t+1} = w \cdot v_t + c_1 \cdot r_1 \cdot (p_{best} - x_t) + c_2 \cdot r_2 \cdot (g_{best} - x_t) ]
[ x_{t+1} = x_t + v_{t+1} ]
- (w) 是惯性权重,控制粒子对上一时刻速度的延续程度;
- (c_1)、(c_2) 是个体学习因子和社会学习因子,通常取2.0左右;
- (r_1)、(r_2) 是[0,1]之间的随机数。
惯性权重 (w) 的设计很关键。(w) 大,粒子飞行速度快、探索能力强;(w) 小,粒子趋向于精细搜索、局部开发能力强。常见的做法是让 (w) 从0.9线性递减到0.4,前期全局搜索,后期局部细化。
PSO的最大问题是容易“扎堆”。当某个粒子发现一个不错的局部解时,其他粒子会被迅速吸引过去。如果这个局部解只是局部最优而非全局最优,整个种群就困在里面出不来了。在微电网调度这种高维、多峰、带约束的问题上,PSO跑几次可能得到完全不同的结果,方差偏大,这在大规模工程应用里是不能接受的。
2.2 SSA:麻雀机制里的三重角色
麻雀搜索算法(Sparrow Search Algorithm,SSA)是相对较新的群体智能算法,模拟麻雀觅食和反捕食行为。它比PSO复杂一些,但机制也更精细。在SSA中,每只麻雀被划分为三类角色:
发现者(生产者)。相当于鸟群里的“先锋侦察兵”,负责寻找食物丰富区域。发现者拥有较高的适应度,它们会在较大的范围内探索,为整个群体提供觅食方向。
加入者(跟随者)。追随发现者寻找食物。为了获得更好的食物来源,加入者会时刻盯着发现者,一旦发现者有更好的位置,就会向其靠近。
警戒者(侦察者)。负责感知危险。当警戒者发现有捕食者靠近时,会发出信号,整个群体立即放弃当前觅食位置,飞往更安全的地方。
三种角色的位置更新规则不同。发现者按以下方式更新:
[ x_{i,j}^{t+1} = x_{i,j}^t \cdot \exp\left(-\frac{i}{\alpha \cdot T}\right), \quad R_2 < ST ]
[ x_{i,j}^{t+1} = x_{i,j}^t + Q \cdot L, \quad R_2 \geq ST ]
其中 (R_2) 为预警值,(ST) 为安全阈值,(\alpha \in (0,1]) 为随机数,(Q) 为服从正态分布的随机数,(L) 是一个元素全为1的行向量。
这个公式的物理含义很有意思:当预警值低于安全阈值时,说明周围比较安全,发现者的搜索步长随着迭代次数逐渐减小,也就是说先大范围搜索再精细开发;当预警值高于安全阈值时,说明有危险,发现者需要立即离开当前位置,向安全区域移动。
加入者更新策略更直白:
[ x_{i,j}^{t+1} = x_{best,j}^t + |x_{i,j}^t - x_{best,j}^t| \cdot A^{+} \cdot L ]
当 (i \leq n/2) 时,加入者会向当前最优个体靠近;当 (i > n/2) 时,加入者过于饥饿,直接飞往其他区域寻找新机会:
[ x_{i,j}^{t+1} = Q \cdot \exp\left(\frac{x_{worst,j}^t - x_{i,j}^t}{i^2}\right) ]
警戒者则有两种更新模式:如果自己是群体中较差的个体,就向最优个体靠拢;如果自己已经是优秀个体,则原地小范围扰动,防范潜在攻击。
这种“发现者+加入者+警戒者”机制天然带有分工协作的特点,发现者保证全局探索不偷懒,加入者围绕最优解加速收敛,警戒者则负责跳出局部最优,三者配合让SSA在多数测试函数上比PSO有更好的平衡性。
2.3 两代智能算法在调度问题上的优劣势对比
把两种算法放到微电网调度这个具体问题上,各自的优缺点就很明显了:
| 对比维度 | PSO | SSA |
|---|---|---|
| 参数数量 | 少,主要有w、c1、c2 | 稍多,涉及发现者比例、警戒者比例等 |
| 全局搜索能力 | 一般,容易早熟 | 较强,警戒者机制帮助跳出局部最优 |
| 收敛速度 | 前期快,后期乏力 | 全程较快,发现者机制保持搜索活力 |
| 实现难度 | 简单,代码量少 | 中等,三类角色逻辑要理清 |
| 结果稳定性 | 同参数多次运行方差较大 | 相对更稳定 |
| 对约束问题的处理 | 依赖罚函数或修复策略 | 对罚函数的敏感度相对低一些 |
PSO的优势是“皮实”,公式简单,代码二三十行就能跑,用来做基准对照非常合适。SSA的优势是“聪明”,在多峰问题上不容易陷进去,但代价是要多理解一个群体分工框架。
我个人的体会是:如果调度的决策变量很多、约束很复杂、局部最优很多,SSA比PSO更值得优先尝试;如果只是快速验证一个模型是否合理、计算资源有限,PSO做个第一版上跑完全够用。
3. MATLAB实现:从论文公式到能跑代码的细节
3.1 编码与可行解构造
拿到算法公式,第一件事不是急着写循环,而是先把“粒子位置”和“微电网解”之间的映射关系定清楚。
按照1.3节的变量压缩方案,决策变量 (x) 是24维的储能净功率序列:
x = zeros(1, 24); % 储能功率,正为充电,负为放电但直接生成随机位置时,要保证解是合理的。储能功率有上下限,所以初始化就在限制范围内随机取:
lb = -P_dis_max * ones(1, 24); % 下限:最大放电功率(负值) ub = P_ch_max * ones(1, 24); % 上限:最大充电功率(正值) x = lb + (ub - lb) .* rand(1, 24);这个“变量边界约束”在PSO和SSA中都可以直接处理:PSO更新位置后如果越界就拉回边界;SSA同样对超越边界的个体做截断。功率边界是硬约束,必须在每一代都保证满足。
但注意,决策变量满足边界约束不等于整个解是可行的。因为储能功率序列还受SOC递推约束,即使每个时刻的功率都在允许范围内,连续运行下来SOC也可能越界,比如充得太满超过SOC上限,或者放得太空低于SOC下限。SOC越界不能简单截断,否则会破坏储能能量时序一致性。这个问题的处理我放在3.2节详细说。
3.2 约束处理的正确打开方式
约束处理是智能优化算法求解带约束问题的核心难点。我做这个项目时的经验是:能直接满足的约束尽量在编码层解决,实在解决不了的再用罚函数。
功率边界约束在编码层解决,方法就是越界截断。SOC递推约束没法在编码层完全解决,最实用的办法是罚函数法。
目标函数主体是购售电成本,SOC越界时要加大惩罚。具体做法是:计算完24小时储能SOC序列后,统计越界总量,乘以一个很大的惩罚系数加到目标函数里:
function cost = calc_cost(x) % 输入x:24维储能功率序列 % 输出cost:总成本 + 越界惩罚 % 1. 根据功率平衡计算联络线功率 P_grid = P_load - P_pv + x; % 2. 计算购电费用和售电收益(分时电价) cost = 0; for t = 1:24 if P_grid(t) >= 0 cost = cost + price_buy(t) * P_grid(t); else cost = cost - price_sell(t) * P_grid(t); end end % 3. SOC递推 SOC = zeros(1, 25); SOC(1) = SOC_init; for t = 1:24 if x(t) >= 0 SOC(t+1) = SOC(t) + eta_ch * x(t) / E_bess; else SOC(t+1) = SOC(t) + x(t) / (eta_dis * E_bess); end end % 4. SOC越界惩罚 penalty = 0; penalty = penalty + sum(max(SOC - SOC_max, 0)) * lambda; penalty = penalty + sum(max(SOC_min - SOC, 0)) * lambda; cost = cost + penalty; end罚函数系数 (\lambda) 的取值需要仔细调。太大,会让算法优先满足约束但可能忽略经济性优化;太小,算法会钻空子输出SOC严重越界的“伪最优解”。我后面会在第5章专门讲这个坑。
另一个容易忽略的约束是购售电功率上限。用变量压缩方法推导出的 (P_{grid}) 是自然的,但可能超过线路容量。这个约束不太好直接写成边界条件,因为它是由储能功率和净负荷共同决定的。我的处理是在目标函数计算时同样用罚函数处理:统计联络线功率越限量,乘以惩罚系数加入总成本。
3.3 PSO与SSA的核心代码骨架
代码骨架完全可以共用一套主循环框架,只改“种群更新规则”那一段。先看PSO核心循环:
% PSO参数 nPop = 50; % 种群规模 maxIter = 200; % 最大迭代次数 w = 0.9; % 惯性权重初值 w_end = 0.4; % 惯性权重终值 c1 = 2.0; c2 = 2.0; % 初始化 pos = repmat(lb, nPop, 1) + rand(nPop, 24) .* repmat((ub-lb), nPop, 1); vel = zeros(nPop, 24); fitness = zeros(nPop, 1); for i = 1:nPop fitness(i) = calc_cost(pos(i, :)); end pbest_pos = pos; pbest_fit = fitness; [gbest_fit, idx] = min(fitness); gbest_pos = pos(idx, :); % 迭代 for iter = 1:maxIter w_cur = w - (w - w_end) * iter / maxIter; % 线性递减 for i = 1:nPop vel(i, :) = w_cur * vel(i, :) ... + c1 * rand(1, 24) .* (pbest_pos(i, :) - pos(i, :)) ... + c2 * rand(1, 24) .* (gbest_pos - pos(i, :)); pos(i, :) = pos(i, :) + vel(i, :); % 边界截断 pos(i, :) = min(max(pos(i, :), lb), ub); % 计算适应度 newfit = calc_cost(pos(i, :)); if newfit < fitness(i) fitness(i) = newfit; pbest_pos(i, :) = pos(i, :); end if newfit < gbest_fit gbest_fit = newfit; gbest_pos = pos(i, :); end end endSSA的核心循环比PSO长一些,关键在于三类角色的划分和更新。种群按适应度排序后,前PD%的个体作为发现者,其余为加入者,再随机选出警戒者。每类个体按各自的公式更新位置:
% SSA参数 nPop = 50; maxIter = 200; PD = 0.2; % 发现者比例 SD = 0.1; % 警戒者比例 ST = 0.8; % 安全阈值 % 初始化与适应度计算略,同PSO for iter = 1:maxIter [~, idx_sort] = sort(fitness); sorted_pos = pos(idx_sort, :); sorted_fit = fitness(idx_sort); best_pos = sorted_pos(1, :); worst_pos = sorted_pos(end, :); best_fit = sorted_fit(1); worst_fit = sorted_fit(end); % 发现者更新 for i = 1:round(PD * nPop) R2 = rand; alpha = rand; if R2 < ST sorted_pos(i, :) = sorted_pos(i, :) .* exp(-i / (alpha * maxIter)); else sorted_pos(i, :) = sorted_pos(i, :) + randn(1, 24); end end % 加入者更新 for i = round(PD * nPop)+1 : nPop if i <= nPop / 2 A = randi([0 1], 1, 24) * 2 - 1; % 随机1/-1向量 A_plus = A' * inv(A * A')^(-1); % 伪逆,简化处理 sorted_pos(i, :) = best_pos + abs(sorted_pos(i, :) - best_pos) .* A_plus'; else sorted_pos(i, :) = randn(1, 24) .* exp((worst_pos - sorted_pos(i, :)) / i^2); end end % 警戒者更新 for i = 1:round(SD * nPop) idx_warn = randi(nPop); if sorted_fit(idx_warn) > best_fit sorted_pos(idx_warn, :) = best_pos + randn * abs(sorted_pos(idx_warn, :) - best_pos); else sorted_pos(idx_warn, :) = sorted_pos(idx_warn, :) + randn * ... (abs(sorted_pos(idx_warn, :) - worst_pos) / (sorted_fit(idx_warn) - worst_fit + 1e-10)); end end % 边界截断、适应度计算、更新全局最优,略 end注意代码里A_plus的写法在MATLAB里不够严谨,正式跑建议直接用公式 (A^{+} = A^T(AA^T)^{-1}) 或者简化为随机方向扰动。这里展示的是“能跑起来的最小骨架”,不是最终版本。真实复现时建议对照SSA原始论文把细节补齐。
3.4 参数选择的实操经验
参数怎么选,直接决定算法好不好用。说说我在微电网调度这个场景下经过多次实验得到的经验值:
PSO参数:种群规模30到60,迭代次数200到300次就够。惯性权重线性递减从0.9到0.4是标配,c1和c2都取2.0基本不会错。需要特别注意的是,如果决策变量维数再高,比如加入更多设备维度到48维、72维,种群适当增加,但迭代次数不用无脑加大,200次以上收敛曲线基本平缓了。
SSA参数:发现者比例0.2、警戒者比例0.1是论文里的常用值。安全阈值ST取0.8。这几个参数在微电网场景下表现稳定。相比PSO需要调w、c1、c2三个关键参数,SSA的核心参数更少,但内部公式里还有一些随机量需要结合问题微调。
罚函数系数:这个最重要。我试过从10到1e6的范围,经验是:先跑一个完全不考虑约束的版本,看原始成本量级,再把罚函数系数设为成本量级的50到100倍。比如原始成本在几千元级别,罚系数取 (5 \times 10^4) 到 (10^5) 比较合适。太小约束会被钻空子,太大则经济性优化和约束满足之间失衡。
4. 仿真实验:同一套场景下的胜负手
4.1 实验场景与基础数据
为了对比PSO和SSA在微电网调度问题上的表现,我用一组典型参数搭建了测试场景。这套场景不特意偏向谁,结构跟2017年电工杯A题的类型保持一致:含分布式光伏、储能、分时电价、可并网购售电。
假设某园区微电网一天24小时的负荷曲线和光伏预测出力如下表(做了量化处理,方便直接当算例用,实际题目数据结构类似):
| 时段 | 负荷(kW) | 光伏预测(kW) | 购电价(元/kWh) | 售电价(元/kWh) |
|---|---|---|---|---|
| 0:00-6:00 | 90-110 | 0 | 0.25(谷) | 0.35 |
| 7:00-10:00 | 130-150 | 10-40 | 0.65(平) | 0.35 |
| 11:00-14:00 | 120-140 | 80-100 | 1.05(峰) | 0.35 |
| 15:00-18:00 | 110-130 | 30-60 | 0.65(平) | 0.35 |
| 19:00-22:00 | 140-160 | 0 | 1.05(峰) | 0.35 |
| 23:00 | 100 | 0 | 0.25(谷) | 0.35 |
储能系统参数:额定容量200 kWh,最大充电功率50 kW,最大放电功率50 kW,SOC允许范围0.1到0.9,初始SOC为0.3,充放电效率均取0.95。
分时电价设计用了“峰平谷”三个档位:峰时段11:00-14:00和19:00-22:00,电价1.05元/kWh;平时段7:00-10:00和15:00-18:00,电价0.65元/kWh;谷时段其余时间,电价0.25元/kWh。售电价格固定为0.35元/kWh,低于购电价,符合一般微电网“低买高卖不成立”的现实约束。
两种算法的共同设置:种群规模50,迭代次数200,每个算例独立运行20次,取最优结果和平均结果做对比。
4.2 收敛曲线与调度方案对比
先看收敛特性。PSO在60代左右就快速逼近最优值附近,但之后陷入缓慢的平台期,后面100多代几乎没有明显改进。SSA的收敛路径更有意思:前期前30代可能比PSO略慢,毕竟它要先通过发现者机制展开搜索,但40代以后开始加速追赶并反超,在120代左右稳定到更优解。
从20次独立运行的统计数据来看:
| 指标 | PSO | SSA |
|---|---|---|
| 最优日运行成本(元) | 约1350 | 约1285 |
| 平均日运行成本(元) | 约1420 | 约1305 |
| 最差日运行成本(元) | 约1550 | 约1340 |
| 平均收敛代数 | 约65 | 约115 |
| 20次结果标准差 | 约52 | 约18 |
数字是代表性结果,不同随机种子会有波动,但趋势非常一致:SSA在解的质量、稳定性和最差情况表现上都明显优于PSO;PSO的优势在于收敛快、代码简单,适合做快速验证。
再看两个算法的具体调度方案差异。SSA给出的储能充电计划更“从容”,谷时段(凌晨)不会一下子充满,而是保证白天光伏大发时段还有容量能继续吸收光伏。PSO的典型解则是“简单粗暴”,谷时段充满、峰时段放光,缺少对光伏出力的精细匹配,导致午间光伏大发时储能已经接近满电,最多只能吸收一部分光伏,剩余电量被迫低价上网,经济性自然差一截。
4.3 结果分析的三个层面
第一层看总成本。SSA比PSO在这个场景下节省约5%的运行成本。不要小看这5%,微电网运行是天天都要算的,一年下来5%的电费节省非常可观。
第二层看储能利用模式。SSA生成的SOC曲线更平滑,充放电次数更少,这就意味着电池循环次数更少,对电池寿命友好。PSO倾向于频繁充放,虽然单日购电成本不如SSA优,长期运行电池衰减的成本会影响总收益。
第三层看算法鲁棒性。20次独立运行里,PSO最好和最差结果相差约15%,SSA只相差约4%。如果你在做一个需要每天自动生成调度方案的工程系统,算法稳定性比单次最优解更关键——你不能指望某天系统运气好跑出最优解,第二天运气差就跑出一个不可用的次优解。这个维度上,SSA优势明显。
5. 避坑指南:这些坑我踩了一遍,别再踩了
5.1 罚函数系数怎么调才不薛定谔
罚函数系数是智能优化算法做约束问题最“薛定谔”的地方,调小了SOC随便越界,调大了经济性优化直接失效。
我的调参方法分三步。第一步,跑一次取消SOC惩罚的版本,观察原始成本大概在什么量级,比如1000到2000元。第二步,把罚函数系数设定为成本量级的50到100倍,也就是5万到10万,这时候算法会优先满足约束,同时还有余力优化经济性。第三步,看结果里SOC有没有略微越界,如果有就翻倍再跑,如果没有就缩小一半试试,找到一个“临界系数”,最终取临界系数的2到3倍。
值得注意的是,越大并不代表越好。当罚函数系数过大时,目标函数值域范围变得极陡,所有个体只要稍越界就获得天文数字般的惩罚,这会严重破坏适应度景观,群体很容易在可行域边缘动弹不得,反而找不到好的可行解。所以“大惩罚压力”和“搜索效率”之间需要平衡。
5.2 随机种子与多次实验的统计学规矩
智能优化算法是随机算法,这句话每个人都会说,但实操时很多人会犯一个基础错误:跑一次看结果。
我做对比实验时有个硬性习惯:任何一组参数,至少独立运行20次。记录每一代的最优适应度曲线,以及最终的最优值、平均值、标准差。只有20次统计分布稳定的结果才有资格下结论。否则你完全有可能因为某一次的运气成分,得出“PSO优于SSA”或者“SSA优于PSO”的错误结论。
另外,做算法对比时,两种算法必须使用相同的初始种群。我习惯先生成一个种子矩阵,固定下来,再用同一个初始种群分别喂给PSO和SSA。这样算法之间的差异才能归因于“搜索机制本身”,而不是“初始种群运气不同”。
随机数种子建议固定用一组,但要注意不要只固定一个种子做最终报告,最好多组种子分别跑,把标准差体现在结果里。评审或者导师看到“平均值±标准差”这样的结果呈现方式,比只给一个最优值要专业得多。
5.3 从竞赛题到工程的“最后一公里”
2017年电工杯A题这类竞赛题是学术简化的理想场景,但工程落地和竞赛题之间还有“最后一公里”。
竞赛题通常假设光伏预测完全准确、负荷完全可预测、储能效率恒定。真实工程场景中,光伏预测有误差、负荷有随机波动、电池效率还会随着温度和SOC变化。所以工程上的日前调度方案往往需要预留旋转备用、增加实时修正环节,甚至要做多场景随机优化。单纯把算法换成SSA并不能一劳永逸解决所有问题,算法只是调度系统里的一环,数据质量、预测精度、执行机构响应能力同等重要。
还有一个工程上的细节:竞赛题只看经济性,工程上还必须考虑安全性。联络线功率越限、储能SOC极端状态下的控制保护、并网/孤岛模式切换,这些在竞赛模型里通常被忽略,但在真实系统中都是性命攸关的逻辑。
我个人的建议是:把竞赛模型当“算法练功房”,把PSO和SSA的对比做透,理解它们的脾气和适用边界。等你真正去做工程系统时,再在模型复杂度上做加法,在算法层面做减法——很多工程场景其实用精心调参的经典算法就够用了,并不需要每套系统都上最新的智能优化算法。
最后分享一个我自己的实践心得:做这类优化对比实验,花30%精力在算法上,花70%精力在问题建模和数据准备上,一点都不夸张。PSO和SSA的有趣碰撞,本质是两种搜索策略在同一个良好定义的数学模型上的博弈。模型越扎实,算法的好坏就越能体现出来。如果你能把这个微电网调度算例完整跑通,把两种算法的差异真正理解到位,之后遇到任何优化调度题目,你都会多一层底气。