遗传算法程序设计
- 2019 年 10 月 6 日
- 筆記
遗传算法程序思路
Begin t=0 % 遗传代数 初始化P(t) 计算P(t)的适应值 while(不满足条件时) begin t=t+1 从P(t-1)中选择P(t) %选择 重组P(t) %交叉和变异 计算P(t)的适应值 end
遗传算法参数设计原则
在单纯的遗传算法中,并不是总是收敛的,即使在单峰或者单调也是如此。这是因为种群的进化能力消失种群早熟。为避免这种现象,参数设计一般遵循以下原则:
(1)种群规模
当群体规模太小时,很明显会出现近亲交配,产生病态基因,生存和竞争的较小。而且太小的种群使得进化不能按照模式定理产生所预测的期望数量。种群规模太大时,结果难以收敛,浪费计算资源,结果稳健性下降,所以规模建议40-100。
(2)变异概率
概率太小时,种群多样性下降太快,容易导致有效基因丢失;变异概率太大时,具有竞争力的基因被破坏的概率又会有所增大。所以一般选择位于0.001-0.2。
(3)交配概率
交配是新种群最重要的手段。交配概率一般选择0.4-0.99
(4)进化代数
迭代次数小,算法不容易收敛;迭代次数大,算法早早收敛,后续过程除了浪费时间没有任何意义。进化代数建议100-500。
(5)种群初始化
初始化种群完全是随机的。在初始化种群的赋予之前,尽量进行一个大概的区间估计,以免偏差太大,增加算法的计算负担。
虽然遗传算法在matlab里面有工具箱,但是工具箱并不是万能的,很多情况下需要具体问题具体对待。另外,过度依赖于工具箱会使得无益于我们理解算法。现在我们用遗传算法来解决一个求最大值的问题。
求解函数最大值:

遗传算法程序设计:
import numpy as np import random from math import * bounds=[-2,2] #一维变量的取值范围 precision=0.0001 #运算精度 bounds_begin ,bounds_end = bounds[0] ,bounds[1] #计算满足所需精度需要至少多少染色体 BitLength=ceil(log((bounds_end-bounds_begin)/precision ,2)) popsize=50 #初始种群大小 Generationmax=200 #最大代数 pcrossover=0.9 #交配概率 pmutation=0.09 #变异概率 #产生初始种群 population = np.rint(np.random.rand(popsize,BitLength)) def func(x): """ 目标函数: y=200exp(-0.05x)*sin(x) x∈[-2,2] 参数:x 自变量 返回值:y 因变量 """ y = 200*exp(-0.05*x)*sin(x) return y def fitnessfun(population): """ 计算种群适应度和累计概率函数 fitnessfun() 参数:population 种群的染色体 返回值:[Fitvalue,cumsump] 适应度和累计概率 """ popsize=population.shape[0] Fitvalue=[] for i in range(0,popsize): x=0 for j in range(BitLength-1,-1,-1): x += population[i,j]*2**j xx=bounds_begin + x*(bounds_end-bounds_begin)/(2**BitLength-1) y=func(x)+230 #保证适应度为正值 Fitvalue.append(y) #计算选择概率 fsum=sum(Fitvalue) Perpopulation=[item/fsum for item in Fitvalue] #计算累计概率 cumsump=[Perpopulation[0]] for i in range(1,popsize): cumsump.append(cumsump[i-1]+Perpopulation[i]) return [Fitvalue,cumsump] def IfCroIfMut(mutorcro): """ 根据概率判断是否应该发生交叉或变异 轮盘赌算法 """ test=np.zeros(100) l=round(100*mutorcro) for i in range(l):test[i]=1 n=random.randint(0,99) return test[n] def mutation(snew,pmutation): """ 变异函数,使染色体发生变异 参数:snew,pmutation 种群染色体,变异概率 返回值:snnew 变异后的染色体 """ BitLength=snew.shape[0] snnew=snew pmm=IfCroIfMut(pmutation) if pmm: chb=random.randint(0,BitLength-1) snnew[chb]=1-snew[chb] return snnew def crossover(population,seln,pc): """ 交叉函数,使得两个染色体进行交叉 参数:population,seln,pc 种群染色体,交叉个体,交叉概率 返回值:交叉后的染色体 """ BitLength=population.shape[1] pcc=IfCroIfMut(pc) if pcc: chb=random.randint(0,BitLength-1) a=np.append(population[seln[0],0:chb],population[seln[1],chb:]) b=np.append(population[seln[1],0:chb],population[seln[0],chb:]) else: a=population[seln[0],:] b=population[seln[1],:] a1=a.reshape(1,a.shape[0]) b1=b.reshape(1,b.shape[0]) return np.append(a1,b1,axis=0) def Selection(population,cumsump): """ 新种群选择操作 """ i_,j_=np.random.rand(1,2)[0,0],np.random.rand(1,2)[0,1] prand1=[item - i_ for item in cumsump] prand2=[item - j_ for item in cumsump] i,j = 0,0 while prand1[i]<0 : i = i+1 while prand2[j]<0 : j = j+1 return [i,j] #计算适应度,返回适应度Fitvalue和累计概率cumsump [Fitvalue , cumsump] = fitnessfun(population) Generation=1 ymax=[] xmax=[] ymean=[] scnew=np.empty(shape=[0,16]) while Generation < Generationmax + 1: scnew=[] flag=1 for j in range(0,popsize,2): #选择操作 seln=Selection(population,cumsump) #交叉操作 scro=crossover(population,seln,pcrossover) a=mutation(scro[0,:],pmutation) b=mutation(scro[1,:],pmutation) a1=a.reshape(1,a.shape[0]) b1=b.reshape(1,b.shape[0]) if flag == 1: flag -=1 scnew=np.append(a1,b1,axis=0) else: scnew=np.append(scnew,a1,axis=0) scnew=np.append(scnew,b1,axis=0) population=scnew #产生了新的种群 [Fitvalue,cumsup]=fitnessfun(population) fmax,index=np.max(Fitvalue),np.argmax(Fitvalue) fmean=np.mean(Fitvalue) ymax.append(fmax) ymean.append(fmean) x=0 for j in range(BitLength-1,-1,-1): x += population[index,j]*2**j xx=bounds_begin + x*(bounds_end-bounds_begin)/(2**BitLength-1) xmax.append(xx) Generation += 1 print(func(xx))
以上就是今天的全部内容了,如果你喜欢的话,点个在看吧,你的支持是我最大的动力