遺傳演算法程式設計

  • 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))

以上就是今天的全部內容了,如果你喜歡的話,點個在看吧,你的支援是我最大的動力