最近看了一下遗传算法,使用轮盘赌选择染色体,使用单点交叉,下面是代码实现(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)