遺傳算法python實現

最近看了一下遺傳算法,使用輪盤賭選擇染色體,使用單點交叉,下面是代碼實現(python3)python

 

  1 import numpy as np
  2 import random
  3 from scipy.optimize import fsolve
  4 import matplotlib.pyplot as plt
  5 import heapq
  6 
  7 # 求染色體長度
  8 def getEncodeLength(decisionvariables, delta):
  9     # 將每一個變量的編碼長度放入數組
 10     lengths = []
 11     for decisionvar in decisionvariables:
 12         uper = decisionvar[1]
 13         low = decisionvar[0]
 14         # res()返回一個數組
 15         res = fsolve(lambda x: ((uper - low) / delta - 2 ** x + 1), 30)
 16         # ceil()向上取整
 17         length = int(np.ceil(res[0]))
 18         lengths.append(length)
 19     # print("染色體長度:", lengths)
 20     return lengths
 21 
 22 
 23 # 隨機生成初始化種羣
 24 def getinitialPopulation(length, populationSize):
 25     chromsomes = np.zeros((populationSize, length), dtype=np.int)
 26     for popusize in range(populationSize):
 27         # np.random.randit()產生[0,2)之間的隨機整數,第三個參數表示隨機數的數量
 28         chromsomes[popusize, :] = np.random.randint(0, 2, length)
 29     return chromsomes
 30 
 31 
 32 # 染色體解碼獲得表現形的解
 33 def getDecode(population, encodelength, decisionvariables, delta):
 34     # 獲得population中有幾個元素
 35     populationsize = population.shape[0]
 36     length = len(encodelength)
 37     decodeVariables = np.zeros((populationsize, length), dtype=np.float)
 38     # 將染色體拆分添加到解碼數組decodeVariables中
 39     for i, populationchild in enumerate(population):
 40         # 設置起始點
 41         start = 0
 42         for j, lengthchild in enumerate(encodelength):
 43             power = lengthchild - 1
 44             decimal = 0
 45             for k in range(start, start + lengthchild):
 46                 # 二進制轉爲十進制
 47                 decimal += populationchild[k] * (2 ** power)
 48                 power = power - 1
 49             # 從下一個染色體開始
 50             start = lengthchild
 51             lower = decisionvariables[j][0]
 52             uper = decisionvariables[j][1]
 53             # 轉換爲表現形
 54             decodevalue = lower + decimal * (uper - lower) / (2 ** lengthchild - 1)
 55             # 將解添加到數組中
 56             decodeVariables[i][j] = decodevalue
 57     return decodeVariables
 58 
 59 
 60 # 獲得每一個個體的適應度值及累計機率
 61 def getFitnessValue(func, decode):
 62     # 獲得種羣的規模和決策變量的個數
 63     popusize, decisionvar = decode.shape
 64     # 初始化適應度值空間
 65     fitnessValue = np.zeros((popusize, 1))
 66     for popunum in range(popusize):
 67         fitnessValue[popunum][0] = func(decode[popunum][0], decode[popunum][1])
 68     # 獲得每一個個體被選擇的機率
 69     probability = fitnessValue / np.sum(fitnessValue)
 70     # 獲得每一個染色體被選中的累積機率,用於輪盤賭算子使用
 71     cum_probability = np.cumsum(probability)
 72     return fitnessValue, cum_probability
 73 
 74 
 75 # 選擇新的種羣
 76 def selectNewPopulation(decodepopu, cum_probability):
 77     # 獲取種羣的規模和
 78     m, n = decodepopu.shape
 79     # 初始化新種羣
 80     newPopulation = np.zeros((m, n))
 81     for i in range(m):
 82         # 產生一個0到1之間的隨機數
 83         randomnum = np.random.random()
 84         # 輪盤賭選擇
 85         for j in range(m):
 86             if (randomnum < cum_probability[j]):
 87                 newPopulation[i] = decodepopu[j]
 88                 break
 89     return newPopulation
 90 
 91 
 92 # 新種羣交叉
 93 def crossNewPopulation(newpopu, prob):
 94     m, n = newpopu.shape
 95     # uint8將數值轉換爲無符號整型
 96     numbers = np.uint8(m * prob)
 97     # 若是選擇的交叉數量爲奇數,則數量加1
 98     if numbers % 2 != 0:
 99         numbers = numbers + 1
100     # 初始化新的交叉種羣
101     updatepopulation = np.zeros((m, n), dtype=np.uint8)
102     # 隨機生成須要交叉的染色體的索引號
103     index = random.sample(range(m), numbers)
104     # 不須要交叉的染色體直接複製到新的種羣中
105     for i in range(m):
106         if not index.__contains__(i):
107             updatepopulation[i] = newpopu[i]
108     # 交叉操做
109     j = 0
110     while j < numbers:
111         # 隨機生成一個交叉點,np.random.randint()返回的是一個列表
112         crosspoint = np.random.randint(0, n, 1)
113         crossPoint = crosspoint[0]
114         # a = index[j]
115         # b = index[j+1]
116         updatepopulation[index[j]][0:crossPoint] = newpopu[index[j]][0:crossPoint]
117         updatepopulation[index[j]][crossPoint:] = newpopu[index[j + 1]][crossPoint:]
118         updatepopulation[index[j + 1]][0:crossPoint] = newpopu[j + 1][0:crossPoint]
119         updatepopulation[index[j + 1]][crossPoint:] = newpopu[index[j]][crossPoint:]
120         j = j + 2
121     return updatepopulation
122 
123 
124 # 變異操做
125 def mutation(crosspopulation, mutaprob):
126     # 初始化變異種羣
127     mutationpopu = np.copy(crosspopulation)
128     m, n = crosspopulation.shape
129     # 計算須要變異的基因數量
130     mutationnums = np.uint8(m * n * mutaprob)
131     # 隨機生成變異基因的位置
132     mutationindex = random.sample(range(m * n), mutationnums)
133     # 變異操做
134     for geneindex in mutationindex:
135         # np.floor()向下取整返回的是float型
136         row = np.uint8(np.floor(geneindex / n))
137         colume = geneindex % n
138         if mutationpopu[row][colume] == 0:
139             mutationpopu[row][colume] = 1
140         else:
141             mutationpopu[row][colume] = 0
142     return mutationpopu
143 
144 # 找到從新生成的種羣中適應度值最大的染色體生成新種羣
145 def findMaxPopulation(population, maxevaluation, maxSize):
146     #將數組轉換爲列表
147     maxevalue = maxevaluation.flatten()
148     maxevaluelist = maxevalue.tolist()
149     # 找到前100個適應度最大的染色體的索引
150     maxIndex = map(maxevaluelist.index, heapq.nlargest(100, maxevaluelist))
151     index = list(maxIndex)
152     colume = population.shape[1]
153     # 根據索引生成新的種羣
154     maxPopulation = np.zeros((maxSize, colume))
155     i = 0
156     for ind in index:
157         maxPopulation[i] = population[ind]
158         i = i + 1
159     return maxPopulation
160 
161 # 適應度函數,使用lambda能夠不用在函數總傳遞參數
162 def fitnessFunction():
163     return lambda a, b: 21.5 + a * np.sin(4 * np.pi * a) + b * np.sin(20 * np.pi * b)
164 
165 
166 def main():
167     optimalvalue = []
168     optimalvariables = []
169 
170     # 兩個決策變量的上下界,多維數組之間必須加逗號
171     decisionVariables = [[-3.0, 12.1], [4.1, 5.8]]
172     # 精度
173     delta = 0.0001
174     # 獲取染色體長度
175     EncodeLength = getEncodeLength(decisionVariables, delta)
176     # 種羣數量
177     initialPopuSize = 100
178     # 初始生成100個種羣
179     population = getinitialPopulation(sum(EncodeLength), initialPopuSize)
180     # 最大進化代數
181     maxgeneration = 100
182     # 交叉機率
183     prob = 0.8
184     # 變異機率
185     mutationprob = 0.01
186     # 新生成的種羣數量
187     maxPopuSize = 100
188 
189     for generation in range(maxgeneration):
190         # 對種羣解碼獲得表現形
191         decode = getDecode(population, EncodeLength, decisionVariables, delta)
192         # 獲得適應度值和累計機率值
193         evaluation, cum_proba = getFitnessValue(fitnessFunction(), decode)
194         # 選擇新的種羣
195         newpopulations = selectNewPopulation(population, cum_proba)
196         # 新種羣交叉
197         crossPopulations = crossNewPopulation(newpopulations, prob)
198         # 變異操做
199         mutationpopulation = mutation(crossPopulations, mutationprob)
200         # 將父母和子女合併爲新的種羣
201         totalpopulation = np.vstack((population, mutationpopulation))
202         # 最終解碼
203         final_decode = getDecode(totalpopulation, EncodeLength, decisionVariables, delta)
204         # 適應度評估
205         final_evaluation, final_cumprob = getFitnessValue(fitnessFunction(), final_decode)
206         #選出適應度最大的100個從新生成種羣
207         population = findMaxPopulation(totalpopulation, final_evaluation, maxPopuSize)
208         # 找到本輪中適應度最大的值
209         optimalvalue.append(np.max(final_evaluation))
210         index = np.where(final_evaluation == max(final_evaluation))
211         optimalvariables.append(list(final_decode[index[0][0]]))
212 
213     x = [i for i in range(maxgeneration)]
214     y = [optimalvalue[i] for i in range(maxgeneration)]
215     plt.plot(x, y)
216     plt.show()
217 
218     optimalval = np.max(optimalvalue)
219     index = np.where(optimalvalue == max(optimalvalue))
220     optimalvar = optimalvariables[index[0][0]]
221     return optimalval, optimalvar
222 
223 
224 if __name__ == "__main__":
225     optval, optvar = main()
226 
227     print("f(x1,x2) = 21.5+x1*sin(4*pi*x1)+x2*sin(20*pi*x2)")
228     print("x1:", optvar[0])
229     print("X2:", optvar[1])
230     print("maxValue:", optval)
相關文章
相關標籤/搜索