利用简单遗传算法计算函数的最值
作者:袁江磊
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
pd.set_option('display.max_rows', None)# 显示所有行
#表格创建
def pd_creat():
na=[['na']*6]*number
pd_all=pd.DataFrame(na,columns=['基因x','基因y','基因z','代数','适应度','适应度排名'])
return pd_all
#初始化种群
def init_population():
all_process = pd.DataFrame(['start'] * 6, columns=['start'], index=['基因x', '基因y', '基因z', '代数', '适应度',
'适应度排名']).T # 整个进化过程[[[种群成员],[适应度]],[[种群成员],[适应度]],...]
pd_all=pd_creat()
all_process = all_process.append(pd_all)
all_process['代数']=1
all_process.drop('start',axis=0,inplace=True)
for i in range(number):
init_popula=np.random.randint(init_range[0], init_range[1], 3).tolist()
all_process.ix[i,['基因x','基因y','基因z']]=init_popula
all_process.ix[i, ['适应度']]=fitness(init_popula[0],init_popula[1],init_popula[2])
all_process=all_process.sort_values(['适应度'])
all_process['适应度排名']=range(1,number+1)
return all_process
#计算种群适应性数值
def fitness( x, y, z):
fit = (x-3.14)**2+3.7*np.cos(y-8.43)+(z-3.43)**2-54.3
return fit
#生成新一代
def breed(genera,all_process):
new_generation=pd_creat()#添加新一代扩展表
last_generation = all_process.ix[all_process['代数']==genera-1]#上一代
new_generation['代数']=genera
last_generation.index=range(1,number+1)
new_generation.index=range(1,number+1)
#染色体两两交叉
best_genera=last_generation.ix[last_generation['适应度排名']<=round(number*p_best)]
for i in range(1,int(number/2)+1):
first=last_generation.ix[2*i-1, ['基因x', '基因y', '基因z']]
first['基因z']=last_generation.ix[2*i,['基因x', '基因y', '基因z']][2]
second = last_generation.ix[2*i, ['基因x', '基因y', '基因z']]
second['基因z'] = last_generation.ix[2*i-1, ['基因x', '基因y', '基因z']][2]
#发生变异
first[0]+=p_change*np.random.normal(0,1,1)[0]
second[0] += p_change*np.random.normal(0,1,1)[0]
first[1] += p_change*np.random.normal(0, 1, 1)[0]
second[1] += p_change*np.random.normal(0, 1, 1)[0]
first[2] += p_change*np.random.normal(0, 1, 1)[0]
second[2] += p_change*np.random.normal(0, 1, 1)[0]
new_generation.ix[2*i-1,['基因x', '基因y', '基因z']]=first
new_generation.ix[2*i, ['基因x', '基因y', '基因z']] = second
#计算刚交叉完后的新一代适应度集排名
for i in range(1,number+1):
init_popula=new_generation.ix[i,['基因x','基因y','基因z']]
new_generation.ix[i, ['适应度']]=fitness(init_popula[0],init_popula[1],init_popula[2])
new_generation = new_generation.sort_values(['适应度'])
new_generation['适应度排名'] = range(1, number + 1)
#将上一代最优质个体留下并加入新一代
new_generation=new_generation.ix[new_generation['适应度排名']<=number-2]
new_generation=new_generation.append(last_generation.ix[last_generation['适应度排名']<=2])
new_generation.index=range(1,number+1)
new_generation['代数'] = genera
# 计算留下上一代最优质的数据后的新一代适应度集排名
for i in range(1, number + 1):
init_popula = new_generation.ix[i, ['基因x', '基因y', '基因z']]
new_generation.ix[i, ['适应度']] = fitness(init_popula[0], init_popula[1], init_popula[2])
new_generation = new_generation.sort_values(['适应度'])
new_generation['适应度排名'] = range(1, number + 1)
X=new_generation.ix[new_generation['适应度排名']==1]
print('x'+str(X['基因x'].tolist()[0])+'y:'+str(X['基因y'].tolist()[0])+'z'+str(X['基因z'].tolist()[0])+'适应度:'+str(X['适应度'].tolist()[0]))
all_process=all_process.append(new_generation)#将新一代添加至总表中
return all_process
def main(last_genera,all_process):
#迭代至第n代
out_count = 0
for genera in range(2,last_genera):
all_process=breed(genera, all_process)
print('已经生成'+str(genera)+'代,已经完成'+str(round(genera/last_genera,2)*100)+'%')
last_fit = all_process.ix[all_process['适应度排名'] == 1]['适应度'].tolist()[-2]
fit = all_process.ix[all_process['适应度排名'] == 1]['适应度'].tolist()[-1]
# 衡量每次迭代最优适应度变化量,当变化量连续小于某个次数30时将终止迭代
delt = (fit - last_fit) / last_fit
if abs(delt) < p_out:
out_count += 1
if out_count > 30:
break
#print(out_count)
return all_process
if __name__=='__main__':
number = 14 # 种群数量
p_best=1/4#留下上一代中最优比例
p_change=0.2#变异程度
p_out=0.0007#当每代最优值变化幅度小于此值时便会终止迭代
init_range=[4,8]#初始种族数据范围
all_process=pd_creat()
all_process=init_population()#创建初始种群
#向下迭代一百次
all_process=main(1000,all_process)
data_best=all_process.ix[all_process['适应度排名']==1]#查看排名第一的数值演变
print(data_best)
plt.plot(data_best['代数'],data_best['适应度'])
plt.show()
#print(all_process.ix[all_process['代数']<=20])