假设函数,其中。试用遗传算法求解y的最大值,请仿照例4.1(参考课件第三章“遗传算法的流程”)写出关键的求解步骤。
import random
import math
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
'''产生初始种群'''
def initialpopulation(NP,n,x0,x1):
'''NP代表种群规模,n代表目标函数的未知量的个数;
x0代表未知数取值的下限,x1代表未知数取值的上限'''
initial=[]
for i in range(NP):
n_initial=[random.uniform(x0,x1) for j in range(n)]
initial.append(n_initial)
return initial
'''标定适值函数'''
def fitnessfunction(X):
'''X代表存储各个未知量的取值的列表'''
return 1/(math.sqrt(X[0]**2)+math.sqrt(X[1]**2)+math.sqrt(X[2]**2)+math.sqrt(X[3]**2)+1)
'''采用轮盘赌选择算法选择个体'''
def selection(NP,X0):
'''NP代表种群规模,X0代表种群'''
#计算种群中各个个体的适应值
value=[]
for i in range(NP):
value.append(fitnessfunction(X0[i]))
'''计算适应度和累计概率函数'''
#计算选择概率
fsum=0
for i in range(NP):
fsum=fsum+value[i]**2
value_ratio=[]
for i in range(NP):
value_ratio.append((value[i]**2)/fsum)
#计算累加概率
value_ratio_add=[]
for i in range(NP):
if i==0:
value_ratio_add.append(value_ratio[i])
else:
value_ratio_add.append(value_ratio_add[i-1]+value_ratio[i])
#产生[0,1]之间的随机数,进行NP次轮转
random_ratio=[random.uniform(0,1) for i in range(NP)]
#进行轮盘赌选择
choose_index=[] #从0开始计
value_ratio_add0=[0,*value_ratio_add] #在列表value_ratio_add的最前面加上一个0
for i in range(NP):
for j in range(NP):
if random_ratio[i]>=value_ratio_add0[j] and random_ratio[i]=history_max:
history_max=value_max
history.append(history_max)
history_X0.append(valueX0_max)
else:
history.append(history_max)
history_X0.append(history_X0[i-1])
print("第{}代:{} value_max={}".format(i + 1, history_X0[i], history[i]))
'''选择'''
X1=selection(NP,X0)
'''双切点交叉运算'''
X2=crossover1(X1,pc,NP,4)
'''变异运算'''
X3=mutation(X2,pm,NP,4,-10,10)
X0=X3
print("最优解Best={}".format(history[-1]))
print("---------------------------------------------------------------进程结束---------------------------------------------------------------")
'''绘制随着代数的增加每一代的最大适应值和历史最大适应值的变化'''
ax1=plt.subplot(111)
ax1.plot(range(1,NG+1),fitnessmax_list,c='plum',label="每一代的最大适应值")
ax1.set_ylabel("适应值")
ax1.set_xlabel("代数")
plt.title("遗传算法(单切点交叉)每一代的最大适应值随代数的变化")
ax1.legend()
plt.show()
ax2=plt.subplot(111)
ax2.plot(range(1,NG+1),history,c='orange',label="历史最大适应值")
ax2.set_ylabel("适应值")
ax2.set_xlabel("代数")
plt.title("遗传算法(单切点交叉)的优化过程")
ax2.legend()
plt.show()
return fitnessmax_list[-1],history[-1],X0max_list[-1],history_X0[-1]
'''使用双切点交叉的遗传算法'''
def GA2(NP,NG,n,x0,x1,pc,pm):
'''NP代表种群规模,NG代表最大代数,n代表一个染色体的基因数
x0代表未知数取值的下限,x1代表未知数取值的上限
pc代表交叉概率,pm代表变异概率'''
#遗传算法——单切点交叉
print("----------------------------------------------------------遗传算法(双切点交叉)----------------------------------------------------------")
#产生初始种群
X0=initialpopulation(NP,n,x0,x1)
#存储最大适应值和对应的函数值的列表
fitnessmax_list=[]
X0max_list=[]
#历史最大适应值
history_max=0
history=[]
history_X0=[]
for i in range(NG):
'''得到种群的最大适应值和对应的染色体'''
value_max,valueX0_max=fitnessmax(X0,NP)
fitnessmax_list.append(value_max)
X0max_list.append(valueX0_max)
if i==0:
history_max=value_max
history.append(history_max)
history_X0.append(valueX0_max)
else:
if value_max>=history_max:
history_max=value_max
history.append(history_max)
history_X0.append(valueX0_max)
else:
history.append(history_max)
history_X0.append(history_X0[i-1])
print("第{}代:{} value_max={}".format(i + 1, history_X0[i], history[i]))
'''选择'''
X1=selection(NP,X0)
'''双切点交叉运算'''
X2=crossover2(X1,pc,NP,4)
'''变异运算'''
X3=mutation(X2,pm,NP,4,-10,10)
X0=X3
print("最优解Best={}".format(history[-1]))
print("---------------------------------------------------------------进程结束---------------------------------------------------------------")
'''绘制随着代数的增加最大适应值的变化'''
ax1=plt.subplot(111)
ax1.plot(range(1,NG+1),fitnessmax_list,c='plum',label="每一代的最大适应值")
ax1.set_ylabel("适应值")
ax1.set_xlabel("代数")
plt.title("遗传算法(双切点交叉)每一代的最大适应值随代数的变化")
ax1.legend()
plt.show()
ax2=plt.subplot(111)
ax2.plot(range(1,NG+1),history,c='orange',label="历史最大适应值")
ax2.set_ylabel("适应值")
ax2.set_xlabel("代数")
plt.title("遗传算法(双切点交叉)的优化过程")
ax2.legend()
plt.show()
return fitnessmax_list[-1],history[-1],X0max_list[-1],history_X0[-1]
'''主函数'''
if __name__=="__main__":
'''规定最大代数'''
NG=1000
'''规定种群规模'''
NP=100
'''规定交叉率'''
pc=0.9
'''规定变异率'''
pm=0.1
'''规定一个染色体上的基因数'''
n=4
'''规定未知数的下限'''
x0=-10
'''规定未知数的上限'''
x1=10
'''存储遗传算法中单切点交叉和双切点交叉最后得到的最大适应值及对应的未知数取值'''
fitness_max=[]
fitnessX0_max=[]
'''进行单切点交叉的遗传算法'''
value_max1,historymax1,valueX0_max1,historymaxX0_1=GA1(NP,NG,n,x0,x1,pc,pm)
fitness_max.append(historymax1)
fitnessX0_max.append(historymaxX0_1)
'''进行双切点交叉的遗传运算'''
value_max2,historymax2,valueX0_max2,historymaxX0_2=GA2(NP,NG,n,x0,x1,pc,pm)
fitness_max.append(historymax2)
fitnessX0_max.append(historymaxX0_2)
print("单切点交叉的最优解:{}\t对应的未知数取值:{}\n双切点交叉的最优解:{}\t对应的未知数取值:{}".format(fitness_max[0],fitnessX0_max[0],fitness_max[1],fitnessX0_max[1]))