#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)

目录
1配电网故障定位原理
1.1 故障信息的数学表示
1.2 二进制PSO算法的配电网故障定位原理
1.3 构造配电网故障定位评价函数
1.4 求期望函数
2 二进制粒子群算法的简单举例------背包问题
2.1 算例
2.2 Python 实现
2.3 Matlab 实现
3二进制粒子群算法的配电网故障定位(Matlab实现)
【#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)】
1配电网故障定位原理

1.1 故障信息的数学表示
在下图中K表示断路器,每一个断路器上均有一个FTU装置,可以反馈断路器开关是否过流,用表示上传的故障信息,反映的是各分段开关处是否流过故障电流有故障电流为1,否则为0)。即:
#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

因为FTU上传的信息可分为有故障信息及无故障信息两类,对于分段区间来讲也只能是有故障及无故障两种情况,所以我们可以用二进制编码规则对配电网故障定位问题进行数学建模。以上图所示辐射状配电网为例,系统拥有12个分段开关,我们可以用一串12位的二进制代码表示FTU的上传信息,作为程序的输入,1代表对应的开关有过流信息,0代表对应的开关无过流信息。同时用另一串12位的二进制代码作为程序的输出,代表对应馈线区间发生故障,代表无故障。
1.2 二进制PSO算法的配电网故障定位原理
应用二进制PSO算法求解配电网故障定位问题,粒子的位置代表配电网中馈线区段的状态,粒子的维数代表配电网的馈线区段总数。每一馈线区段存在0和1两种状态,0表示正常状态,1表示故障状态,馈线区段的状态为待求量。因此,N段馈线区段的状态求解就转化成N维粒子群优化求解,每个粒子的N维位置都表示为配电网N段馈线区段的潜在状态。每次迭代过程中,通过评价函数评价各粒子位置优劣,更新粒子的当前最优位置和全体粒子的最优位置,进而更新粒子的速度和位置,直到满足程序终止条件为止。最终得出的粒子群的全局最优位置就是所求的各馈线区段的实际状态。
离散粒子群
基本的粒子群算法是在连续域中搜索函数极值的有力工具,在此之后,提出了离散二进制粒子群,将离散问题空间映射到连续粒子运动空间,并适当修改粒子群算法来求解,在计算上仍保留经典粒子群算法速度-位置更新运算法则,粒子在状态空间的取值和变化只限于0和1两个值,而速度的每一维Vij代表位置每一位xij的取值为1的可能性,,因此在连续粒子群中的vij更新公式仍保持不变,但是Pbest和Gbest只在【0,1】的取值,其位置更新等式为:
(式中:r是0-1之间的随机数。)
#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

1.3 构造配电网故障定位评价函数
基于待求各馈线区段实际状态下所对应的信息应与实际上传故障信息偏差最小的原则,构造如下评价函数:
#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

表达式的值为每个潜在解对应的适应度值,值越小表示解越优良,因此评价函数应取极小值。
式中:#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片
为第j个开关FTU上传的故障信息,取值为1认为该开关流过了故障电流,为0则未流过;#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片
为各开关节点的期望状态,若该开关流过了故障电流,则期望状态为1,相反,期望状态为0,表达式为各区段状态的函数。N为配电网中馈线区段的总数,#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片
为配电网中各设备状态,为1表明设备故障,取0则设备正常。#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片
表示一个权系数乘以故障设备数,。是根据故障诊断理论中“最小集”概念设置的权重系数,取值范围介于与1之间,表明故障区间数越少解越优,避免出现误诊断,本文中权系数取0.5。
1.4 求期望函数#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

针对不同的网络,期望函数的表达式不同,无法用统一的格式表示出来。仅以上述算例为例来说明如何求取期望函数。
在辐射型配电网中,任何区间发生故障,必将导致其上游开关流过故障过电流。这是求取期望函数的原则。假设图一的馈线区段6处发生故障,那么分段开关K1,K2,K3 ,K6,都将有过电流若馈线区段11处发生故障,则K1,K2,K3 ,K6,K10都将有过电流。由此类推我们可得到各个分段开关的期望函数:
#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

2 二进制粒子群算法的简单举例------背包问题 2.1 算例
背包问题。有N件物品和一个容量为V的背包。第i件物品的体积是c(i),价值是w(i)。求解将哪些物品放入背包可使物品的体积总和不超过背包的容量,且价值总和最大。假设物品数量为10,背包的容量为300。每件物品的体积为[95,75,23, 73,50, 22,6,57,89, 98], 价值为[89, 59,19, 43,100,72,44,16,7, 64]。
2.2 Python 实现
import numpy as np import matplotlib.pyplot as plt from tqdm import tqdm#进度条设置 import matplotlib.pyplot as plt import matplotlib; matplotlib.use('TkAgg') from pylab import * mpl.rcParams['font.sans-serif'] = ['SimHei']# 指定默认字体 mpl.rcParams['axes.unicode_minus'] = False# 解决保存图像是负号'-'显示为方块的问题class BackPack(object): def __init__(self): self.Weight = [95,75,23,73,50,22,6,57,89,98]# 物品体积 self.Value = https://www.it610.com/article/[89, 59, 19, 43, 100, 72, 44, 16, 7, 64]# 物品价值 self.N = 100# 群体粒子个数 self.D = len(self.Weight)# 粒子维数 self.T = 100# 最大迭代次数 self.c1 = 1.5# 学习因子1 self.c2 = 1.5# 学习因子2 self.w = 1# 惯性因子,一般取1 self.V_max = 10# 速度最大值 self.V_min = -10# 速度最小值 self.Weight_max = 300# 背包容量 self.afa = 10# 惩罚系数 self.G=100 #迭代次数#=====初始化种群========= def init_x(self):""" :return: 随机生成的种群(二维list) """ X = np.random.choice([0, 1], size=(self.N, self.D)) return X #======初始化速度========== def init_v(self): """ :return: 速度 """ V = np.random.random(size=(self.N, self.D))##10维 return V#=====适应度值======== def fitness_func(self,X): """ :param X: 种群 :return: """ """计算粒子的的适应度值,也就是目标函数值,X 的维度是 size * 10 """ size = np.shape(X)[0] #种群个数 result = np.zeros((size, 1)) for i in range(size):# 遍历每一个粒子 fit = sum(X[i] * self.Value)# 物品价值 TotalSize = sum(X[i] * self.Weight)# 物品重量 if TotalSize <= self.Weight_max:# 如果小于限制重量 fit = fit result[i] = fit else: #fit = fit - self.afa * (TotalSize - self.Weight_max)# 对fit进行惩罚 fit=0 result[i] = fit return result# 我们要求result越大#=====速度更新公式======== def velocity_update(self,V, X, pbest, gbest): """ 根据速度更新公式更新每个粒子的速度 种群size=100 :param V: 粒子当前的速度矩阵,size*10 的矩阵 :param X: 粒子当前的位置矩阵,size*10 的矩阵 :param pbest: 每个粒子历史最优位置,size*10 的矩阵 :param gbest: 种群历史最优位置,1*10 的矩阵 """ r1 = np.random.random((self.N, 1)) #(粒子个数,1) r2 = np.random.random((self.N, 1)) V = self.w * V + self.c1 * r1 * (pbest - X) + self.c2 * r2 * (gbest - X)# 直接对照公式写就好了 #===防止越界处理=== V[V < self.V_min] = np.random.random() * (self.V_max - self.V_min) + self.V_min V[V > self.V_max] = np.random.random() * (self.V_max - self.V_min) +self.V_min return V#==========位置更新公式========== def position_update(self,X, V): """ 根据公式更新粒子的位置 :param X: 粒子当前的位置矩阵,维度是 size*10 :param V: 粒子当前的速度举着,维度是 size*10 return更新后的种群 """for i in range(self.N):# 遍历每一个粒子 # 修改速度为sigmoid形式V[i, :] = 1. / (1 + np.exp(-np.array(V[i, :]))) for j in range(self.D):# 遍历粒子中的每一个元素 rand = np.random.random()# 生成 0-1之间的随机数 if V[i, j] > rand: X[i, j] = 1 else: X[i, j] = 0 #对当前个体进行限制,放在超重 while np.sum(X[i]*self.Weight)>self.Weight_max:#如果当前粒子超重 X[i]=np.random.choice([0, 1], size=(1, self.D)) return Xdef update_pbest(self,X, fitness, pbest, pbestfitness, m): """ 更新个体最优 :param X: 当前种群 :param fitness: 当前每个粒子的适应度 :param pbest: 更新前的个体最优解 :param pbestfitness: 更新前的个体最优适应度 :param m: 粒子数量 :return: 更新后的个体最优解、个体最优适应度 """for i in range(m): if fitness[i] > pbestfitness[i]: pbest[i] = X[i] pbestfitness[i] = fitness[i] return pbest, pbestfitnessdef update_gbest(self,pbest, pbestfitness, gbest, gbestfitness, m): """ 更新全局最优解 :param pbest: 粒子群 :param pbestfitness: 个体适应度(个体最优) :param gbest: 全局最优解 :param gbestfitness: 全局最优解 :param m: 粒子数量 :return: gbest全局最优,g对应的全局最优解 """ for i in range(m): if pbestfitness[i] > gbestfitness: gbest = pbest[i] gbestfitness = pbestfitness[i] return gbest, gbestfitnessdef main(self): fitneess_value_list = []# 记录每次迭代过程中的种群适应度值变化 x = self.init_x()# 初始化x v = self.init_v()# 初始化v # 计算种群各个粒子的初始适应度值 p_fitness = self.fitness_func(x) # 计算种群的初始最优适应度值 g_fitness = p_fitness.max() # 讲添加到记录中 fitneess_value_list.append(g_fitness) # 初始的个体最优位置和种群最优位置 pbest = x gbest = x[p_fitness.argmax()]##===接下来就是不断迭代了======== for i in tqdm(range(self.G)): pbest=pbest.copy()#必须加,不然会被篡改值,造成结果错 p_fitness= p_fitness.copy()#必须加,不然会被篡改值,造成结果错 gbest=gbest.copy()#必须加,不然会被篡改值,造成结果错 g_fitness=g_fitness.copy()#必须加,不然会被篡改值,造成结果错 v = self.velocity_update(v, x, pbest, gbest)# 更新速度 x = self.position_update(x, v)# 更新位置 p_fitness2 = self.fitness_func(x)# 计算子代各个粒子的适应度# 更新每个粒子的历史最优位置 pbest, p_fitness=self.update_pbest(x, p_fitness2, pbest, p_fitness, self.N)#更新群体的最优位置 gbest, g_fitness=self.update_gbest(pbest, p_fitness, gbest, g_fitness, self.N)# 记录最优迭代结果 fitneess_value_list.append(g_fitness)print("最优适应度是:%.5f" % fitneess_value_list[-1]) print("最优解是", gbest) print('最优解对应的体积',np.sum(gbest*self.Weight)) print('最优解对应的价值',np.sum(gbest*self.Value))plt.plot(fitneess_value_list,label='迭代曲线') plt.xlabel('迭代次数') plt.ylabel('适应度') plt.legend() plt.show()if __name__=='__main__': pso = BackPack() pso.main()

#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片

2.3 Matlab 实现
%% 离散粒子群算法解决0-1背包问题 %% 初始化 clear all; %清除所有变量 close all; %清图 clc; %清屏 N=100; %群体粒子个数 D=10; %粒子维数 c1=1.5; %学习因子1 c2=1.5; %学习因子2 Wmax=0.8; %惯性权重最大值 Wmin=0.4; %惯性权重最小值 Vmax=10; %速度最大值 Vmin=-10; %速度最小值 V = 300; %背包容量 C = [95,75,23,73,50,22,6,57,89,98]; %物品体积 W = [89,59,19,43,100,72,44,16,7,64]; %物品价值 afa = 2; %惩罚函数系数 %% 初始化种群个体(限定位置和速度) x=randi(N,D); %随机获得二进制编码的初始种群,randint在后期版本中会被randi代替 v=rand(N,D) * (Vmax-Vmin)+Vmin; %% 初始化个体最优位置和最优值 p=x; pbest=ones(D,1); for i=1:D pbest(i)= func(x(i,:),C,W,V,afa); end %% 初始化全局最优位置和最优值 g=ones(1,D); gbest=-10000; for i=1:D if(pbest(i)>gbest) g=p(i,:); gbest=pbest(i); end end gb=ones(1,D); %% 按照公式依次迭代直到满足精度或者迭代次数 while 1>0 %无限迭代 for j=1:D %% 更新个体最优位置和最优值 if (func(x(j,:),C,W,V,afa)>pbest(j)) p(j,:)=x(j,:); pbest(j)=func(x(j,:),C,W,V,afa); end %% 更新全局最优位置和最优值 if(pbest(j)>gbest) g=p(j,:); gbest=pbest(j); end %% 计算动态惯性权重值 w=Wmax-(Wmax-Wmin)*i/D; %% 跟新位置和速度值 v(j,:)=w*v(j,:)+c1*rand*(p(j,:)-x(j,:))... +c2*rand*(g-x(j,:)); %% 边界条件处理 for ii=1:D if (v(j,ii)>Vmax)|(v(j,ii)< Vmin) v(j,ii)=rand * (Vmax-Vmin)+Vmin; end end vx(j,:)=1./(1+exp(-v(j,:))); for jj=1:D if vx(j,jj)>rand x(j,jj)=1; else x(j,jj)=0; end end end %% 记录历代全局最优值 gb(i)=gbest; if g.*C<=300 %如果满足条件 退出 breakendg; %最优个体 figure plot(gb) xlabel('迭代次数'); ylabel('适应度值'); title('适应度进化曲线') end

%% 适应度函数 function result = func(f,C,W,V,afa) fit = sum(f.*W); TotalSize = sum(f.*C); if TotalSize <= V fit = fit; else fit = fit - afa * (TotalSize - V); end result = fit;

3二进制粒子群算法的配电网故障定位(Matlab实现)
clc; clear all; %% 初始化参数 global Ij; %全局变量 global Vmax; %允许误差 MaxNum=120; %粒子最大迭代次数 D=12; %粒子的维数代表配电网的馈线区段总数 Particlesize=30; %粒子群规模 c1=2.1; %每个粒子的个体学习因子,也称为加速常数 c2=2.1; %每个粒子的社会学习因子,也称为加速常数 w=1; %惯性因子 Vmax=4; %粒子的最大飞翔速度 S_b=randi([0,1],Particlesize,D); %粒子所在的位置,randint在后期版本中会被randi代替 V=Vmax*rand(Particlesize,D); %粒子的飞翔速度 Ij=[1 1 1 1 0 1 1 1 0 0 1 1]; %FTU 反馈的值这里就是输入,请修改这里,看结果 fitness=F(S_b'); %这里注意下,要转置%% inline定义的适应度函数会使程序运行速度大大降低 for i=1:Particlesize f(i)=F(S_b(i,:)); %S_b配电网中各设备状态,为1表明设备故障,取0则设备正常。 end %% 个体最优与总群最优 personalbest_x=S_b; %这里是种群里的每个粒子都认为自己是最好的 personalbest_faval=f; [globalbest_favali]=min(personalbest_faval); %全局最优 globalbest_x=personalbest_x(i,:); k=1; Start=0; %% 这里就是把整个种群中的所有粒子都检查了一遍,保证当前最优 while k<=MaxNum Remember=globalbest_favali; for i=1:Particlesize f(i)=F(S_b(i,:)); %计算适应度函数值 if f(i)

function fitness=F(SB) global Ij; %% 期望函数Ij(SB):IE IE=zeros(1,length(Ij)); IE(1)=SB(1)|SB(2)|SB(3)|SB(4)|SB(5)|SB(6)|SB(7)|SB(8)|SB(9)|SB(10)|SB(11)|SB(12); IE(2)=SB(2)|SB(3)|SB(4)|SB(5)|SB(6)|SB(7)|SB(8)|SB(9)|SB(10)|SB(11)|SB(12); IE(3)=SB(3)|SB(4)|SB(5)|SB(6)|SB(7)|SB(8)|SB(9)|SB(10)|SB(11)|SB(12); IE(4)=SB(4)|SB(5); IE(5)=SB(5); IE(6)=SB(6)|SB(7)|SB(8)|SB(9)|SB(10)|SB(11)|SB(12); IE(7)=SB(7)|SB(8)|SB(9)|SB(10); IE(8)=SB(8)|SB(9)|SB(10); IE(9)=SB(9); IE(10)=SB(10); IE(11)=SB(11)|SB(12); IE(12)=SB(12); %% 构造配电网故障定位评价函数Fij:fitness fitness=sum(abs(Ij-IE))+0.5*sum(abs(SB)); end

function AN=Sigmoid(V) global Vmax; if V>Vmax AN=0.98; elseif V>-Vmax AN=1/(1+exp(-V)); else AN=-0.98; end end

#|二进制粒子群算法的配电网故障定位(Python&Matlab实现)
文章图片



    推荐阅读