遺傳演算法程式設計
- 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))
以上就是今天的全部內容了,如果你喜歡的話,點個在看吧,你的支援是我最大的動力