ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

粒子群优化算法在IEEE33节点配电网DG选址与定容中的应用

粒子群优化算法在IEEE33节点配电网DG选址与定容中的应用 做配电网规划的朋友应该都遇到过这种场景领导或甲方问你“光伏、风电这些小电源到底接到哪个节点合适装多大容量”看着简单背后却是一整套“选址与定容”的组合优化问题。我在实际项目里试过多种智能算法方案最后稳定下来一直用的是粒子群优化算法PSO在IEEE33节点系统上做多目标寻优输出一套可跑的Matlab代码。如果你正在做配电网DG接入方案设计、写相关课程作业或课题研究这篇文章能给你一条可以直接照抄的完整路径从粒子编码到潮流计算再到结果分析把每个环节的“为什么”都讲清楚。1. 把“选址定容”翻译成粒子IEEE33算例的建模起点1.1 IEEE33节点系统先要弄清楚哪些参数做配电网方向研究的人对IEEE33节点系统应该不陌生这是一个非常经典的辐射状配电网测试系统常被用来验证DG选址、无功优化、网络重构等算法。我在搭算例时先明确了这个系统的基本参数参数数值说明基准电压12.66 kV全系统电压基准基准功率10 MVA计算标幺值时用节点数/支路数33 / 32辐射状网络总有功负荷3715 kW初始条件下的总负荷总无功负荷2300 kvar初始条件下的总无功初始有功网损约202.7 kW无DG时的结果最低节点电压约0.913 p.u.一般在18号节点附近这些参数在代码里是以数组形式维护的。重点提醒第一次接触这个算例的同学支路参数表里每一行对应一条支路的首端节点、末端节点、电阻和电抗顺序必须和网络拓扑严格对应。很多人把节点编号和数组索引搞混后面算潮流时节点电压全是乱的排查起来非常痛苦。1.2 粒子的编码方式为什么不把节点编号直接放进粒子粒子群算法本身工作在连续空间但“选址”这个动作本质上是离散的——你要从32个候选节点里挑出几个来。我见过不少新手直接把节点编号放进粒子比如把一个粒子编码成[5, 12, 27, 0.8, 0.5, 0.6]意思是节点5装0.8 MW、节点12装0.5 MW、节点27装0.6 MW。这样看起来直观但问题很大速度更新后节点编号会变成小数取整后可能重复也可能超出范围还要做合法性修复算法逻辑和代码都变得相当拧巴。我采用的方案是连续编码加稀疏选择粒子维度设为32对应节点2到节点331号节点作为平衡节点不参与第i维的取值代表该节点DG接入容量。取值0表示不接入大于0表示接入容量。这样选址和定容在同一个连续向量里全部搞定PSO天然支持这种表达不需要额外处理离散量。为了保证最优解不会是“所有节点都装一点”我还加了一个约束非零元素个数不超过设定的最大DG接入数量比如3个或5个同时单节点容量和总渗透率都有上限。这些约束通过罚函数或者对粒子修正来处理。三种常见编码方案对比编码方案优点缺点我的建议节点编号容量混合编码直观离散处理麻烦、速度更新后取值破缺不推荐二进制选址连续容量两段编码选址和定容解耦编码长度翻倍、PSO对二进制域支持弱可行但复杂连续容量编码0表示不接入全部约束由PSO连续域承担需要额外控制非零个数推荐粒子群优化算法在这种编码下工作得非常自然位置更新就是把某些维度的容量值压低到0某些维度从0抬起来完全不需要额外的离散化操作。这个设计决策是整个代码能跑通的基础。2. 潮流计算和PSO如何咬合前推回代法的实现细节2.1 为什么配网潮流选择前推回代而不是牛顿拉夫逊在配电网场景里系统拓扑是从变电站母线出发、向外辐射的树状结构不像输电网那种强环网。前推回代法就是专门针对辐射状配电网设计的潮流求解方法核心思路非常朴素顺着功率传输方向从首端向末端推再反方向把电压修正回来。有人会问用牛拉法行不行行但没必要。牛拉法通用性强、收敛性好但每次迭代都要构造雅可比矩阵程序复杂度更高。前推回代在辐射网上实现简单、迭代速度快而且对大多数DG接入场景数值上都很稳定。我在代码里用的是电流形式的前推回代精度和稳定性都足够。比较项前推回代法牛顿-拉夫逊法适用网络辐射状配电网任意拓扑实现难度低高单次迭代速度快慢需要构造雅可比矩阵否是配网DG选址场景推荐也可用但不必要2.2 前推回代代码结构拆解前推回代的流程可以拆成四步初始化所有节点电压为1.0 p.u.平衡节点电压保持1.0 p.u.不变根据当前节点电压和节点注入功率计算各节点注入电流I_i conj(S_i / V_i)前推支路电流从网络末端往根节点方向把下游节点注入电流累加到对应支路回代电压从根节点往末端V_child V_parent - Z_branch * I_branch反复执行第2到第4步直到两次迭代的节点电压最大偏差小于阈值我一般取1e-6。给一段核心代码骨架% branch: n_branch x 4 矩阵列为[首端节点, 末端节点, R, X] % load_power: 33 x 1 节点注入复功率含DG后 V ones(33, 1); V(1) 1.0; max_iter 100; tol 1e-6; for iter 1:max_iter V_old V; I_inj conj(load_power ./ V); % 节点注入电流 I_branch zeros(length(branch), 1); % 前推按支路编号反向累加 for k length(branch):-1:1 child branch(k, 2); I_branch(k) I_inj(child) sum(I_branch(branch(:, 1) child)); end % 回代从根节点向后更新 for k 1:length(branch) parent branch(k, 1); child branch(k, 2); Z branch(k, 3) 1j * branch(k, 4); V(child) V(parent) - Z * I_branch(k); end if max(abs(V - V_old)) tol break; end end这里有一个容易忽略的细节配网每条支路的Z都是有名值。IEEE33系统里支路电阻是0.09到0.5欧这个量级如果拿它直接和标幺值电压混合计算数值会差好几个数量级。我的做法是统一用有名值算电压单位是kV功率单位是kVA、kW、kvar电流单位是安培。这样调试时打印出来的量不会让人发懵。2.3 和PSO主循环的接口设计PSO每评估一个粒子实际上就要跑一次潮流计算。所以潮流计算最好写成独立函数比如function [Ploss, Vmin, Vdev] power_flow_eval(x, sysdata) % x 是解码后的DG接入方案 % 内部计算节点注入功率调前推回代返回网损、最小电压、电压偏差 end这样做的好处是PSO主循环只关心适应度不关心潮流内部逻辑。后面换节点系统、换DG类型时只需要改sysdata和这个函数内部的数据映射。需要注意DG接入后对节点注入功率的处理。DG按PQ节点处理如果功率因数设为0.9那么某节点注入功率就是S_DG P_DG 1j * P_DG * tan(acos(0.9))然后该节点的综合注入功率S_node S_load - S_DG这里的S_load是节点原始负荷S_node才是代入潮流计算的净注入功率。整个PSO迭代过程中每次粒子更新都要重新组装这个S_node向量。3. 多目标不打架的关键权重合并、归一化和约束处理3.1 三个目标函数的数学形式“多目标优化”这个名字听起来抽象落到这个算例上其实就是同时优化几个可能互相矛盾的量。我用的目标函数有三个系统有功网损最小f1 sum(P_loss)单位kW电压偏差最小f2 sum(abs(V_i - 1.0))标幺值累加DG等年值成本最小f3 sum(C_dg * P_DG_i)单位可以简化为万元网损代表运行经济性电压偏差代表电能质量DG成本代表投资经济性。这三个目标的本质冲突在于DG接得越多电压和网损往往越好看但投资成本越高而且节点选得不同同样的总容量效果完全不同。这就是定位需要考虑的核心问题。如果只考虑技术目标也可以只保留前两个目标做双目标优化。但题目既然是“多目标优化”通常会把经济性拉进来否则工程说服力不够。3.2 归一化的必要性量纲完全不是一个数量级我最早跑多目标时踩过一个坑直接把三个目标加起来。结果因为网损是几百kW、电压偏差是零点几、DG成本是几百万最后优化器几乎完全被成本项牵着走网损和电压目标形同虚设。解决办法是先归一化再做加权。我的做法是f1_norm f1 / f1_0其中f1_0是无DG时的初始网损f2_norm f2 / f2_0其中f2_0是无DG时的电压偏差f3_norm f3 / f3_max其中f3_max是最大允许DG容量对应的成本这样三个目标都大致落在0到1这个区间权重的意义才真实。这也是多目标优化里最容易忽略但直接决定结果有没有用的一步。我在代码里维护了一套无DG时的基准结果也就是初始网损和初始电压偏差专门用来做归一化参照。3.3 约束条件如何用罚函数收住约束条件通常包括节点电压范围0.95~1.05 p.u.单节点DG容量上限0.5 MW左右DG总渗透率上限不超过总负荷的40%接入点数量上限不超过预设值我用的约束处理策略是罚函数。适应度函数写成F alpha1 * f1_norm alpha2 * f2_norm alpha3 * f3_norm penalty当违反某个约束时penalty累加一个大数。具体做法是超出量乘以一个足够大的系数。提示罚函数系数不要设成突然跳变的常数我建议用“超出量×系数”的形式。比如电压越限penalty 1000 * max(0, V_i - 1.05)^2 1000 * max(0, 0.95 - V_i)^2。这样越限越厉害惩罚越大粒子能感受到一个平滑的“排斥力”不会在可行域边界反复横跳。如果罚函数系数设成常数例如只要越限就加固定的100000粒子在边界附近会得到一个非常陡峭的适应度突跳梯度信息完全丢失收敛会变得很差。平滑的二次型惩罚是实践下来最省心的方案。4. 跑完一遍之后读结果电压分布、网损和收敛曲线怎么判断效果4.1 优化前后电压剖面怎么对比跑完PSO之后第一步不是看适应度值而是画电压分布曲线。用Matlab画图很简单plot(1:33, V_base, --o); hold on; plot(1:33, V_opt, -s); grid on; xlabel(节点编号); ylabel(电压幅值(p.u.)); legend(无DG, PSO优化后);从我的算例看无DG时最容易跌破0.95 p.u.的位置一般在18号节点附近。优化后DG接入点附近的电压被明显抬起来整条电压曲线整体上移最低点通常在0.95以上。如果不出现这种效果基本可以判断DG总容量太小、接入位置偏了或者目标里电压权重大低。电压剖面还能看出一个信息如果某节点电压比其他节点明显高出很多说明DG容量集中得太厉害可能导致了局部电压过高。这时应该检查是不是接入点数量上限设得太大或者单节点容量约束没起作用。4.2 网损和成本目标之间的权衡怎么看算例里我跑过几组不同权重。网损最小为目标时得到的方案倾向于把DG集中放在末端重负荷节点旁边网损下降明显但电压可能会局部偏高成本也偏高。而采用等权重多目标时DG分布更分散接近“均衡方案”。权重组合网损(kW)最低电压(p.u.)DG总安装容量(kW)说明网损权重大约90-110约0.951000-1500网损最好但成本偏高等权重约120-140约0.93-0.96600-1000各项比较均衡电压权重大约160-190约0.97800-1200电压改善明显但网损改善有限注意这些数值是我算例里的一组典型结果具体随随机种子和系统参数浮动但“权重不同导致结果倾向不同”这个趋势是稳定的。真正做课题时应该对多组权重做敏感性分析画出一组Pareto前沿这才是多目标优化的正确用法。如果只想画出Pareto前沿可以用权重法多次运行收集所有非支配解。追求更完整的Pareto前沿的话可以考虑NSGA-II这类真正的多目标进化算法但代码复杂度会高一个台阶。对IEEE33这个规模和大多数工程场景权重法配合多组参数已经够用。4.3 收敛曲线怎么判断收敛曲线看的是每一代的全局最优适应度。我通常跑120代、种群规模30个。正常情况下前20代下降很快40代以后基本平缓。如果出现两种情况需要检查代码曲线下降特别慢可能惯性权重太大粒子一直在飞大范围该聚焦的局部区域没聚焦。曲线后期还在上下跳动可能v_max设得太大或者罚函数系数太小把不可行解当成了还不错的结果。收敛曲线的形态也能反映初始化范围是否合理。如果第一代适应度就特别低往往是初始粒子生成了一个比较特殊的方案后面很难超越如果第一代适应度特别高说明初始方案整体都很差可能会浪费很多代数才进入正轨。我习惯记录第一代和最后一代的适应度用于判断初始化范围的匹配程度。5. 调参和踩坑记录我在这个算例上反复修正的真实记录5.1 最容易翻车的地方粒子初始化范围粒子初始化范围直接决定了潮流计算能不能收敛。我刚开始设置DG容量上限为1 MW但粒子初始速度范围没控制导致初始粒子生成的方案里某个节点DG容量冲到几MW甚至十几MW潮流计算直接变成NaN迭代全崩。我的建议是粒子初始化范围严格限制在[0, 0.5] MW速度上限v_max设为区间宽度的10%~20%每次更新后都做一次边界裁剪x max(min(x, x_max), 0)如果跑的过程中出现电压为NaN第一时间检查DG容量是否越界而不是先怀疑潮流代码我遇到过一次非常隐蔽的问题DG容量的单位搞混了。我在目标函数里用的是kW但初始化和约束里却用了一些MW的数值导致粒子在0到0.5 MW之间生成潮流计算节点注入功率却按kW去减相当于负荷完全抵消不了电压一路跌到负值。这种问题打印出来就是一堆负数电压和NaN非常容易让人误以为是前推回代代码写错了。5.2 权重系数的分配策略多目标权重没有绝对正确答案取决于你当前关心什么。实践上我总结了一个顺序先用等权重跑通全流程确认代码和数据的正确性把网损权重加大到0.4左右电压和成本各0.3看结果变化如果想突出某项目标就把它设到0.6以上但要小心其他目标完全被忽略对每组权重独立跑3次取最好的一次避免随机性干扰判断这个流程能让你对“哪些权重组合会产生什么结果”建立起直观感受。特别是当决策者问你“如果降低一点成本网损会恶化多少”时你手上有几组权重下的结果表可以直接回答而不是临时重新跑。5.3 收敛性和改进的几点体会从我自己跑这个算例的感受来说标准PSO解决IEEE33的选址定容已经完全够用100代内收敛到稳定解不是问题。如果后面想继续进阶可以试着在标准PSO里加一个“越限修正”步骤每次粒子更新后对超过约束的值做一个定向回拉而不是完全靠罚函数。这种修正方式在小规模配网上比罚函数收敛更快代码改动也不大。另一个我在迭代过程中常用的技巧是动态调整速度钳制。前期让粒子在大范围内探索后期适当地缩小v_max帮助粒子在小区域内精细搜索。具体实现不复杂v_max 0.15 * (1 - 0.6 * iter / max_iter);这样迭代后期粒子速度变小局部搜索能力增强收敛精度会有可感知的提升。最后如果要把这套代码迁移到你自己的实际配网系统有一个小习惯值得注意换系统数据时先把无DG情况的潮流跑一遍和已知结果对比确认数据和拓扑正确后再接PSO。我遇到过很多次“数据没抄对”导致的离谱结果排查方法就是先把无DG状态跑通。IEEE33的基态结果比较明确很容易对照验证这也是为什么我一直推荐在这个系统上做原型验证。等基态数据完全对上了再接粒子群优化算法整个流程会顺利很多。
返回列表