遗传算法简介:
模拟生物学中的基因遗传变异来达到缓慢迭代至最优解的方法
遗传算法流程图:
步骤1:确定函数的自变量区间。
确定可行解范围,如果在遗传算法的过程中出现了数据跳出可行域的情况下需要通过映射来将其拉回可行域内。
步骤2:产生初代种群。
需要在区间内随机出一个初代种群来进行下面的操作。
如果使用染色体交叉以及染色体单点变异的话就需要对种群进行编码,将十进制的数转化成编码后的染色体式,同时也要准备好染色体解码回十进制数的相关程序。
!!!本程序使用的区间为-100到100之间的浮点数
步骤3:遗传算子:交叉。
交叉的方式有很多,常见的有染色体交叉,通过切点随机在两个不同的单体的染色体上分割出同一位置的染色体块,然后机交换两个单体上的某一部分染色体片段。
还有通过凸组合交叉的方式,在种群中随机抽出两个个体x1和x2,接着通过以下公式来得出交叉后的新个体(当miu取不同的值的时候交叉效果自然也就不一样,1>miu>0时新个体将在x1至x2的连线上。
步骤4:遗传算子:变异。
当使用染色体单点变异时,需要将个体编码成染色体的形式,然后随机将染色体上的某一位进行变异取反操作
除了染色体变异之外还可以采用高斯扰动的方法来进行小范围的变异。假设交叉后的新种群里面有i个个体,就将这i个个体求出期望,接着给每一个个体加上随机的小范围高斯扰动值来生成新的变异个体。
!!!!!!本程序的变异采用的是给个体加上高斯扰动
步骤5:遗传算子:选择。
在进行选择操作时,首先要把变异的种群和原来的种群形成一个并集,接着在这个并集的基础上来进行选择的操作。第一种方法是精英保留法,将并集内的单体带入函数式中得出适应度函数值,然后将适应度函数值来进行排序操作,只选择前面固定个数的精英单体进行保留到下一代。自然这个精英选择的过程也是能概率化的,比如百分之八十的概率来抽取前百分之多少的适应度函数值优秀的单体,,百分之二十的概率来抽取适应度函数不优秀的单体。
程序》》》》》》》
如需理解时,将程序内的所有注释掉的print重新激活便可以看见完整的逻辑过程。
import random import math import numpy import matplotlib.pyplot as plt#于2020.10.16日写,本程序为老师布置的遗传算法的练习#design by zqh#联系方式QQ962903415,博客园-克莱比 #——————————————参数部分————————————————# populationsize=10 #种群尺寸 popgeneration=20 #程序执行的世代数 basedig=[] #存放每代的最优良的那一个单体,用于制图 fitvalue=[] #存放每代的最优良的单体的适应度值,用于制图 #——————————————(产生种群,交叉变异)的模块————————————————# def createPop(popsize): ret=[] for i in range(0,popsize): num=round(random.uniform(-100, 100),3) ret.append(num) return ret def crossOver(population): ret=[] for i in range(0,len(population)): target=0 x1=round(random.choice(population),3) while target!=1: x2=round(random.choice(population),3) if x2!=x1: target=1 if x2==x1: continue lenda=random.uniform(-2,3) ret.append(round((lenda*x1+(1-lenda)*x2)/2,3)) # print('随机选两个%s和%s,求和除以2后%s' %(x1,x2,round((x1+x2)/2,3))) return ret def mutation(population): newpop=[] expect=0 for i in population: expect=expect+i expect=round(expect/len(population),3) # print('求得数学期望',expect) for i1 in population: vari=random.uniform(expect-3,expect+3) # print('从(miu-3sigma),(miu+3sigma)取任意自变量',vari) nor_distru = (1 / pow(2 * math.pi, 1 / 2)) * math.exp(-1*pow((vari-expect),2)/2) # print('自变量带入高斯分布函数得到扰动',nor_distru) count=i1+nor_distru newpop.append(round(count,3)) # print('高斯扰动后的(变异)新种群',newpop) return newpop #——————————————自写的排序公式————————————————# # def paixu(poplist): # ret=[] # while(poplist !=[]): # minkey=poplist[0] # for i in poplist: # if minkey>i: # minkey=i # if minkey<i: # minkey=minkey # ret.append(minkey) # position=poplist.index(minkey) # del poplist[position] # return ret #——————————————选择函数的公式————————————————# def fx(poplist): ret = [] for i in poplist: res = eval(gongshi) ret.append(round(res,5)) return ret #——————————————适应度选择函数————————————————# def popChoice(population): dict1={} ret1=[] ret=[] popfit=[] unionpop=list(set(a).union(set(population))) print('新老种群并集',unionpop) popfit=fx(unionpop) print('将并集求适应度函数值',popfit) for xp in range(0,len(unionpop)): dict1.update({popfit[xp]:unionpop[xp]}) print(dict1) unionpop=numpy.sort(popfit) #使用numpy包里面的浮点数排序方法 print('将其从小到大排列',unionpop) for i1 in range(len(population)): ret1.append(unionpop[i1]) print('只取前面popsize个',ret1) for xp1 in ret1: ret.append(dict1[xp1]) print('新种群',ret) print('本代最优单体为%s,它的适应度为%s' %(ret[0],ret1[0])) fitvalue.append(ret1[0]) basedig.append(ret[0]) return ret #——————————————函数主体————————————————# gongshi=input('请输入公式>>') popgeneration=int(input('请输入迭代次数>>')) start=createPop(populationsize) print('初始种群', start) a = start for i in range(0,popgeneration): b=crossOver(a) print('交叉后的新种群',b) c=mutation(b) print('变异后的新种群',c) d=popChoice(c) a=d print('\n') plt.plot(basedig,fitvalue) plt.ylabel('fitness value') #为y轴加注释 plt.xlabel('best one') #为x轴加注释 plt.show()#于2020.10.16日写,本程序为老师布置的遗传算法的练习#design by zqh#联系方式QQ962903415,博客园-克莱比