遗传算法之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])

    return fitness

以上。

喜欢的话麻烦点个喜欢哦~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,976评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,249评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,449评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,433评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,460评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,132评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,721评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,641评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,180评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,267评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,408评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,076评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,767评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,255评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,386评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,764评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,413评论 2 358

推荐阅读更多精彩内容