作者majoyun (R_pu)
看板Python
标题[问题] 多目标演算法
时间Tue Oct 16 23:48:12 2018
小妹最近在写nsga2,目前正在将matlab的程式码,转换成python
但是一直遇到瓶颈,明明是写多目标,最後出来搞得跟单目标一样...
为何总是找到同一个解....
尽自己最大的努力去转换程式语法,
网路上虽然有nsga2的程式码可以下载,但问题定义的方式有点落差
所以没办法直接拿现成的来用QQ
程式码有点又臭又长,希望有人兄愿意尝试解救一下
是否能站内信交流呢~
长得很丑的程式码就不放上来干扰视听了
下台鞠躬
p.s
另外请教板上众高手,小妹目前立马要对演算法熟悉以及熟悉python
是否有需要请高手来一对一教学?
若版上高手认为可以针对小妹的问题来教学
也请欢迎站内信(如有违反版规,请板主通知,会删除这段)
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 223.137.72.169
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Python/M.1539704897.A.8CC.html
※ 编辑: majoyun (223.137.72.169), 10/17/2018 00:07:55
1F:→ femlro: 直接问比较快 就算得不到答案也有人可以提供你线索 10/17 11:49
import numpy as np; import random; import math
#问题定义
nvar=3; varsize=[1,nvar]
varmin=-5; varmax=5 #变数上下界
##cost适应函数
def costfun(x,nobj):
n=np.size(x)#n为x的尺寸
z1=1-math.exp(-np.sum((x-1/math.sqrt(n))**2))
z2=1-math.exp(-np.sum((x+1/math.sqrt(n))**2))
z=[z1, z2]
nobj=np.size(z)
return z,nobj
##支配解函数
def Dom(x,y):
x=np.array(x)
y=np.array(y)
b=((x<=y).all()) and ((x<y).any())
return b
##问题求解需要的结构建立
empty_sol_content={'position':list(), 'cost':list(), 'rank':list(),
'DominSet':int(),'DominCount':list(),
'CroDistance':list()}
##问题参数
problem1={'npop':50, 'pcoss':0.3, 'pmuta':0.9, 'mu':1,'maxit':100,
'sigma':0.1*(varmax-varmin)}
npop=problem1['npop']; pcoss=problem1['pcoss']; pmuta=problem1['pmuta']
mu=problem1['mu']; sigma=problem1['sigma'];maxit=problem1['maxit']
problem2={'ncoss':2*round(pcoss*npop/2), 'nmuta':round(pmuta*npop)}
ncoss=problem2['ncoss']; nmuta=problem2['nmuta']
##产生初始解
pop=list()#初始解空集合
for i in range(0,npop):
pop.append(empty_sol_content.copy())
pop[i]['position']=np.random.uniform(varmin,varmax,size=varsize)
pop[i]['cost'],nobj=costfun(pop[i]['position'],nobj=list())
npop=np.size(pop)
##基因交叉函数
def crossover(x1,x2):
y1=list();y2=list()
alpha=np.random.uniform(0,1,size=np.size(x1))
y1=alpha*x1+(1-alpha)*x2
y2=alpha*x2+(1-alpha)*x1
return y1,y2
##基因变异函数
def mutate(x,mu,sigma):
sigma=int(sigma)
nvar=np.size(x)
x=x.reshape([1,3])
nmu=math.ceil(mu*nvar)
j=np.random.choice(nvar,nmu)
if np.size(sigma)>1:
sigma=sigma[j]
y=x
y[0][j]=x[0][j]+np.dot(sigma,np.random.randn(np.size(j)))
return y
#######
po11=np.array([0.,0.,0.])
po22=np.array([0.,0.,0.])
for it in range(maxit):
#popc1=np.tile(pop.copy(),int(ncoss/2))
popc1=pop[:int(ncoss/2)]
#popc2=np.tile(empty_sol_content.copy(),int(ncoss/2))
popc2=pop[:int(ncoss/2)]
popc1=list(popc1);popc2=list(popc2)#增加转list
for k in range(int(ncoss/2)):
i1=np.random.randint(0,npop)
p1=pop[i1]
i2=np.random.randint(0,npop)
p2=pop[i2]
po1,po2=crossover(p1['position'],p2['position'])
po11=np.vstack((po11,po1))
po22=np.vstack((po22,po2))
po11=np.delete(po11,0,0)
po22=np.delete(po22,0,0)
po=np.vstack((po11,po22))
popc=np.hstack((popc1,popc2))
popc=list(popc)
for k in range(len(popc)):
popc[k]['position']=po[k]
popc[k]['cost'],nobj=costfun(popc[k]['position'],nobj=list())
####进入基因变异
#popm=np.tile(empty_sol_content.copy(),nmuta)
popm=pop[:nmuta]
popm=list(popm)
for k in range(nmuta):
i=np.random.randint(0,npop)
p=pop[i]
popm[k]['position']=mutate(p['position'],mu,sigma)
popm[k]['cost'],nobj=costfun(popm[k]['position'],nobj=list())
pop=np.hstack((pop,popc))
pop=np.hstack((pop,popm))
pop=list(pop)
#'DominedCount'被支配数、DominSet支配解
##非支配排序
for i in range(len(pop)):
pop[i]['DominSet']=[]
pop[i]['DominCount']=0
F=list()
Q=list()
for i in range(len(pop)):
for j in range(i+1,len(pop)):
p=pop[i]
q=pop[j]
if Dom(p['cost'],q['cost']):
p['DominSet']=np.hstack((p['DominSet'],j))
p['DominSet'].astype(np.int)
q['DominCount']=q['DominCount']+1
if Dom(q['cost'],p['cost']):
q['DominSet']=np.hstack((q['DominSet'],i))
q['DominSet'].astype(np.int)
p['DominCount']=p['DominCount']+1
pop[i]=p
pop[j]=q
if pop[i]['DominCount']==0:
F.append(i)
pop[i]['rank']=0
Q.append(F)#把F变成一组放到Q里面
F=Q
F1=list()
F1=F
k=0
while True:
Q=list()
F=np.array(F)
for i in F[0]:
p=pop[i]
for j in p['DominSet']:
j=j.astype(np.int64)
q=pop[j]
q['DominCount']=q['DominCount']-1
if q['DominCount']==0:
Q.append(j)
q['rank']=k+1
pop[j]=q
if Q==[]:
break
F1.append(Q)
F=list()
F.append(F1[k+1])
k=k+1
F=F1
##拥挤距离
nf=len(F1)
costs0=list()
for k in range(nf):
F=F1[k]
costs=np.array([[0.],[0.]])
for f in range(np.size(F1[k])):
costs0=pop[F[f]]['cost'][0]#把在F[k]中所有的cost都叫出来
costs1=pop[F[f]]['cost'][1]
costs0=np.vstack((costs0,costs1))#转乘矩阵属性
costs=np.hstack((costs,costs0))#vstack合并在垂直方向上
costs=np.delete(costs,0,1)#把第一row删除(原本创建的[0,0]矩阵)
nobj=len(np.mat(costs))#nobj为cost的row数
n=np.size(costs,1)
d=np.zeros((n,nobj), dtype=np.float)
cj=list()
for j in range(nobj):
cj=sorted(costs[j])#将costs由小至大排序
so=np.argsort(costs[j], axis=0)#排序後的costs下标情况
d[so[0],j]=np.inf
if n-1>1:
for i in range(1,n-1):#matlab i=2:n-1
d[so[i],j]=abs(cj[i+1]-cj[i-1])/abs(cj[0]-cj[-1])
d[so[-1],j]=np.inf
d[so[-1],j]=np.inf
for i in range(n):
pop[F1[k][i]]['CroDistance']=sum(d[i,:])#F中的每一个都算好拥挤距离
##拥挤距离计算完毕
#
#sortingPopulation
#先排rank
rso=np.zeros(len(pop))
Rso=list()
RSO=list()
for i in range(len(pop)):
rso[i]=pop[i]['rank']#rso里面是现在pop的rank状态
rso=rso.astype(np.int64)
Rso=sorted(rso)#Rso把rso由小到大排序,接下来要知道排序的index
RSO=np.argsort(rso,axis=0)#pop比须按照RSO顺序来排列rank才会由大到小
pop1=pop.copy()#pop1要把pop按照RSO重新排列
for i in range(len(pop)):
for j in [RSO[i]]:
pop1[i]=pop[j]#pop1已经将所有姐都按照rank小至大排列
##再把每个rank中的拥挤距离由大到小排列
maxRso=max(Rso)
Crod=list()#把crod排序之後放进来
CROD=list()#排序之後crod的index放进来
CDSO=np.zeros(len(pop))
pop2=pop.copy()
for R in range(maxRso+1):
crod=list()
F=list()
for i in range(len(pop1)):
if pop1[i]['rank'] is R:
crod.append(pop1[i]['CroDistance'])
F=np.hstack((F,i))
crod=np.array(crod)
Crod=crod[np.argsort(-crod)]
CROD=np.argsort(-crod,axis=0)
for f in range(len(F)):
CDSO[int(F[f])]=F[CROD[f]]
for i in range(len(pop)):
pop2[i]=pop1[int(CDSO[i])]#pop2是用pop1的rank分组排列拥挤距离
ranks=[]
for i in range(len(pop)):
ranks=np.hstack((ranks,pop2[i]['rank']))
maxrank=max(ranks).astype(np.int64)
F=list()
F2=list()
for r in range(maxrank+1):
for i in range(len(pop2)):
if pop2[i]['rank'] is r:
F2.append(i)
F.append(F2)#F是把同样rank的分成一组
F2=list()
pop=pop2
##F2 & pop2 是输出的参数
pop=pop[:npop]
##########
ranks=[]
for i in range(len(pop)):
ranks=np.hstack((ranks,pop[i]['rank']))
maxrank=max(ranks).astype(np.int64)
F=list()
F2=list()
for r in range(maxrank+1):
for i in range(len(pop)):
if pop2[i]['rank'] is r:
F2.append(i)
F.append(F2)#F是把同样rank的分成一组
F2=list()
##F2 & pop2 是输出的参数
## store F1
F1=list()
for i in F[0]:
F1.append(pop[F[0][i]])
sf=[]
for i in range(np.size(F1)):
sf.append(F1[i]['cost'])
sf=np.array(sf)
#显示迭代资讯
print('Iteration:',it);
print('Num of F1 Members:',np.size(F1))
import matplotlib.pyplot as plt
x=sf[:,0]
y=sf[:,1]
x=list(x)
y=list(y)
plt.ion()
plt.title('pcoss:0.7, pmuta:0.4, mu:0.2', fontsize=18)
plt.scatter(x,y)
#plt.xlim((0,1))
#plt.ylim((0,1))
plt.ioff()
plt.pause(0.1)
plt.show()
※ 编辑: majoyun (223.137.72.169), 10/17/2018 15:57:59
2F:→ david855008: 怎麽不放贴code网站 10/21 02:33
3F:推 Neisseria: github gist 是你的好朋友,有微软加持过更好用 10/21 14:18