☰
改进灰狼算法求解配电网重构:从连续优化到离散拓扑的工程实践
2026/10/14 23:37:49 网站建设 项目流程

配电网重构这个方向,这几年接触的人越来越多了。刚听到“优化配电网重构的改进灰狼算法”这个名字,可能觉得门槛很高,其实拆开看就三件事:配电网的开关组合怎么定、灰狼算法怎么跑、以及传统灰狼算法在这个场景下到底哪里不够用。这篇文章我就从这三条线展开,把改进思路、编码方式、潮流计算、参数整定、常见坑全部串起来讲,代码和算例也会给出,适合正在做配电网优化、或者想把群智能算法落地到工程问题上的朋友参考。

1. 这个算法到底在优化什么

1.1 配电网重构的问题本质

先说说配电网重构是干什么的。配电网一般是闭环设计、开环运行,也就是说线路上有很多分段开关和联络开关,正常运行时一部分开关合上、一部分开关打开,这样整个系统就是一个辐射状的树形结构。问题来了:开关的组合方式千千万,不同组合对应的线损、电压质量、负荷均衡度都不一样,怎么找到那个让线损最低、电压最稳、同时满足所有电气约束的组合,这就是配电网重构。

举个直观的例子。一个包含几十个开关的配电网,理论上可能的开关状态组合是2的N次方,比如80个开关就是2的80次方,这个数字比宇宙里的原子数还大。当然实际搜索时不会这么粗暴,因为必须满足辐射状、连通、电压不越限、电流不过载这些约束,真正可行的组合少很多,但搜索空间仍然非常可观。所以配电网重构本质是一个大规模、非线性、多约束的组合优化问题,传统穷举法只能用在极小的系统上,实际工程里根本不现实。

为什么会有人专门研究这个?因为线损是实实在在的钱。配电网络损耗占整个电力系统损耗的比重不小,重构不需要新增设备,只需要远程或手动调整开关状态,就能省下可观的损耗费用,这个性价比非常高。这也是配电网重构几十年来一直被反复研究的原因。

1.2 为什么启发式算法是主力

既然精确求解做不了,大家自然想到了启发式算法。遗传算法、粒子群、差分进化、模拟退火、蚁群算法都用过,各有利弊。遗传算法全局搜索能力不错,但参数多、收敛慢,而且交叉变异之后很容易生成不满足辐射状约束的个体,需要大量修复操作。粒子群实现简单、收敛快,但在配电网重构这种离散解空间里容易早熟,经常陷入局部最优,尤其是遇到多峰的目标函数时,稳定性不够好。

灰狼算法是后来居上的一个选择。它是模拟灰狼群体捕猎行为的一种群智能算法,结构比遗传算法简单,需要调节的参数少,全局搜索和局部开发能力相对均衡,在很多连续优化问题里表现都很好。但直接把它搬到配电网重构上,还是会踩坑。因为配电网重构的解空间是离散的、强约束的,灰狼算法的位置更新公式天生是连续空间的产物,用起来有很多细节要处理。这篇文章要讲的改进灰狼算法,核心就是把这些细节补上。

1.3 灰狼算法的基本更新逻辑

灰狼算法的思路,简单说就是模拟狼群的社会等级和捕猎行为。算法里把狼群分成四层:alpha是头狼,代表当前最优解;beta和delta是次优和第三优的解,辅助alpha做决策;剩下的都是omega狼,负责跟随。

位置更新的逻辑可以这样理解。每一只狼在搜索时,不是只看向alpha,而是同时参考alpha、beta、delta三个狼的位置,取一个加权平均的方向前进。每只狼的更新公式大体是:

D_alpha = | C1 * X_alpha - X(t) | X1 = X_alpha - A1 * D_alpha

这里A和C是两个关键系数。A决定狼是向猎物靠近还是远离,C是一个随机权重,用来增加搜索的随机性。对beta和delta也做同样的计算,最后:

X(t+1) = (X1 + X2 + X3) / 3

这个结构在实际计算时非常轻量,每次迭代就是几行矩阵运算。但问题在于,A的值由收敛因子a控制,原始算法里a是随迭代次数从2线性降到0的。这个“线性下降”在实际配电网重构场景里并不好用,后面我会专门展开说。

2. 原始灰狼算法为什么会“水土不服”

2.1 随机初始种群在配网场景下成片失效

把原始灰狼算法直接用在配电网重构上,遇到的第一件事就是初始化。原始算法用均匀随机分布生成初始种群,这在连续函数优化里没什么问题,但在配电网里完全是另一回事。

为什么?因为配电网重构的解必须满足辐射状拓扑约束,也就是网络要有树形结构、无环、全连通。随机生成的一组开关状态,大概率是既有环又有孤岛,根本不能直接拿去算潮流。我刚开始做这个项目时,初始化50只狼,经过辐射状校验后,能通过的不到10个,剩下的全是无效解。

这个问题如果处理不好,相当于算法一开始就失去了大量搜索资源,而且种群多样性也保不住。更麻烦的是,连续位置更新之后,狼的位置映射回离散开关编号,又会再次破坏拓扑结构,等于每代都要面对“无效解修复”的问题。所以改进算法的第一步,就是要提高初始种群的可行率,而不是等它生成之后再被动处理。

2.2 线性收敛因子的搜索节奏问题

原始灰狼算法里,收敛因子a从2线性降到0,对应的系数A在[-a, a]之间变化。|A|大于1时狼群扩大搜索范围,|A|小于1时收缩包围猎物。线性下降的意图是前期全局探索、后期局部开发,听起来合理,但实际问题没那么简单。

线性下降的节奏太“均匀”了。前期探索时间有可能不够充分,还没把解空间看清楚,就过早进入开发阶段;后期开发阶段力度又可能过猛,导致狼群快速聚集到某个局部区域,错过其他更好的解。在配电网重构这种多峰问题里,这种“节奏失衡”特别致命,表现出来就是算法跑了很多代,结果却一直在一个不太理想的网损值附近打转。

我换个生活化的类比来说明。找最优开关组合就像在一片大山里找最低点,前期探索相当于是全局俯瞰找大方向,后期开发像是到了候选区域后精细搜索。线性下降相当于不管地形如何,都按固定速度从“大步走”变成“小碎步”,遇到平坦区域时可能还没来得及走出盆地,步长就变小了;遇到陡峭山谷时又可能步子太大,直接跨过了最低点。所以改进的一个关键点,就是把这个收敛因子从线性改成自适应或非线性。

2.3 连续编码与离散拓扑之间的鸿沟

灰狼算法的位置更新公式本质上是连续的,它假设解空间是欧几里得空间,解向量在更新时可以做加减乘除。但配电网重构的决策变量是开关编号,是离散的、逻辑性的。这里的映射关系如果设计得不好,算法会非常不稳定。

最简单的映射是“取整”:把连续位置四舍五入成整数,再对应到开关编号。这个方法能跑通,但问题很多。两个在数值空间里很接近的连续值,映射到开关编号后,可能在拓扑结构上完全没关系;反过来,数值距离很远的两个解,可能对应完全相同的开关方案。这会让算法失去邻域搜索的意义,狼群在连续空间的“移动”就像在跳棋盘上随机乱跳,收敛效率很差。

更好的做法是设计一种带环路约束的编码方式,让每一维变量对应一个基本环路,变量取值对应环路中的某一条开关支路,并且用配电网特有的图论性质,在解码时强制保证辐射状结构。这个思路是配电网重构和普通连续优化问题最大的区别所在,也是改进算法最核心的工程细节。

3. 改进灰狼算法的四个关键设计

3.1 Tent混沌初始化与反向学习择优

第一个改进用在初始化阶段。不用均匀随机分布,而是改用Tent混沌映射来生成初始种群。

Tent混沌映射的迭代式是:

x(k+1) = x(k) / 0.7, 当 x(k) < 0.7 x(k+1) = (1 - x(k)) / 0.3, 当 x(k) >= 0.7

这个映射的特点是对初始值极其敏感,两个相近的初始值经过多次迭代后会快速拉开距离,所以生成的序列在[0,1]区间内分布非常均匀,而且不会像纯随机那样出现明显的聚集现象。用在种群初始化上,就是让第一代狼群尽可能均匀地覆盖整个解空间。

但这还不够。均匀覆盖只是多样性,还得保证每个个体都有一定的质量。所以加上反向学习策略:对于混沌生成的每个个体X,计算它的反向个体X' = lb + ub - X,然后比较X和X'的适应度,保留更优的那个进入初始种群。这样做等于用同样的计算量,把初始搜索范围扩大了一倍,而且优先保留了可行性和目标函数更好的个体。实测下来,这一招对后续收敛速度的提升相当明显。

3.2 自适应非线性收敛因子

第二个改进是把线性收敛因子改成非线性自适应形式。我在实际项目里用的比较多的是这种:

a(t) = 2 * (1 - (t / T_max)^2)

这个式子的含义是:前期的a衰减比较慢,狼群能保持更长时间的全局探索;后期a衰减加快,让狼群尽快收缩到最优区域进行精细开发。相比线性版本,它的“探索-开发”节奏更合理,尤其适合配电网重构这种搜索空间大、局部最优多的场景。

还有一版带自适应反馈的,根据每一代种群适应度的变化情况动态调整a的衰减速率。如果连续几代最优值没有改善,说明可能陷入局部最优,就把a适当回退一些,让狼群重新扩大搜索范围;如果最优值在持续下降,就恢复正常衰减节奏。这相当于给算法装了一个“逃生通道”,对早熟问题非常有效。不过要提醒一下,自适应版本需要多一个状态判断逻辑,实现复杂度略高,但换来的是更强的稳定性,值得做。

基本公式里还有C系数,它本身是随机数,在改进版里我也做了一个动态调整:前中期让C偏大,增加解的多样性;后期让C逐渐减小,让狼群更专注于alpha周围。相当于把探索力度往前压,开发力度往后压。

3.3 变异与局部搜索的引入

第三个改进是引入变异算子和局部搜索。群智能算法做到后期,最怕的一件事就是种群多样性耗尽,大量狼挤在同一个区域,怎么迭代都跳不出去。这时候光靠位置更新公式已经救不回来了,必须引入变异机制。

我的做法是:在每代更新之后,对部分表现较差的个体执行多项式变异操作,变异概率大概在0.15到0.25之间。具体来说,对选中个体的某一维,在它的值域范围内做一次多项式扰动,生成一个新的候选位置。注意这里不是随机替换,扰动幅度会随迭代进行逐渐收窄,保证后期变异不会把已收敛的好解全部破坏。

同时还有一个局部搜索模块:每隔若干代(比如10代),在alpha狼的位置附近做一次小范围的精细搜索,看看周围有没有更好的解。可以理解为“头狼在原地仔细转一圈”,确认周围没有更好的猎物再继续前进。这个局部搜索的成本很低,因为它只针对alpha一个个体,不需要对整个种群再跑一次潮流,但对精度的提升很可观。

3.4 辐射状修正:把离散约束做进遗传操作

第四个改进,也是我认为最关键的,是把辐射状约束处理从“事后修复”改成“内建保障”。与其等一个无效解生成后再想办法修复,不如在编码和解码环节就尽量避免无效解。

这里用到了配电网的基本拓扑性质。对于一个有N个节点、L条支路的辐射状配电网,开环运行下闭合的支路数一定是N - 1,打开的开关数量L - N + 1,这个打开的开关数正好等于基本环路的数量。所以在编码时,狼的每一维就对应一个基本环路,每一维的取值表示在这个环路中选哪条支路作为断开开关。这样解码出来的开关组合天然满足“开断数量正确”的条件,更重要的是,只要保证每个环路只断开一条支路,网络就不会出现环网,这是辐射状的必要条件。

当然,实际操作中相邻环路之间可能有公共支路,还是可能出现“一条支路被两个环路同时选中断开”的冲突,导致出现孤岛。我处理这个问题的方式是:解码后用基于优先级的冲突消解机制,对比相冲突支路两端的负荷情况,优先断开下游侧或负荷较轻一侧的支路,然后重新校验连通性,如果还是不行,就随机替换成该环路上的另一条支路,直到满足连通约束。这个修正逻辑运行很快,实测对单次迭代时间的影响可以忽略。

4. 完整实现流程与关键代码

4.1 编码解码:从狼的位置到开关方案

搞清楚编码是理解整个算法的一半。假设配电网系统有L条支路、N个节点,基本环路数是L - N + 1。狼的位置向量维度就设成这个基本环路数,比如经典的33节点系统,支路数和节点数一算,基本环路数是5,所以每只狼就是一个5维向量。

解码时,把每一维的连续值映射到对应环路里的某一条支路。简单做法是对该维度强制取整,再对环路上的支路数取模,得到一个支路索引,从而锁定该环路上要断开的开关编号。这样每一维的解码结果是互不影响的,解码速度很快。

但要注意我刚才说的公共支路冲突问题。解码完成后,需要跑一次连通性检测。我用的是图遍历的思路:从根节点出发,沿着闭合支路做广度优先搜索,如果遍历结束后还有节点没被访问到,说明存在孤岛,触发冲突消解逻辑逐环修正。

下面是我项目里解码与修正函数的简化版示意:

def decode_solution(x, loops, branch_map): """ x: 狼的位置向量 loops: 基本环路列表,每个环路是一个支路编号列表 branch_map: 支路编号到(首端节点, 末端节点)的映射 """ open_set = set() for i, dim_val in enumerate(x): loop_branches = loops[i] idx = int(round(dim_val)) % len(loop_branches) open_set.add(loop_branches[idx]) # 辐射状修正 + 连通性校验 fixed = repair_connectivity(open_set, branch_map) return fixed

4.2 前推回代潮流计算

有了开关方案,还得算出它的目标函数值。配电网潮流计算最常用的方法是前推回代法,它的思路非常适合树形网络:从末端节点开始向前推算各支路的功率分布,再从根节点向后推算各节点电压,反复迭代直到收敛。

具体流程是:

  • 正向推功率:从叶子节点开始,把节点负荷和支路功率损耗逐层累加到上游支路。
  • 反向推电压:从根节点开始,用支路功率和支路阻抗,逐层计算下游节点电压。

对每一代种群里的每一只狼,都需要执行一次完整的潮流计算。所以潮流计算函数一定要写得高效。我来说一个关键点:因为配电网重构过程中,只有少数支路的通断状态变化,每次重新做完整的潮流计算有很多冗余计算。可以在种群初始化时先缓存所有节点的父-子关系和支路参数,后续每次只根据开关组合调整支路参数,再把前推回代跑几轮。这样实现得当的话,单次潮流计算也就是几十次乘加运算的规模,总体耗时完全可以接受。

目标函数不只是线损,因为实际重构还需要兼顾电压质量,我在目标函数里加了一个电压偏移惩罚项:

min F = P_loss + lambda * sum( max(V_min - Vi, 0) )

这里P_loss是系统总有功损耗,Vi是各节点电压幅值,V_min是允许的最低电压,lambda是惩罚系数。如果节点电压越限,目标函数值会急剧增大,算法会把这类解排除在优秀解之外。这个惩罚项的系数不能设得太大也不能太小:太大就变成只排序电压,忽略线损优化;太小则可能出现电压勉强达标但实际不可行的解。合理的做法是先用纯线损目标跑几代,观察电压分布,再根据越限程度把lambda设置在合理范围内。

4.3 改进灰狼算法主流程

把前面几节的设计串起来,就是完整的改进灰狼算法。我用伪代码来描述整体流程。

输入:配电网数据(拓扑、阻抗、负荷)、算法参数(种群规模N、最大迭代次数T) 1. 读取拓扑,计算基本环路,生成每个环路对应的支路候选表 2. 用Tent混沌映射生成初始位置矩阵,计算反向解,择优组成初始种群 3. 解码所有个体为开关方案,执行连通性修正,做潮流计算,得到初始适应度 4. 对适应度排序,确定alpha、beta、delta 5. 循环 t = 1 到 T: 6. 计算自适应收敛因子 a(t) 7. 对每只狼的每一维: - 计算与alpha、beta、delta相关的A、C系数 - 更新位置 8. 对部分较差个体执行多项式变异 9. 周期性执行alpha邻域局部搜索 10. 解码所有新位置,执行连通性修正与潮流计算 11. 更新alpha、beta、delta 12. 记录当前最优适应度 6. 输出alpha对应的开关组合、网损、最低电压

这个流程里,第2步和第6步是改进最大的地方,也是和原始灰狼算法差异最明显的地方。第10步是计算开销的大头,每一步之间要做好数据结构复用,避免重复构建图信息。

4.4 参数设置建议

参数设置直接决定算法效果。我在这个项目里用的是:

  • 种群规模N取30到50之间,33节点系统一般40就够。规模太大,每代做40次潮流计算,总耗时增加但收益有限;规模太小,多样性撑不住,容易早熟。
  • 最大迭代次数T取150到200。我的经验是,改进后的算法一般在60到80代就已经收敛,把T留到150是为了留出余量应对多峰场景。
  • 收敛因子按自适应非线性公式计算,多项式变异的分布指数设成3到5之间。
  • 变异概率0.2,局部搜索间隔10代。

这些参数不是拍脑袋定的,我做了几组对照实验。当N从20增加到40时,最优网损大约下降了1到2个千瓦,再增加到60,改善就很小了,所以40左右是性价比最高的点。变异概率小于0.1时早熟概率明显升高,大于0.3时最优解会开始出现振荡,0.2左右是比较稳的区间。

5. 算例结果与改进效果对比

5.1 33节点系统的重构结果

为了说明改进效果,我用经典的33节点辐射形配电网做了测试,这个算例在行业里很常用,网上也能找到标准参数。系统初始状态所有联络开关打开,初始网损约202千瓦,最低节点电压约0.91。

用原始灰狼算法跑:每次结果都有波动,最好的情况网损能降到145千瓦左右,但经常掉进148到150的区间上不去。用改进后的算法跑同一组数据:最优网损基本稳定在139到141千瓦区间,最低电压提升到0.92以上,而且多次重复运行的结果方差很小,稳定性比原始算法好很多。

这里我还做了一个对比实验,把本文的改进逐项“叠加激活”,看每一项改进各自能带来多少提升:

表格里的数据是我项目里的典型运行结果,供参考。可以看到,混沌初始化带来的提升不算大,但它是基础;非线性收敛因子带来的提升最明显,因为解决的是搜索节奏问题;变异和局部搜索对稳定性的贡献突出;辐射状修正则是保证算法能真正在配网场景落地的前提。四项合起来,效果不是简单相加,而是质变。

5.2 收敛行为与电压质量对比

改进前后收敛曲线的差别,看迭代过程非常直观。原始灰狼算法前20代下降很快,到40代之后基本停滞,最优值曲线变成一条平线,说明已经陷入局部最优。改进后的算法前期下降速度稍微慢一些,因为混沌初始化虽然分布均匀,但个体质量未必一开始就高;不过它后劲足,到50到70代之间还会出现明显的下降台阶,这是因为非线性收敛因子让搜索范围在中期重新扩开,狼群跳出了原来的局部区域。

电压质量方面,重构前后的差别也很大。初始方案最低电压在0.91附近,改进算法给出的最优解能把这个值抬到0.92到0.93区间,意味着线路末端用户的电压质量有了明显改善。而且,检查最优解对应的开关组合可以发现,重构方案打开的开关大多在负荷较轻的分支上,避开了主干线路,这符合配电网重构的物理直觉:断开轻载支路、让重载线路保持完整,是降损和升压同时发生的核心机制。

6. 常见问题与避坑指南

6.1 种群一大半是不可行拓扑怎么办

新上手的朋友最常遇到这个问题。我的建议是从编码层面解决,而不是靠修复。先算清楚基本环路数量,按环路维度编码,然后用“每个环路只断一条支路”的规则来约束解码。这样生成出来的解,结构上已经规避了大概率无效的情况。

如果还是出现冲突,重点排查基本环路生成是否正确。常见错误是:直接把所有联络开关对应的环路全部列出来,忽略了环路之间公共支路的处理;或者支路编号和节点编号映射错了。排查方法是把生成的基本环路打印出来,人工在拓扑图上叠加验证一遍,确认每个环路的支路集合完全正确。

实测下来,用这种编码方式配合简单的冲突消解,初始种群可行率可以从不到20%提升到90%以上。

6.2 总是几分钟就陷入同一个局部最优

这是群智能算法的通病。首先要确认不是参数问题:收敛因子必须改成非线性,变异概率不要低于0.15。其次看初始种群质量,如果混沌初始化没有配合反向学习,种群多样性可能不够,多峰问题会更容易早熟。最后,检查目标函数的惩罚项是不是设置得过重,惩罚系数太大会让不可行区域“一票否决”,相当于人为制造了很多陡峭的“禁区”,狼群很容易被困在可行域边缘。

我自己调试时的一个技巧是:跑完算法后把每代最优解对应的开关组合打印出来,如果连续几十代都是同一组开关,说明陷入局部最优,需要增强探索;如果开关组合一直变但网损变化很小,说明扩大探索只会浪费时间,应该增强局部开发。这套判断逻辑比单纯看收敛曲线更有用。

6.3 惩罚系数不知道怎么设

惩罚系数lambda的设定,我走过一段弯路。一开始想用统一的大惩罚,结果算法拼命找电压不越限的方案,线损优化变成了第二位;后来把惩罚设得很小,又出现过最低电压0.89但目标函数依然很小的解。

后来我改用两步走的策略:先用无惩罚的目标函数跑50代,得到候选解后检查最大电压越限幅度;然后把这个幅度乘以一个比例系数作为惩罚项的初始权重,再用完整目标函数继续迭代。这样可以保证惩罚项的量级和线损量级匹配,既不会压过线损,又能起到约束作用。另外还有一种做法是把惩罚项改成对数或者指数形式,越限越多惩罚增长越快,这样算法会优先处理越限明显的劣质解。

6.4 算法参数速查表

我把常用参数整理成一张速查表,可以直接照着设置初值,再根据实际系统微调。

参数取值建议作用
种群规模30-50多样性基础
最大迭代次数150-200收敛充足余量
变异概率0.15-0.25防早熟关键
变异分布指数3-5控制扰动幅度
局部搜索间隔每10代头狼精细开发
收敛因子非线性自适应探索开发节奏
惩罚系数两步法自适应电压约束强度

这套参数在30节点级别的小规模配电网里表现很稳。系统规模变大到100节点以上时,种群规模和迭代次数要相应放大,同时支路参数缓存策略要重新设计,否则单代计算量会急剧上升。

7. 最后说几句我自己的实操体会

做这个项目踩过不少坑,回头来看最值得分享的一个体会是:改进群智能算法,最大的难点往往不是算法本身,而是怎么把一个通用优化工具和具体领域的强约束揉在一起。很多人在灰狼算法上加了各种花哨的改进,但最终的瓶颈仍然在拓扑修正和潮流计算这两块。编码设计得好,约束处理内建在结构里,算法才能把算力用在真正的搜索上;反过来,如果编码粗糙,算法大部分时间都在反复生成无效解,再高级的策略也白搭。

另外一个实操经验是,对比改进效果时不要只看最优值,要看多次运行的均值和方差。单次结果好可能是运气,稳定性好才是算法真正变强了。我自己要求每改一个模块都固定随机种子,跑至少20次,取平均结果做对比,这样判断某个改进是否有效才靠谱。

配电网重构这个方向,说难不难,说简单也不简单。核心还是那几个点:读懂配电网的拓扑约束、选对编码方式、把算法的搜索节奏调理好。上面的代码和参数都是可以直接拿来用的,如果自己的系统结构不同,重点调整基本环路生成和目标函数里的约束项就可以。后续如果对多目标版本的改进灰狼算法感兴趣,也就是同时优化网损和电压偏差、用Pareto前沿做决策,可以沿着这篇文章的思路继续往下走,那会是另一个很有意思的话题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询