遗传算法之Python实现代码

作者:老梁家的风子 时间:2021-06-14 15:15:07 

写在前面

之前的文章中已经讲过了遗传算法的基本流程,并且用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里面有八个函数,主要包含了作用于种群或者染色体操作的函数,分别为:

  1. findBest函数,用于寻找种群中的最优染色体;

  2. findworse函数,用于寻找种群中的最劣染色体;

  3. initialize函数,用于初始化种群;

  4. calAveFitness函数,用于计算种群的平均适应度;

  5. mutChrom函数,用于对染色体进行变异;

  6. inRange函数,用于判断染色体节点值是否越界;

  7. acrChrom函数,用于对染色体进行交叉;

  8. compareChrom函数,用于比较两个染色体孰优孰劣。

Fitness.py里面有两个函数,主要包含了对适应度操作的函数,分别为:

  1. calFitness函数,用来迭代每一个个体,并计算适应度(利用funcFitness函数计算);

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

来源:http://www.jianshu.com/p/b049c68ef3c3?utm_source=tuicool&utm_medium=referral

标签:Python,遗传算法
0
投稿

猜你喜欢

  • Python中的defaultdict模块和namedtuple模块的简单入门指南

    2022-01-21 07:10:20
  • GDAL 矢量属性数据修改方式(python)

    2021-01-30 20:53:28
  • link 和 style 元素在 HTML 文档中的位置

    2008-06-02 13:56:00
  • php关于array_multisort多维数组排序的使用说明

    2023-09-07 08:13:27
  • 用python编写第一个IDA插件的实例

    2022-01-09 13:05:14
  • Python中Jieba进行词频统计与关键词提取

    2022-02-03 23:08:50
  • 使用 Angular 服务器端渲染 Transfer State Service

    2024-04-22 22:39:50
  • python基础入门之列表(一)

    2023-11-23 19:33:42
  • XMLHTTP错误The server name or address could not be resolved 的解决过程

    2009-12-26 18:33:00
  • Python实现提取音乐频谱的方法详解

    2022-01-27 07:03:08
  • python密码学库pynacl功能介绍

    2021-03-07 01:29:44
  • mysql第一次安装成功后初始化密码操作步骤

    2024-01-19 22:20:45
  • 深入SQL截取字符串(substring与patindex)的详解

    2024-01-27 16:16:24
  • ASP程序中调用函数Now()显示上午下午的问题

    2009-08-27 13:09:00
  • 怎样用cmd命令行运行Python文件

    2023-07-15 00:25:11
  • Python3结合Dlib实现人脸识别和剪切

    2023-01-10 01:28:48
  • 如何基于Python实现数字类型转换

    2023-10-08 00:57:13
  • python使用梯度下降和牛顿法寻找Rosenbrock函数最小值实例

    2022-09-10 20:01:20
  • sqlserver 巧妙的自关联运用

    2012-07-21 14:55:12
  • [翻译]标记语言和样式手册 Chapter 2 标题

    2008-01-16 11:56:00
  • asp之家 网络编程 m.aspxhome.com