遺傳算法簡介:
模擬生物學中的基因遺傳變異來達到緩慢迭代至最優解的方法
遺傳算法流程圖:
步驟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,博客園-克萊比