upstreamL

博客中的文章用于做笔记用,来源于网络,并非本人所写,如有侵权,请您联系我标明出处或删除,3Q~

导航

遗传算法python实现

最近看了一下遗传算法,使用轮盘赌选择染色体,使用单点交叉,下面是代码实现(python3)

 

  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)

 

posted on 2019-05-06 19:05  upstreamL  阅读(10355)  评论(4编辑  收藏  举报