本篇主要介紹了Python 遺傳演算法,小編覺得還挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧
寫在前面
之前的文章中已經講過了遺傳演算法的基本流程,並且用MATLAB實作過一遍了。這篇文章主要面對的人群是看過了我之前的文章,因此我就不再贅述遺傳演算法是什麼以及基本的內容了,假設大家已經知道我是怎麼寫遺傳演算法的了。
Python的遺傳演算法主函數
我的想法是,創建一個染色體的類,其中包括了兩個變數:染色體chrom與適應度fitness。因此我們就可以透過直接建立物件來作為族群中的個體。
#染色体的类 class Chrom: chrom = [] fitness = 0 def showChrom(self): print(self.chrom) def showFitness(self): print(self.fitness)
所以我們開始設定基礎參數。其中族群的表達方式我用的是字典,也就是用一個字典來保存族群內的所有個體,這個也是我想出來的創造多個物件的方法。
將字典的索引為個體的標號,如:chrom1, chrom2等。字典索引的值就是一個物件。這個物件擁有兩個屬性,就是染色體與適應度。
其實在這方便來說,我覺得在思路上是優於利用MATLAB的矩陣式程式設計的。因為這樣可以很直觀的將個體與個體的屬性這一思想給表達出來,相比一堆矩陣來說,在邏輯上比較容易接受。
#基础参数 N = 200 #种群内个体数目 mut = 0.2 #突变概率 acr = 0.2 #交叉概率 pop = {} #存储染色体的字典 for i in range(N): pop['chrom'+str(i)] = Chrom() chromNodes = 2 #染色体节点数(变量个数) iterNum = 10000 #迭代次数 chromRange = [[0, 10], [0, 10]] #染色体范围 aveFitnessList = [] #平均适应度 bestFitnessList = [] #最优适应度
之後就是初始染色體了,其中就牽扯到了各種用來初始化種群、計算適應度、找到最優等函數,我在這裡分出了兩個文件,分別為Genetic.py與Fitness.py。
Genetic.py裡面有八個函數,主要包含了作用於族群或染色體運算的函數,分別為:
findBest函數,用於尋找族群中的最優染色體;
findworse函數,用於尋找族群中的最劣染色體;
initialize函數,用於初始化族群;
calAveFitness函數,用於計算族群的平均適應度;
mutChrom函數,用於對染色體進行變異;
inRange函數,用於判斷染色體節點值是否越界;
#acrChrom函數,用於交叉染色體;
#初始染色体 pop = Genetic.initialize(pop, chromNodes, chromRange) pop = Fitness.calFitness(pop) #计算适应度 bestChrom = Genetic.findBest(pop) #寻找最优染色体 bestFitnessList.append(bestChrom[1]) #将当前最优适应度压入列表中 aveFitnessList.append(Genetic.calAveFitness(pop, N)) #计算并存储平均适应度迭代過程的想法與邏輯與MATLAB無異
#开始迭代 for t in range(iterNum): #染色体突变 pop = Genetic.mutChrom(pop, mut, chromNodes, bestChrom, chromRange) #染色体交换 pop = Genetic.acrChrom(pop, acr, chromNodes) #寻找最优 nowBestChrom = Genetic.findBest(pop) #比较前一个时间的最优和现在的最优 bestChrom = Genetic.compareChrom(nowBestChrom, bestChrom) #寻找与替换最劣 worseChrom = Genetic.findWorse(pop) pop[worseChrom[0]].chrom = pop[bestChrom[0]].chrom.copy() pop[worseChrom[0]].fitness = pop[bestChrom[0]].fitness #存储最优与平均 bestFitnessList.append(bestChrom[1]) aveFitnessList.append(Genetic.calAveFitness(pop, N))最後再做一次迭代的圖片
#
plt.figure(1) plt.plot(x, aveFitnessList) plt.plot(x, bestFitnessList) plt.show()最後再在最前面加上各種函式庫和檔案就可以執行了。
import Genetic import Fitness import matplotlib.pyplot as plt import numpy as np
感悟
#可以說最主要的感悟就是染色體這一類。其實那個Genetic.py與Fitness.py這兩個文件也可以直接包裝成類,但是這樣一來我就嫌主文件太臃腫,在其他裡面再包裝成類又多此一舉,畢竟這只是一個小程序,所以我就這樣寫了。 深刻感悟到了物件導向程式設計的優點,在程式邏輯的處理上真是一種享受,只需要思考物件的屬性即可,省去了許多複雜的思考。 另一個感想就是創建多個物件時,利用字典的方法來創建物件。當初我也是困惑怎麼建立一個類似C++中的物件數組,上網找了各種方法,結果都避而不談(當然,也可能是我搜尋能力太差沒找到),所以經過嘗試中遇到了這種方法。 等有空我再詳細說一下這個方法吧,這次就先到這裡。剩餘的函數補充##首先是Genetic.py裡面的八個函數
import random #寻找最优染色体 def findBest(pop): best = ['1', 0.0000001] for i in pop: if best[1] < pop[i].fitness: best = [i, pop[i].fitness] return best #寻找最劣染色体 def findWorse(pop): worse = ['1', 999999] for i in pop: if worse[1] > pop[i].fitness: worse = [i, pop[i].fitness] return worse #赋初始值 def initialize(pop, chromNodes, chromRange): for i in pop: chromList = [] for j in range(chromNodes): chromList.append(random.uniform(chromRange[j][0], chromRange[j][1]+1)) pop[i].chrom = chromList.copy() return pop #计算平均适应度 def calAveFitness(pop, N): sumFitness = 0 for i in pop: sumFitness = sumFitness + pop[i].fitness aveFitness = sumFitness / N return aveFitness #进行突变 def mutChrom(pop, mut, chromNodes, bestChrom, chromRange): for i in pop: #如果随机数小于变异概率(即可以变异) if mut > random.random(): mutNode = random.randrange(0,chromNodes) mutRange = random.random() * (1-pop[i].fitness/bestChrom[1])**2 pop[i].chrom[mutNode] = pop[i].chrom[mutNode] * (1+mutRange) #判断变异后的范围是否在要求范围内 pop[i].chrom[mutNode] = inRange(pop[i].chrom[mutNode], chromRange[mutNode]) return pop #检验便宜范围是否在要求范围内 def inRange(mutNode, chromRange): if chromRange[0] < mutNode < chromRange[1]: return mutNode elif mutNode-chromRange[0] > mutNode-chromRange[1]: return chromRange[1] else: return chromRange[0] #进行交叉 def acrChrom(pop, acr, chromNodes): for i in pop: for j in pop: if acr > random.random(): acrNode = random.randrange(0, chromNodes) #两个染色体节点进行交换 pop[i].chrom[acrNode], pop[j].chrom[acrNode] = pop[j].chrom[acrNode], pop[i].chrom[acrNode] return pop #进行比较 def compareChrom(nowbestChrom, bestChrom): if bestChrom[1] > nowbestChrom[1]: return bestChrom else: return nowbestChrom
import math def calFitness(pop): for i in pop: #计算每个染色体的适应度 pop[i].fitness = funcFitness(pop[i].chrom) return pop def funcFitness(chrom): #适应度函数 fitness = math.sin(chrom[0])+math.cos(chrom[1])+0.1*(chrom[0]+chrom[1])
以上是Python實作遺傳演算法的程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!