遗传算法之Python实现代码
写在前面
之前的文章中已经讲过了遗传算法的基本流程,并且用MATLAB实现过一遍了。这一篇文章主要面对的人群是看过了我之前的文章,因此我就不再赘述遗传算法是什么以及基本的内容了,假设大家已经知道我是怎么写遗传算法的了。
Python的遗传算法主函数
我的思想是,创建一个染色体的类,其中包括了两个变量:染色体chrom与适应度fitness。因此我们就可以通过直接建立对象来作为种群中的个体。
#染色体的类 classChrom: chrom=[] fitness=0 defshowChrom(self): print(self.chrom) defshowFitness(self): print(self.fitness)
所以我们开始设置基础参数。其中种群的表达方式我用的是字典,也就是用一个字典来保存种群内的所有个体,这个也是我想出来的创建多个对象的方法。
将字典的索引为个体的标号,如:chrom1,chrom2等。字典索引的值就是一个对象。这个对象拥有两个属性,就是染色体与适应度。
其实在这一方便来说,我觉得在思路上是优于利用MATLAB的矩阵式编程的。因为这样可以很直观的将个体与个体的属性这一种思想给表达出来,相比一堆矩阵来说,在逻辑上比较容易接受。
#基础参数 N=200#种群内个体数目 mut=0.2#突变概率 acr=0.2#交叉概率 pop={}#存储染色体的字典 foriinrange(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无异
#开始迭代 fortinrange(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()
最后再在最前面加上各种库和文件就可以运行了。
importGenetic importFitness importmatplotlib.pyplotasplt importnumpyasnp
感悟
可以说最主要的感悟就是染色体这一个类。其实那个Genetic.py与Fitness.py这两个文件也可以直接包装成类,但是这样一来我就嫌主文件太臃肿,在其他里面再包装成类又多此一举,毕竟这只是一个小程序,所以我就这样写了。
深刻感悟到了面向对象编程的优点,在编程逻辑的处理上真是一种享受,只需要思考对象的属性即可,省去了许多复杂的思考。
另一个感悟就是创建多个对象时,利用字典的方法来创建对象。当初我也是困惑怎么建立一个类似于C++中的对象数组,上网查找了各种方法,结果都避而不谈(当然,也可能是我搜索能力太差没找到),所以经过尝试中遇到到了这种方法。
等有空我再详细说一下这个方法吧,这一次就先到这里。
剩余的函数补充
首先是Genetic.py里面的八个函数
importrandom #寻找最优染色体 deffindBest(pop): best=['1',0.0000001] foriinpop: ifbest[1]pop[i].fitness: worse=[i,pop[i].fitness] returnworse #赋初始值 definitialize(pop,chromNodes,chromRange): foriinpop: chromList=[] forjinrange(chromNodes): chromList.append(random.uniform(chromRange[j][0],chromRange[j][1]+1)) pop[i].chrom=chromList.copy() returnpop #计算平均适应度 defcalAveFitness(pop,N): sumFitness=0 foriinpop: sumFitness=sumFitness+pop[i].fitness aveFitness=sumFitness/N returnaveFitness #进行突变 defmutChrom(pop,mut,chromNodes,bestChrom,chromRange): foriinpop: #如果随机数小于变异概率(即可以变异) ifmut>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]) returnpop #检验便宜范围是否在要求范围内 definRange(mutNode,chromRange): ifchromRange[0] mutNode-chromRange[1]: returnchromRange[1] else: returnchromRange[0] #进行交叉 defacrChrom(pop,acr,chromNodes): foriinpop: forjinpop: ifacr>random.random(): acrNode=random.randrange(0,chromNodes) #两个染色体节点进行交换 pop[i].chrom[acrNode],pop[j].chrom[acrNode]=pop[j].chrom[acrNode],pop[i].chrom[acrNode] returnpop #进行比较 defcompareChrom(nowbestChrom,bestChrom): ifbestChrom[1]>nowbestChrom[1]: returnbestChrom else: returnnowbestChrom
然后是Fitness.py的两个函数
importmath defcalFitness(pop): foriinpop: #计算每个染色体的适应度 pop[i].fitness=funcFitness(pop[i].chrom) returnpop deffuncFitness(chrom): #适应度函数 fitness=math.sin(chrom[0])+math.cos(chrom[1])+0.1*(chrom[0]+chrom[1])
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。