目录
前言
代码功能优化
代码实现
前言
这篇博客单纯填一下上一篇多目标优化留下的坑(见下方链接),我上次在文末提到了前沿曲线会出现单点收敛的情况,这个是因为已经迭代到无法分层的情况了(所有点都在第一层),而还没到设定的迭代终止次数,所以它就一直迭代,而拥挤距离的判断条件又让极值点取到无穷了,这样综合作用的结果就是两端的极值点会一直被保留,久而久之,就剩下两个极值点了,其他点都被拥挤距离这个因素给筛掉了(我也没想到会是这个结果,emmmm)。
Python_多目标遗传算法_入门学习+代码实现
代码功能优化
做出了如下修改:
一、加入退出迭代的判断条件,即比较矩阵ps全为0的时候,所有个体均在第一层,此时记录迭代次数,并在本次迭代之后再迭代6次,退出进化过程。
二、修改拥挤距离判断,只确保两个点作为极大值和极小值对应为无穷的拥挤距离,这样就避免了出现多个点重合在两端的情况,多余的重合点把它们筛掉
三、加入输入变量,完成多目标优化的多输入情况,更具备普遍性。
代码实现
import numpy as np
import matplotlib.pyplot as plt
import math as mt
#import seaborn as sns
#sns.set_style('darkgrid')
#多输入多目标优化
def funclsin(x,y):
z=4*(x**2+y**2)
return z
def funclcos(x,y):
z=(x-5)**2+(y-5)**2
return z
#%%
pi=mt.pi
NP=50 #初始化种群数
L=15 #二进制位串长度
Pc=0.9 #交叉率
Pm=0.3 #变异率
G=10 #最大遗传代数
Xs=5 #x上限
Xx=0 #x下限
Ys=3 #y上限
Yy=0 #y下限
f=np.random.randint(0,high=2,size=(NP,L)) #生成随机初始种群
fy=np.random.randint(0,high=2,size=(NP,L)) #生成随机初始种群,这里把xy分开生成
x=np.zeros((1,100))[0].tolist()
y=np.zeros((1,100))[0].tolist()
tempx=np.zeros((1,100))[0].tolist()
tempy=np.zeros((1,100))[0].tolist()
f1trace=[] #记录第一个目标函数
f2trace=[] #记录第二个目标函数
diedazhongzhi=-1
#%%遗传算法循环
for i in range(G):
print(i)
f1=[]
f2=[]
nf=f #出新的种群,在其基础上进行交叉、变异
nf1=fy
for M in range(0,NP,2):
p=np.random.rand() #交叉
if p<Pc:
q=np.random.randint(0,high=2,size=(1,L))[0].tolist()
for j in range(L):
if q[j]==1:
temp=nf[M+1][j]
nf[M+1][j]=nf[M][j]
nf[M][j]=temp
temp=nf1[M+1][j]
nf1[M+1][j]=nf1[M][j]
nf1[M][j]=temp
j=1
while j<=(NP*Pm):
h=np.random.randint(1,high=NP) #变异
for k in range(round(L*Pm)):
g=np.random.randint(1,high=L)
nf[h][g]=(not nf[h][g])+0 #取反操作,python和matlab不一样
nf1[h][g]=(not nf1[h][g])+0
j+=1
#交叉变异结束之后,新一代nf加上前代f共2*NP个个体进行筛选
newf=np.vstack((f,nf)) #垂直方向累加两个f
newf1=np.vstack((fy,nf1))
for j in range(newf.shape[0]):
U=newf[j]
U1=newf1[j]
m=0
m1=0
for k in range(L):
m=U[k]*(2**(k-1))+m #将二进制解码为定义域范围内十进制
m1=U1[k]*(2**(k-1))+m1
x[j]=Xx+m*(Xs-Xx)/(2**(L-1))
y[j]=Yy+m1*(Ys-Yy)/(2**(L-1))
f1.append(funclsin(x[j],y[j]))
f2.append(funclcos(x[j],y[j]))
fs=[]
# plt.scatter(f1,f2)
# plt.savefig(r'C:\Users\王耀\Desktop\Genetic Algorithm\pic\exx'+str(i),bbox_inches = 'tight',pad_inches = 0,dpi =100)
# plt.close()
for j in range(len(f1)):
fs.append(f1[j])
fs.append(f2[j])
fs=np.array(fs)
fs=fs.reshape(len(f1),2) #把求解得到的适应度函数转换为多目标散点的形式
fs=fs.tolist()
ps=np.zeros((len(f1),len(f1))) #i,j=1,i支配j,我们希望点的值越小越好
for k in range(0,len(f1)):
for j in range(0,len(f1)):
if fs[k][0]<fs[j][0] and fs[k][1]<fs[j][1]:
ps[k][j]=1
elif fs[k][0]==fs[j][0] and fs[k][1]<fs[j][1]:
pass
elif fs[k][0]<fs[j][0] and fs[k][1]==fs[j][1]:
ps[k][j]=1
#这一步是这样的,ps是一个比较矩阵,如果100个点互相比(包括自己)
#如果被置1了,就说明被支配了,全部比完之后,纵向全为0,则说明没有点支配自己
jishu=[]
for k in range(len(ps)):
aa=0
for j in range(len(ps)):
if ps[j][k]==1:
aa+=1
jishu.append(aa)
if max(jishu)==0 and diedazhongzhi==-1:
print('迭代结束于{}代'.format(i))
diedazhongzhi=i+6
elif i==diedazhongzhi:
break
sortjishu=np.sort(jishu) #升序排序
index= np.argsort(jishu) #升序对应索引
aaa=list(set(sortjishu))
front=[[] for k in range(len(set(sortjishu)))]
for k in range(len(set(sortjishu))):
for j in range(len(index)):
if sortjishu[j]==aaa[k]:
front[k].append(index[j]) #记录对应的索引位置
#只是依靠分层的话,很可能最后会优化到一个点上
#所以需要加入拥挤距离来刻画点的分布情况
f=[]
fy=[]
for j in range(len(front)):
if len(f)==NP:
# print(2)
break
tempf=[]
tempfy=[]
for k in range(len(front[j])):
tempf.append(newf[front[j][k]]) #把第J层的染色体添加进入tempf中
tempfy.append(newf1[front[j][k]])
tempf1=[]
tempf2=[]
for M in range(len(tempf)): #计算第j层染色体的函数值,存在temf1.2中
U=tempf[M]
U1=tempfy[M]
m=0
m1=0
for k in range(L):
m=U[k]*(2**(k-1))+m #将二进制解码为定义域范围内十进制
m1=U1[k]*(2**(k-1))+m1
tempx[M]=Xx+m*(Xs-Xx)/(2**(L-1))
tempy[M]=Yy+m1*(Ys-Yy)/(2**(L-1))
tempf1.append(funclsin(tempx[M],tempy[M]))
tempf2.append(funclcos(tempx[M],tempy[M]))
#对f1计算其拥挤距离,此时与f2无关。
tempf1index=np.argsort(tempf1) #tempf1升序排序
distance=np.zeros(len(tempf1))
#将两端位置值置为正负无穷
#导致收敛到两端上,我现在只取两个极值点,避免重复
distance[tempf1index[0]]=float('inf')
distance[tempf1index[-1]]=float('inf')
#计算每个点在f1下的拥挤距离
for k in range(len(tempf1index)):
if abs(distance[tempf1index[k]])<10: #把极值点排除在外,极值点如果不排除呢?
distance[tempf1index[k]]=(tempf1[tempf1index[k+1]]-tempf1[tempf1index[k-1]])/(max(tempf1)-min(tempf1))
else:
continue
#对f2计算拥挤距离,与f1无关
tempf1index1=np.argsort(tempf2) #tempf2升序排序
distance1=np.zeros(len(tempf1))
#将两端位置值置为正负无穷
distance1[tempf1index1[0]]=float('inf')
distance1[tempf1index1[-1]]=float('inf')
for k in range(len(tempf1index1)):
if abs(distance1[tempf1index1[k]])<10: #把极值点排除在外
distance1[tempf1index1[k]]=(tempf2[tempf1index1[k+1]]-tempf2[tempf1index1[k-1]])/(max(tempf2)-min(tempf2))
else:
continue
sumdis=[] #当收敛到一个点时,拥挤距离就失去意义了
for k in range(len(distance)):
sundistance=distance[k]+distance1[k]
sumdis.append(sundistance)
disindex=np.argsort(sumdis)[::-1] #sumdis降序排序(拥挤距离越大越好)
for k in range(len(sumdis)):
f.append(tempf[disindex[k]])
fy.append(tempf[disindex[k]])
if len(f)==NP:
break
else:
continue
f1=[]
f2=[]
for j in range(len(f)):
U=f[j]
U1=tempfy[M]
m=0
m1=0
for k in range(L):
m=U[k]*(2**(k-1))+m #将二进制解码为定义域范围内十进制
m1=U1[k]*(2**(k-1))+m1
x[j]=Xx+m*(Xs-Xx)/(2**(L-1))
y[j]=Yy+m1*(Ys-Yy)/(2**(L-1))
f1.append(funclsin(x[j],y[j]))
f2.append(funclcos(x[j],y[j]))
plt.scatter(f1,f2)
plt.savefig(r'C:\Users\王耀\Desktop\Genetic Algorithm\pic1\exx1'+str(i),bbox_inches = 'tight',pad_inches = 0,dpi =100)
plt.close()
|