天天看點

python 遺傳算法_Python實作遺傳算法的代碼

本篇文章主要介紹了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函數,用于對染色體進行交叉;

compareChrom函數,用于比較兩個染色體孰優孰劣。

Fitness.py裡面有兩個函數,主要包含了對适應度操作的函數,分别為:calFitness函數,用來疊代每一個個體,并計算适應度(利用funcFitness函數計算);

funcFitness函數,計算單個個體的适應度。

是以可以列出初始化代碼為

#初始染色體

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

然後是Fitness.py的兩個函數

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])