zoukankan      html  css  js  c++  java
  • 遗传算法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)
  • 相关阅读:
    HTML转码码表
    【转】javascript 小技巧 JavaScript[对象.属性]集锦
    枯燥的数据库插入修改,投机取巧的方法
    asp.net jquery ajax处理json数据
    .net生成zTree标准形式的json数据源
    SqlDateTime 溢出
    limit 与 offset
    祖国六十大寿阅兵
    Esri for Window Phone 7(一) 加载BingMap
    Create a Settings Page for Windows phone
  • 原文地址:https://www.cnblogs.com/aabbcc/p/10821435.html
Copyright © 2011-2022 走看看