Python_多目标遗传算法_多输入代码实现

目录

前言

代码功能优化

代码实现


前言

这篇博客单纯填一下上一篇多目标优化留下的坑(见下方链接),我上次在文末提到了前沿曲线会出现单点收敛的情况,这个是因为已经迭代到无法分层的情况了(所有点都在第一层),而还没到设定的迭代终止次数,所以它就一直迭代,而拥挤距离的判断条件又让极值点取到无穷了,这样综合作用的结果就是两端的极值点会一直被保留,久而久之,就剩下两个极值点了,其他点都被拥挤距离这个因素给筛掉了(我也没想到会是这个结果,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.2  #变异率
G=20    #最大遗传代数
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(tempfy[disindex[k]])
            if len(f)==NP:
                break
            else:
                continue
        f1=[]
        f2=[]      
        for j in range(len(f)):
            U=f[j]
            U1=fy[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]))       
    plt.scatter(f1,f2)
    plt.savefig(r'C:\Users\sc35131\Desktop\Genetic Algorithm\pic\\'+str(i),bbox_inches = 'tight',pad_inches = 0,dpi =100)
    plt.close()

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值