遗传算法混合编码
对于大多数复杂的实际问题单靠一种编码是很难甚至是完全无法进行求解的。例如变量中既有连续的实数又有整数某些变量还满足排列编码即多个变量之间互不相等的特征这个时候需要混合编码才能很好地对问题进行求解。本文采用Python高性能实用型进化算法工具箱Geatpy来进行相关的实验探究Geatpy工具箱内置支持复杂混合编码的进化优化并且只需把待求解的问题编写在”问题类“中然后调用内置的进化算法模板便能求解问题通用性很强。Geatpy的官方教程如下http://geatpy.com/index.php/geatpy%E6%95%99%E7%A8%8B/Geatpy的染色体本身有三种最基础的编码方式BG(二进制/格雷编码)、RI(实数整数混合编码)以及P(排列编码)这意味着一条染色体只能是这三种编码方式的其中一种。因此当需要更加复杂的编码时需要用多条染色体来进行协同表达。Geatpy的四个大类中的Population种群类只支持单染色体其Chrom属性(种群染色体矩阵)中每一行对应的是种群的一条染色体因此只支持BG、RI或P中的一种编码方式。这里引入PsyPopulation种群类它是继承了Population类的一个新的类它用Linds列表代替Population中的Lind来存储各染色体的长度用Encodings代替Population中的Encoding来存储各染色体的编码方式用Fields代替Population中的Field来存储各染色体的译码矩阵用Chroms代替Population中的Chrom来存储各个染色体矩阵。PsyPopulation和Population的UML类图对比如下所示上图中的Field, Chrom, ObjV, FitnV, CV, Phen等均满足Geatpy的数据结构详见“Geatpy数据结构”章节。如果在进化过程中采用的是PsyPopulation类的种群而不采用Population那么原有的算法模板都要作出一定的修改。首先是染色体的初始化需要遍历各种编码的染色体进行初始化操作。然后对于重组和变异也是需要遍历各种编码的染色体分别进行重组和变异因此Geatpy为各个算法模板提供其对应的多染色体版本并且用“psy”字符串加以标识。比如多目标优化NSGA2的算法模板“moea_NSGA2_templet”其对应的多染色体版本为“moea_psy_NSGA2_templet”算法的源码可点开超链接进行查看。下面以一个单目标带约束问题为例阐述如何使用多染色体混合编码求解问题该问题本来可以像以往那样直接使用实整数编码RI的染色体来表达所有的变量然后加一个不等式约束使得x3 ≠ x4 ≠ x5 ≠ x6 。但这里我们采用另一种编码方法不难发现x3, x4, x5, x6 ∈ {1, 2, 3, 4, 5, 6, 7}和x3 ≠ x4 ≠ x5 ≠ x6 正好符合排列编码的特征即x3, x4, x5, x6 是从{1,2,3,4,5,6,7}中任意挑选出4个数字的排列。因此前两个变量用RI编码(实整数编码)的染色体把对应的varTypes设为0标记这2个变量为连续型变量后4个变量用P编码(排列编码)的染色体。实验代码如下第一步编写问题类MyProblem写在MyProblem.py文件中。# -*- coding: utf-8 -*- MyProblem.py import numpy as np import geatpy as ea class MyProblem(ea.Problem): # 继承Problem父类 def __init__(self): name MyProblem # 初始化name函数名称可以随意设置 M 1 # 初始化M目标维数 # 初始化maxormins目标最小最大化标记列表1最小化-1最大化 maxormins [-1] Dim 6 # 初始化Dim决策变量维数 # 初始化决策变量的类型元素为0表示变量是连续的1为离散的 varTypes [0,0,1,1,1,1] lb [-1.5,-1.5,1,1,1,1] # 决策变量下界 ub [2.5,2.5,7,7,7,7] # 决策变量上界 lbin [1] * Dim # 决策变量下边界 ubin [1] * Dim # 决策变量上边界 # 调用父类构造方法完成实例化 ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin) def aimFunc(self, pop): # 目标函数 X pop.Phen # 得到决策变量矩阵 x1 X[:, [0]] x2 X[:, [1]] x3 X[:, [2]] x4 X[:, [3]] x5 X[:, [4]] x6 X[:, [5]] pop.ObjV np.sin(2*x1) - np.cos(x2) 2*x3**2 -3*x4 (x5-3)**2 7*x6 # 计算目标函数值赋值给pop种群对象的ObjV属性第二步编写执行脚本写在main.py文件中。# -*- coding: utf-8 -*- main.py import geatpy as ea # import geatpy from MyProblem import MyProblem # 导入自定义问题接口 if __name__ __main__: 实例化问题对象 problem MyProblem() # 生成问题对象 种群设置 NIND 40 # 种群规模 # 创建区域描述器这里需要创建两个前2个变量用RI编码剩余变量用排列编码 Encodings [RI, P] Field1 ea.crtfld(Encodings[0], problem.varTypes[:2], problem.ranges[:, :2], problem.borders[:, :2]) Field2 ea.crtfld(Encodings[1], problem.varTypes[2:], problem.ranges[:, 2:], problem.borders[:, 2:]) Fields [Field1, Field2] population ea.PsyPopulation(Encodings, Fields, NIND) # 实例化种群对象此时种群还没被初始化仅仅是完成种群对象的实例化 算法参数设置 myAlgorithm ea.soea_psy_EGA_templet(problem, population) # 实例化一个算法模板对象 myAlgorithm.MAXGEN 25 # 最大进化代数 myAlgorithm.logTras 1 # 设置每隔多少代记录日志若设置成0则表示不记录日志 myAlgorithm.verbose True # 设置是否打印输出日志信息 myAlgorithm.drawing 1 # 设置绘图方式0不绘图1绘制结果图2绘制目标空间过程动画3绘制决策空间过程动画 调用算法模板进行种群进化 [BestIndi, population] myAlgorithm.run() # 执行算法模板得到最优个体以及最后一代种群 BestIndi.save() # 把最优个体的信息保存到文件中 输出结果 print(评价次数%s % myAlgorithm.evalsNum) print(时间已过 %s 秒 % myAlgorithm.passTime) if BestIndi.sizes ! 0: print(最优的目标函数值为%s % (BestIndi.ObjV[0][0])) print(最优的控制变量值为) for i in range(BestIndi.Phen.shape[1]): print(BestIndi.Phen[0, i]) else: print(没找到可行解。)代码解析Geatpy的问题类是不用管种群用何种编码方式的只需把问题描述清楚。上面的代码中种群染色体采用何种编码方式是在执行脚本main.py中进行设置的由于上述问题中前两个变量是实数后四个变量是互不相等的整数于是设置两个Encoding把它存储在Encodings列表中因此有“Encodings [RI, P]”由于有两种编码因此需要创建两个译码矩阵Field1和Field2最后把它们存储到Fields列表中。在随后的实例化种群对象时要注意用的种群类是PsyPopulation而不是Population。因为PsyPopulation是Population衍生出来的支持多染色体混合编码的种群类。最后在实例化算法模板对象时要注意挑选的算法模板的名称要带有“psy”字符串表示这是一个支持多染色体混合编码的算法模板。由于本例是一个单目标优化问题因此可以采用“soea_SEGA_templet”的多染色体版本“soea_psy_SEGA_templet”算法模板进行求解算法的源码可点开超链接进行查看。运行main.py得到如下结果以下是Geatpy目前内置的多染色体版本的进化算法模板其具体代码均可在源码中查看到• soea_psy_EGA_templet (精英保留的多染色体遗传算法模板)• soea_psy_SEGA_templet (增强精英保留的多染色体遗传算法模板)• soea_psy_SGA_templet (最简单、最经典的多染色体遗传算法模板)• soea_psy_GGAP_SGA_templet (带代沟的多染色体简单遗传算法模板)• soea_psy_studGA_templet (多染色体种马遗传算法模板)• soea_psy_steady_GA_templet (多染色体稳态遗传算法模板)• moea_psy_awGA_templet (基于awGA 算法的多染色体多目标进化算法模板)• moea_psy_NSGA2_archive_templet (带全局存档的多染色体多目标进化NSGA-II 算法模板)• moea_psy_NSGA2_templet (基于NSGA-II 算法的多染色体多目标进化算法模板)• moea_psy_NSGA3_templet (基于NSGA-III 算法的多染色体多目标进化算法模板)• moea_psy_RVEA_templet (基于RVEA 算法的多染色体多目标进化算法模板)• moea_psy_RVEA_RES_templet (基于带参考点再生策略的多染色体RVEA 算法的多目标进化算法模板)更多相关介绍可以详见博客https://blog.csdn.net/qq_33353186/article/details/82014986https://blog.csdn.net/qq_33353186/article/details/82020507https://blog.csdn.net/qq_33353186/article/details/82047692https://blog.csdn.net/qq_33353186/article/details/82082053欢迎继续跟进感谢