ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

含碳捕集微网多时间尺度低碳调度:改进粒子群算法与Matlab实现

含碳捕集微网多时间尺度低碳调度:改进粒子群算法与Matlab实现 基于改进粒子群算法的含碳捕集微网多时间尺度低碳经济调度Matlab代码实现做微网调度的人应该都有感受传统经济调度模型已经讲烂了但把碳捕集装置和微网结合起来做多时间尺度优化参考代码少得可怜。尤其是碳捕集装置这玩意儿——它本身要耗电捕集出来的CO2又可以被电转气利用整个能量流关系比单纯风电储能燃气轮机的模型复杂得多。之前我项目需要做含碳捕集的微网日前-日内-实时调度找遍了各个平台要么是纯理论推导没有落地代码要么是简化到只剩一个碳捕集率公式。后来我基于Matlab自己搭了一套改进粒子群算法的求解框架今天把这套思路完整拆开讲清楚从模型结构、算法改进、代码实现到调参经验尽量讲明白每一个为什么这么做。1. 含碳捕集微网调度的问题本质不只是省电费是钱的综合账1.1 碳捕集装置在微网里到底扮演什么角色微网里的电源通常包括风电、光伏、燃气轮机、储能有些还带燃料电池。绝大多数文献在做低碳调度时只是给燃气轮机的碳排放加一个碳价系数算进目标函数里就完事了。但真正的碳捕集微网核心区别在于多了一套CCS装置Carbon Capture System碳捕集系统。这套装置可不像加个系数那么简单它有明确的物理行为吸收烟气中的CO2贫液富液循环、再生塔加热解析每一步都要消耗能量。在微网模型里CCS的能耗通常建模成与捕集到的CO2量成线性或二次关系这直接影响了微网内部的电力平衡——上一时刻的可再生出力本来可以供给负荷现在得拿出一部分给CCS用。另一个非常关键的点是碳捕集与固定源燃气轮机和灵活源风电光伏之间的耦合关系。燃气轮机烧天然气发电排放CO2CCS把这些CO2捕集下来一部分可以送去P2G电转气装置生成天然气再回补气网另一部分封存。于是燃气轮机的净碳排放量就变成了总排放量 - 捕集量而捕集量又取决于CCS的能耗和运行状态。这就是一个源端排放-捕集端消纳-负荷端用电三向耦合的环不是简单地在目标函数里扣一笔钱就能正确处理的时间耦合与功率耦合问题。1.2 为什么不能只用传统PSO直接硬解刚开始我的想法很简单目标函数就是运行成本加碳交易成本这不就是一个带约束的非线性优化问题吗直接用标准粒子群算法套上去不就行了。实践下来很快就发现问题了——标准PSO几十次迭代之后粒子多样性急剧下降整个种群往一个局部最优死胡同里挤。尤其是当模型里带储能SOC、碳捕集设备爬坡约束、以及24小时的日前调度变量耦合在一起时决策变量维度常常超过200维标准PSO压根搜不动这种大规模带强约束的优化问题。后来我意识到含碳捕集微网调度优化本质是一个非常典型的多约束、高维非线性优化问题。约束分好几层功率平衡约束是等式约束机组出力上下限是盒式约束储能SOC、CCS运行区间是动态约束而且不同时间尺度的调度计划之间还存在递进关系——日前计划执行得准不准直接决定日内更新的调整量大小。如果算法没有妥善处理这些约束比如乱给一版乱糟糟的燃气轮机出力和CCS能耗序列粒子适应度虽然很低但其实现实中完全不可行。所以问题其实分成了两个层面第一模型层面要做多时间尺度分层架构避免把24小时所有决策一次性求解第二算法层面必须针对约束高维特性做改进否则PSO就是个摆设。2. 多时间尺度调度框架日前-日内-实时三层怎么衔接2.1 日前计划层的建模变量与目标多时间尺度调度的思路是分层次滚动修正这个思路在传统电网调度中已经很成熟微网同样可以套用。我采用的是经典的三层架构日前调度Day-Ahead、日内滚动Intra-Day、实时调整Real-Time。每一层的时间分辨率和决策变量都不太一样。日前层是24小时的全局优化时间尺度取1小时决策变量包括各时段燃气轮机的启停状态与出力、储能充放电功率、与主网的交互功率、CCS的捕集能耗及捕集到的CO2量、P2G产气量等。日前层对应的主要数据是日前预测的风电、光伏出力和负荷曲线预测误差相对大所以只需要做到全局经济性最优。日前优化对应的目标函数我是这样设置的目标 购电成本 燃气轮机燃料成本 储能充放电老化折算成本 碳交易成本 - 售电收益其中碳交易成本和碳捕集的耦合非常关键公式形如实际碳排放量 燃气轮机总排放量 - 捕集量不考虑封存途径时碳交易成本 碳价 ×实际排放量 - 免费配额免费配额一般给到微网的基准排放量如果实际排放低于配额碳指标可以卖给碳市场赚钱。这个机制带来的联动效应是CCS耗电虽然增加了购电成本但减少了碳交易成本等于用电能买碳排放权。到底划算不划算完全取决于当地的碳价和实时电价。如果碳价低而电价高可能少开CCS更合算算法要把这笔账算明白。这种经济权衡本质上是一个混合整数非线性规划问题——因为有启停状态这种0/1变量——这也是为什么很多人用遗传算法或粒子群来做而不用纯线性规划。2.2 日内滚动层与实时反馈层的作用日内层的时间尺度取15分钟每4小时为一个滚动窗口采用模型预测控制MPC的思想。每15分钟根据最新的超短期预测数据未来4小时修正日前计划。这里要特别注意日内层不需要重新求解全天的变量只需要对日前计划里后续时段的出力计划做增量修正。修正的幅度不能太大否则会破坏日前计划的经济性所以我在目标函数里加了计划偏差惩罚项日内出力与日前计划的差值平方和乘以惩罚系数。这相当于把经济性目标与计划一致性目标做了折中。实时层处理的是秒级到分钟级的功率波动。微网一般在并网模式下实时层更多只是对储能和CCS的瞬时出力做小范围调整频率控制在秒级我这套代码没有单独建立实时层的优化模型而是用决策变量的鲁棒保留裕量来近似处理——在日前和日内调度里为储能和燃气轮机预留5%的调节裕度。这样可以避免实时层建模过于复杂。如果你是做实际工程项目建议在Simulink里搭一个PCC点频率控制器来处理秒级波动但那是另一个话题了。三层的衔接逻辑在代码实现中必须有一条清晰的数据链日前层输出次日的燃气轮机出力和储能SOC参考轨迹日内层把这组轨迹当作参考基准在滚动优化中跟踪实时层只在日内结果基础上做极小范围的资源再分配。跟着这条链走整个程序的可读性和可维护性会好很多。3. 改进粒子群算法的三个关键改进点惯性权重、种群变异、约束修正3.1 从标准PSO说起它到底哪里不够用标准PSO的迭代公式大家都比较熟悉v w × v c1 × r1 × (pbest - x) c2 × r2 × (gbest - x) x x v核心思想是每个粒子根据自身最优位置和全局最优位置来更新速度从而搜索解空间。标准PSO最大的问题是早熟收敛——一旦某个粒子找到了一个局部较优的位置由于gbest对全体粒子的牵引力很大群体很容易被吸过去失去探索其他区域的能力。另一个问题是算法对参数w, c1, c2很敏感同一个问题调好的参数换一个算例就不一定好使。在含CCS微网调度这个场景这两个问题都被放大了。因为适应度函数里包含碳交易成本、燃料成本、购电成本等多目标加权组合函数地形非常崎岖到处都是局部陷阱。而决策变量维度高种群规模如果不到100以上初始粒子根本铺不满整个解空间更加剧了早熟。3.2 改进点一非线性递减惯性权重针对早熟收敛我把固定惯性权重改成随迭代次数非线性递减的策略。公式如下w w_min (w_max - w_min) × (cos(π × iter / max_iter) 1) / 2为什么用cos递减而不是传统线性递减因为cos曲线在迭代初期下降较慢让粒子在前期保有较强的全局探索能力——这非常关键前期搜索不充分后期无论如何精细搜索都找不到最优区域。迭代后期曲线加速下降粒子速度减小逐步收敛到局部精细搜索提高解的精度。我用这个办法在多个算例上跑下来相比线性递减最终目标函数值平均能改善3%到5%。虽然看起来不多但碳价高的场景下可能对应不少真金白银。3.3 改进点二自适应变异操作第二个改进是引入变异操作。这个思路借鉴了遗传算法但实现方式不同。具体做法很直接每个粒子在每一代更新后以一定的概率比如0.05到0.1触发变异变异的方式是随机选择该粒子维度中的若干个位置用边界内随机值重写。if rand pm: 对粒子x随机选择k个维度每个维度重新初始化 x(j) lb (ub-lb) × rand这里有个细节值得注意变异概率不能太大太大会导致粒子变成随机搜索算法不收敛太小又起不到跳出局部最优的作用。我的做法是把变异概率随迭代次数递减比如从0.15线性降到0.02。这样在迭代前期充分探索后期保持收敛稳定性。对比测试下来加了变异后的算法在CCS微网调度问题上30次独立重复实验得到的最优解标准差只有标准PSO的大约一半稳定性提升很明显。3.4 改进点三约束修正 动态罚函数含碳捕集微网调度里有大量约束粒子群算法处理约束不像数学规划方法那么自然。我的方案是混合处理盒式约束直接硬剪裁等式和不等式约束用动态罚函数法处理。盒式约束机组出力限值、储能充电功率限值、CCS捕集量限值等在粒子更新后直接用边界值裁剪即可这个简单可靠。等式约束如功率平衡约束和复杂不等式约束如储能SOC状态转移约束则加到目标函数里乘以一个动态罚因子F_total F_objective λ × (违反约束平方和)λ随迭代次数逐步增大前期让粒子松散探索可行域之外后期紧约束把粒子拉回可行域内。这个先松后紧的模式对高维约束问题很有效。需要注意的是罚函数系数不能从一开始就设得过大否则那些稍微违反约束但经济性非常好的粒子会被直接淘汰而实际上这些粒子附近的区域可能正是全局最优所在的区域。4. Matlab代码架构从数据读到结果导出的完整链路4.1 程序整体框架与目录组织整个Matlab项目我建议按下面的目录结构来组织这是工程化仿真的基本素养别把几十个脚本全丢在一个文件夹里carbon_microgrid_scheduling/ ├── main.m % 主入口 ├── data/ │ ├── load_data.m % 生成或读取负荷/风电/光伏数据 │ ├── price_data.m % 电价与碳价参数 ├── models/ │ ├── initialize_particles.m % 粒子群初始化 │ ├── evaluate_objective.m % 适应度函数计算 │ ├── ... ├── algorithms/ │ ├── ipsoschedule.m % 改进粒子群主迭代 ├── results/ % 结果保存目录main.m是唯一的入口负责设置基本参数、调用各模块、汇总结果并绘制图表。这个结构最大的好处是你要换碳价、换负荷数据、甚至换算法比如改回标准PSO做对比实验只需要改对应模块的参数接口不用从头到尾改代码。核心参数设置示例%% 微网基本参数 N 24; % 日前调度时段数小时 T_intra 96; % 日内调度时段数15分钟 P_load load_data(typical_day); % 负荷曲线 P_wind wind_data(typical_day); % 风电出力曲线 P_pv pv_data(typical_day); % 光伏出力曲线 %% 改进粒子群算法参数 pso_params.nPop 120; % 种群规模 pso_params.maxIter 300; % 最大迭代次数 pso_params.wMax 0.95; % 最大惯性权重 pso_params.wMin 0.25; % 最小惯性权重 pso_params.c1 1.6; % 自身学习因子 pso_params.c2 1.8; % 社会学习因子 pso_params.pm0 0.15; % 初始变异概率 pso_params.pmMin 0.02; % 最小变异概率注意学习因子c1和c2的取值我做了一些实验。教科书里经常推荐c1c22但在这种高维约束问题上c1自身认知稍小、c2社会学习稍大的组合收敛更快。我把c1调到1.6、c2调到1.8之后300代内收敛效果明显变好。4.2 粒子编码设计把调度方案映射成粒子向量粒子编码是整个算法和物理模型的桥梁设计得好不好直接影响算法效率和代码复杂度。我这里采用的是混合编码方式把决策变量铺成一维向量。日前层的粒子编码形式如下x [P_GT(1:N), P_ES(1:N), P_grid(1:N), P_CCS(1:N), P_P2G(1:N)]其中P_GT燃气轮机各时段出力P_ES储能各时段充放电功率正为充电负为放电P_grid与主网的交换功率正为购电负为售电P_CCS碳捕集装置各时段能耗P_P2G电转气装置各时段能耗这样一个粒子长度为5×24120维。对了燃气轮机的启停状态0/1变量我没有放进粒子编码而是作为外层循环来枚举因为微网里通常只有一到两台燃气轮机启停组合数量有限枚举的效率远高于优化。这个设计决策帮我省了不少麻烦——否则粒子群处理0/1整数变量又得多一步离散化操作。粒子编码示例lb [ones(1,N)*P_GT_min, ones(1,N)*(-P_ES_max), ones(1,N)*(-P_grid_max), ... ones(1,N)*P_CCS_min, ones(1,N)*0]; ub [ones(1,N)*P_GT_max, ones(1,N)*P_ES_max, ones(1,N)*P_grid_max, ... ones(1,N)*P_CCS_max, ones(1,N)*P_P2G_max]; population initialize_particles(pso_params.nPop, lb, ub);粒子的每个维度都有明确的物理含义后续在evaluate_objective函数里按索引切分即可。4.3 适应度函数目标函数约束罚项的统一封装适应度函数是整个程序的核心。我把它封装成一个独立函数输入是粒子位置向量和系统参数结构体输出是适应度值和各个成本分项。这样做有很多好处其中最重要的就是调试时可以直接把一个已知可行解代入函数检查成本计算是否正确而不需要跑整个算法。伪代码逻辑如下function [fitness, cost_breakdown] evaluate_objective(x, params) %% 1. 解码粒子 N params.N; P_GT x(1:N); P_ES x(N1:2*N); P_grid x(2*N1:3*N); P_CCS x(3*N1:4*N); P_P2G x(4*N1:5*N); %% 2. 计算功率平衡约束违反量 % 风电光伏燃气轮机储能放电购电 负荷储能充电CCS能耗P2G能耗售电 P_renewable params.P_wind params.P_pv; balance_violation zeros(1,N); for t 1:N balance_violation(t) P_renewable(t) P_GT(t) max(-P_ES(t),0) max(P_grid(t),0) ... - params.P_load(t) - max(P_ES(t),0) - P_CCS(t) - P_P2G(t) - max(-P_grid(t),0); end %% 3. 计算经济成本 fuel_cost sum(params.gas_price .* P_GT / params.GT_efficiency); grid_cost sum(P_grid .* params.elec_price); % 正为购电负为售电 ess_cost sum(abs(P_ES) .* params.ess_degradation_coef); %% 4. 碳排放与碳交易成本 total_emission sum(params.emission_factor .* P_GT); % 总排放 captured_co2 sum(params.capture_rate .* P_CCS); % 捕集量 net_emission total_emission - captured_co2; % 净排放 carbon_cost params.carbon_price * (net_emission - params.free_quota); %% 5. 总适应度目标动态罚函数 penalty_factor params.lambda; objective fuel_cost grid_cost ess_cost carbon_cost; constraint_penalty penalty_factor * sum(balance_violation.^2); fitness objective constraint_penalty; cost_breakdown struct(fuel, fuel_cost, grid, grid_cost, ... ess, ess_cost, carbon, carbon_cost, penalty, constraint_penalty); end4.4 IPSO主迭代过程的Matlab核心代码改进粒子群主循环并不复杂但要把前面说的三个改进点都落进去。核心代码如下function [gbest, gbest_value, convergence_curve] ipsoschedule(...) % 初始化粒子位置和速度 [positions, velocities] initialize_swarm(params); pbest positions; % 个体最优 pbest_value inf(1, params.nPop); % 评估初始种群 fitness_values zeros(1, params.nPop); for i 1:params.nPop [fitness_values(i), ~] evaluate_objective(positions(i,:), params); pbest_value(i) fitness_values(i); end [gbest_value, best_idx] min(fitness_values); gbest positions(best_idx,:); convergence_curve zeros(1, params.maxIter); for iter 1:params.maxIter % 1. 自适应惯性权重cos非线性递减 w params.wMin (params.wMax - params.wMin) * ... (cos(pi * iter / params.maxIter) 1) / 2; % 2. 自适应变异概率递减 pm params.pm0 (params.pmMin - params.pm0) * (iter / params.maxIter); for i 1:params.nPop % 标准PSO速度更新 r1 rand(1, length(positions(i,:))); r2 rand(1, length(positions(i,:))); velocities(i,:) w * velocities(i,:) ... params.c1 * r1 .* (pbest(i,:) - positions(i,:)) ... params.c2 * r2 .* (gbest - positions(i,:)); % 位置更新 positions(i,:) positions(i,:) velocities(i,:); % 3. 盒式约束硬裁剪 positions(i,:) max(positions(i,:), lb); positions(i,:) min(positions(i,:), ub); % 4. 自适应变异 if rand pm k randi(5); % 随机变异1~5个维度 idx randperm(length(positions(i,:)), k); positions(i,idx) lb(idx) (ub(idx) - lb(idx)) .* rand(1,k); end % 重新评估 [fit_val, ~] evaluate_objective(positions(i,:), params); % 更新个体最优 if fit_val pbest_value(i) pbest_value(i) fit_val; pbest(i,:) positions(i,:); end end % 更新全局最优 [best_curr, best_idx] min(pbest_value); if best_curr gbest_value gbest_value best_curr; gbest pbest(best_idx,:); end % 动态罚函数lambda递增 params.lambda params.lambda0 (params.lambda1 - params.lambda0) * (iter / params.maxIter); convergence_curve(iter) gbest_value; end end这里有一个非常容易被忽视的细节r1和r2的生成方式。很多教材写的是两个标量随机数但更推荐向量化的随机数——每个维度独立随机。在高维问题上每个维度使用独立随机步长能显著增加搜索多样性。这是我做对比实验时发现的一个小但有效的改进。4.5 多时间尺度的数据衔接实现日前层跑完后得到solution_day结构体包含各机组出力序列。日内层要做的事是读取这个结果并在此基础上滚动优化。代码层面我在日内层的适应度函数中增加了一个跟踪项% 日内滚动优化的目标在跟随日前计划的基础上进行修正 deviation_penalty sum((P_GT_intra - P_GT_day_ref(1:4)).^2) * delta_coef; fitness_intra objective_intra penalty deviation_penalty;这块的要点在于日前计划传过来的是一个向量日内滚动只取与当前滚动窗口相对应的一小段作为参考基准。比如现在处于第5个15分钟时段滚动窗口覆盖5到20时段那参考基准就取日前计划对应的第2小时到第5小时的出力值而不是把全天计划都拿进来。5. 仿真结果分析改进算法到底好在哪5.1 测试系统与参数设定我这套代码用典型的微网测试系统做了验证。微网结构包括一台250kW燃气轮机、120kW风电、60kW光伏、200kWh储能、CCS装置最大捕集能耗80kW、P2G装置最大40kW、一个200kW的负荷基准。电价采用峰谷平时段电价峰时段1.2元/kWh谷时段0.4元/kWh碳价为50元/吨。注意碳价这个参数对整个调度结果影响极大。我做了一个敏感性分析碳价从20元/吨升到150元/吨碳捕集装置的平均捕集率会从30%升到超过85%。这说明模型确实捕捉到了碳价信号对低碳调度行为的引导作用。5.2 改进PSO与传统PSO的收敛性对比30次独立实验的平均收敛曲线对比表明传统PSO在约80代左右就陷入平稳最终平均适应度值大概在1.75万元而改进PSO要到160代左右才趋于平稳最终平均适应度值约1.62万元。改进算法虽然迭代更久但找到的解经济性好了约7.5%。更关键的是标准差。传统PSO多次运行结果跳动范围从1.7万到2万极差很大而改进PSO的标准差只有传统PSO的一半不到。做科研和写报告的人应该都明白算法的稳定性和复现性有时比绝对最优值更重要——审稿人总会问你的算法跑几次波动大吗没有一个稳定的结果确实很难交代。5.3 调度结果直观分析最优调度结果有几个直观的现象值得说一说。第一储能充放电呈现明显的谷充峰放特征。凌晨电价低谷期储能充电下午高峰时段放电这和预期一致。储能成本参数决定了这个特征会不会被削平。第二CCS的运行时段集中在风大的夜间时段。夜间风电出力波动大还容易弃风正好把多余的风电拿来给CCS供电捕集CO2同时把捕集到的CO2送到P2G制气储存起来等到白天燃气轮机出力大的时候用。这相当于把之前弃掉的风电转换成了负排放和可储存燃气整个经济账一下就活了。第三燃气轮机出力并没有因为碳捕集能耗增加而简单下降。相反在碳价高的场景下燃气轮机出力反而有所增加因为CCS会消耗额外的电能来自风电和储能再配合P2G产生燃气回补实现一定程度的碳循环。6. 调参与避坑指南Matlab实现中的关键教训6.1 粒子群参数的先粗调后微调经验我见过不少人一上来就对着PSO的四个核心参数疯狂调其实效率极低。我自己的经验是先固定种群规模和迭代次数把惯性权重范围给定0.4到1.0之间然后粗调c1和c2。优先调c1和c2的绝对值比较如果收敛太慢优先减少c1如果震荡不收敛优先减少c2。参数调试的三条线列成表会更直观症状可能原因调整方向前期收敛极快但结果很差w初始值太小增大wMax到0.9以上后期收敛极慢徘徊不前wMin过大减小wMin到0.25以下多次运行结果波动大变异概率太低增大pm0到0.1-0.15结果一直不可行约束严重违反罚函数权重过小增大lambda1或加快lambda递增速度6.2 罚函数系数调整的两难动态罚函数这个环节最折磨人。罚函数系数若太小算法最终可能给出一个违反功率平衡约束的解若太大前期搜索又会被限制在非常狭窄的可行域内很难跳出局部最优。我的做法是lambda从1e-2起步每代乘1.02增长到1e2左右封顶。因为约束违反量平方的量级通常在1e-3到1e2之间乘上100这个量级的系数对适应度的惩罚大概从几十到几万可以在迭代后期起到强约束作用。但注意这不是一个普适规律。如果你的系统参数变了比如负荷大了10倍约束违反量的量级也会变化罚参数需要相应调整。最稳的办法是先跑10代在命令行打印一下目标函数值和约束违反量的数量级再决定罚系数的取值档位。6.3 别忘了解码时的单位统一这是很多Matlab新手最容易栽的坑。碳捕集的能耗单位是kW捕集CO2量单位是kg碳排放因子单位是kg/kWh碳价单位是元/吨。这四个单位之间至少要经过三步换算。我见过太多人在算碳交易成本时直接把吨当千克用结果碳排放成本算出来小了1000倍调度结果完全扭曲。针对这个问题最好的习惯是把所有的单位换算关系写成一个常量定义模块放在程序最开头%% 单位换算常量 kg_per_kWh 0.5; % 燃气轮机碳排放因子 per_ton 1000; % 千克转吨倍数 carbon_price_per_ton 50; % 元/吨 carbon_price_per_kg carbon_price_per_ton / per_ton; % 换算成元/千克每次在代码里用到碳价、排放量这些量直接使用换算过的常量不要在公式里乘1000。这条建议值千斤。6.4 结果可视化的三张必画图做完整套调度建议至少画三张图既方便自己检查结果有没有问题也方便直接放进论文里有说服力。第一张是电功率平衡图横轴24小时纵轴功率把负荷、风电、光伏、燃气轮机、储能、CCS能耗、P2G和购电售电全部画在堆叠面积图里一眼就能看出每个时段功率是否平衡。如果出来上下面积不闭合说明约束处理还有问题。第二张是储能SOC与充放电功率曲线SOC是平滑的锯齿状变化充放电功率和SOC的增减方向必须匹配。这张图可以快速检验储能建模是否正确。第三张是碳排放与碳捕集量逐时对比图柱状图放燃气轮机总排放量和捕集量折线放净排放量。如果捕集量出现脉冲式的高峰看是否与风电高发时段重合核对该时段的功率平衡是否在合理范围内。这张图我能用于快速判断优化出来的策略是否符合低碳目标在时序上的预期。7. 这套代码的扩展方向与实际工程应用建议结构上这套代码为后续扩展留了比较大的余地。最常见的扩展方向包括第一考虑不确定性。把风电和光伏的预测误差用场景法或机会约束的方式引入模型。比如可以生成多组风电场景在日前调度时考虑最坏场景下的约束满足情况这会显著增加计算量但改进的粒子群算法相对于标准优化算法反而有了优势——因为粒子群天然适合并行计算场景评估。第二加入需求响应。把可平移负荷、可削减负荷作为新的决策变量。操作上只需在粒子编码中增加对应的控制变量维度比如负荷平移量向量并修改功率平衡约束的左侧负荷项即可适应性很强。第三换成多目标优化。很多时候我们不仅关心经济成本还要同时权衡碳排放量这就是典型的多目标优化问题。可以把适应度函数改成非支配排序结构参考NSGA-II的框架实现多目标改进PSO。所有前面说的约束处理技巧都可以原样复用难度主要在拥挤距离排序和外部档案维护上。当然做工程应用来提高代码可信度最好与商业求解器做个交叉验证。比如用Gurobi或Cplex求解同一个线性化模型把结果作为参考解对比改进PSO的解与全局最优解之间的差距百分比。我这条流程里使用了线性化处理与PSO对比在典型工况下差距在2%以内这个数据拿出来无论是写论文还是向领导汇报都比较有说服力。最后再分享一个小细节粒子群算法是多起点随机搜索算法强烈建议在调用主函数之前先执行一次rng shuffle或用时间戳作为随机种子避免每次跑出相同的初始化结果。做实验时记录种子值出问题时可以复现这样可以大幅减少上次结果跑出来这次怎么跑不出来了的困惑。我在实际项目中吃过这个亏现在所有涉及随机数的代码都会统一保存随机种子状态这个习惯已经成了我的固定流程。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进