一个完全面向对象的竞争性遗传算法框架
pyrimidine的Python项目详细描述
嘧啶
遗传算法的python面向对象实现。有关详细信息,请参见pyrimidine's document。在
为什么
为什么包装名为“嘧啶”?因为它以“py”开头。在
— Are you kiding?
— No, I am serious.
下载
它已经上传到pypi,所以用pip install pyrimidine
下载,也可以从github下载。在
想法
我们把人口看作个体的容器,把个体看作染色体的容器 以及作为基因容器(阵列)的染色体。在
容器可以是列表或数组。
容器类有一个属性element_class
,它告诉自己其中元素的类。在
以下是BaseIndividual
和BasePopulation
的源代码部分。在
classBaseIndividual(BaseFitnessModel,metaclass=MetaContainer):element_class=BaseChromosomedefault_size=1classBasePopulation(BaseFitnessModel,metaclass=MetaHighContainer):element_class=BaseIndividualdefault_size=20
容器主要有两种:列表和元组,如编程语言Haskell
。参见以下示例。在
使用
主要类别
- 基基因:染色体的基因
- 基本染色体:基因序列,代表解决方案的一部分
- 基本个体:染色体序列,代表一个问题的解决方案
- 一组个体,代表一组问题 也就是不稳定的过程
- 基种:更复杂优化的种群集合
导入
只需使用命令from pyrimidine import *
导入所有对象。在
子类
染色体
一般来说,它是一组基因。在
作为0-1的数组,BinaryChromosome
最常用。在
个人
在大多数情况下,只是子类MonoIndividual
。在
classMyIndividual(MonoIndividual):"""individual with only one chromosome we set the gene is 0 or 1 in the chromosome """element_class=BinaryChromosomedef_fitness(self):...
由于类MonoBinaryIndividual
被定义为这样的个体,它等价于
classMyIndividual(MonoBinaryIndividual):# only need define the fitnessdef_fitness(self):...
如果一个个体包含几个染色体,那么子类MultiIndividual
。它可以应用于多实变量优化问题。在
在大多数情况下,我们必须将染色体解码为实数。在
class_Chromosome(BinaryChromosome):defdecode(self):"""Decode a binary chromosome if the sequence of 0-1 represents a real number, then overide the method to transform it to a nubmer """classExampleIndividual(BaseIndividual):element_class=_Chromosomedef_fitness(self):# define the method to calculate the fitnessx=self.decode()# will call decode method of _Chromosomereturnevaluate(x)
如果个体中的染色体彼此不同,那么子类MixIndividual
,同时,属性{
classMyIndividual(MixIndividual):""" Inherit the fitness from ExampleIndividual directly. It has 6 chromosomes, 5 are instances of _Chromosome, 1 is instance of FloatChromosome """element_class=(_Chromosome,)*5+(FloatChromosome,)
它相当于MyIndividual=MixIndividual[(_Chromosome,)*5 + (FloatChromosome,)]
人口
classMyPopulation(SGAPopulation):element_class=MyIndividual
element_class
是类的最重要属性,它定义了群体中个体的类。它相当于MyPopulation=SGAPopulation[MyIndividual]
。在
随机初始化
初始化填充
产生一个群体,有50个个体,每个个体有100个基因
pop = MyPopulation.random(n_individuals=50, size=100)
当每个个体包含5条染色体时。在
pop = MyPopulation.random(n_individuals=10, n_chromosomes=5, size=10)
对于MixIndividual
,我们建议使用,例如
pop = MyPopulation.random(n_individuals=10, sizes=(10,8,8,3))
初始化个人
实际上,Population
的random
方法将调用Individual
的随机方法。如果您想生成一个个体,那么只需执行MyIndividual.random(n_chromosomes=5, size=10)
,对于简单的个体,只需执行SimpleIndividual.random(size=10)
,因为它的n_chromosomes
等于1。在
进化
evolve
方法
使用random
方法初始化填充,然后调用evolve
方法。在
pop=MyPopulation.random(n_individuals=50,size=100)pop.evolve()print(pop.best_individual)
设置verbose=True
以显示每一代的数据。在
历史
了解进化史。在
stat={'Fitness':'fitness','Best Fitness':lambdapop:pop.best_individual.fitness}data=pop.history(stat=stat)# use history instead of evolve
stat
是一个dict映射键到函数的dict,其中字符串'fitness'表示函数lambda pop:pop.fitness
,它获得pop的平均适应度。因为我们已经定义流行音乐最佳个人音乐.fitness作为属性,stat
可以重新定义为{'Fitness':'fitness', 'Best Fitness': 'best_fitness'}
。在
性能
使用pop.perf()
检查性能。在
示例
例1
说明
select ti, ni from t, n
sum of ni ~ 10, while ti dose not repeat
选择。问题是
min abs(sum_i{ni}-10) + maximum of frequences in {ti}
where i is selected.
t=np.random.randint(1,5,100)n=np.random.randint(1,4,100)importcollectionsdefmax_repeat(x):# maximum of numbers of repeatsc=collections.Counter(x)bm=np.argmax([bfora,binc.items()])returnlist(c.keys())[bm]classMyIndividual(BinaryIndividual):def_fitness(self):x,y=self.evaluate()return-x-ydefevaluate(self):returnabs(np.dot(n,self.chromosome)-10),max_repeat(tiforti,cinzip(t,self)ifc==1)classMyPopulation(SGAPopulation):element_class=MyIndividualpop=MyPopulation.random(n_individuals=50,size=100)pop.evolve()print(pop.best_individual)
注意到MonoIndividual
中只有一条染色体,可以通过self.chromosome
获得。在
例2:背包问题
其中一个著名的问题是背包问题。这是遗传算法的一个很好的例子
我们在evolve
方法中设置history=True
,它将记录whol的主要数据进化论。它将返回一个pandas.DataFrame
的对象。参数stat
是一个dict,它从一个key到function/str(对应于一个方法)映射一个总体到一个数字。一代中的数字将存储在数据帧的一行中。在
见# examples/example0
#!/usr/bin/env python3# -*- coding: utf-8 -*-frompyrimidineimportMonoBinaryIndividual,SGAPopulationfrompyrimidine.benchmarks.optimizationimport*# generate a knapsack problem randomlyevaluate=Knapsack.random(n=20)classMyIndividual(MonoBinaryIndividual):def_fitness(self):returnevaluate(self)classMyPopulation(SGAPopulation):element_class=MyIndividualpop=MyPopulation.random(size=20)stat={'Mean Fitness':'mean_fitness','Best Fitness':'best_fitness'}data=pop.evolve(stat=stat,history=True)# data is an instance of DataFrame of pandasimportmatplotlib.pyplotaspltfig=plt.figure()ax=fig.add_subplot(111)data[['Mean Fitness','Best Fitness']].plot(ax=ax)ax.set_xlabel('Generations')ax.set_ylabel('Fitness')plt.show()
扩展
pyrimidine
是可扩展的。它易于实现其他迭代模型,如模拟退火和粒子群优化。在
目前,建议将基于BaseIterativeModel
的子类定义为maxin。在
在粒子群优化算法中,我们把粒子看作一个个体,ParticleSwarm
作为一个总体。但是在下面,我们将它从BaseIterativeModel
子类化
# pso.pyclassParticle(PolyIndividual):"""A particle in PSO Variables: default_size {number} -- one individual represented by 2 chromosomes: position and velocity phantom {Particle} -- the current state of the particle moving in the solution space. """element_class=FloatChromosomedefault_size=2phantom=Nonedefbackup(self):self.chromosomes[0]=self.positionself.fitness=self.phantom.fitnessdefinit(self):self.phantom=self.clone(fitness=self.fitness)# other methodsclassParticleSwarm(BaseIterativeModel):element_class=Particledefault_size=20params={'learning_factor':2,'acceleration_coefficient':3,'inertia':0.5,'n_best_particles':0.1,'max_velocity':None}definit(self):self.best_particles=self.get_best_individuals(self.n_best_particles)forparticleinself.particles:particle.init()deftransit(self,*args,**kwargs):""" Transitation of the states of particles """forparticleinself:ifparticle.phantom.fitness>particle.fitness:particle.backup()forparticleinself:ifparticlenotinself.best_particles:fork,binenumerate(self.best_particles):ifparticle.fitness<=b.fitness:breakifk>0:self.best_particles.pop(k)self.best_particles.insert(k,particle)self.move()defmove(self):# moving rule of particlesxi=random()eta=random()forparticleinself:ifparticleinself.best_particles:particle.velocity=(self.inertia*particle.velocity+self.learning_factor*xi*(particle.best_position-particle.position))else:forbinself.best_particles:ifparticle.fitness<b.fitness:breakparticle.velocity=(self.inertia*particle.velocity+self.learning_factor*xi*(particle.best_position-particle.position)+self.acceleration_coefficient*eta*(b.best_position-particle.position))particle.position+=particle.velocityparticle.phantom.fitness=None
如果您想应用PSO,那么您可以定义
classMyParticleSwarm(ParticleSwarm,BasePopulation):element_class=_Particledefault_size=20pop=MyParticleSwarm.random()
这不是强迫性的。可以直接从BasePopulation
继承{
- 项目
标签: