=====快速解读官方一个遗传算法程序=====
读懂每行代码
关于求解 f = x*sin(10π*x) + 2 的最大值 x的范围-1<<=x<<=2
1.首先创建MyProblem.py文件,去存放导入相关的库,像numpy、Geatpy等。
/*numpy是python语言的一个扩展程序库,提供和处理N维数组对象Array*/
/*Geatpy简而言之就是包含了遗传和进化算法相关的函数的一个库*/
import numpy as np #导入numpy库
import geatpy as ea #导入geatpy库
2.创建MyProblem,调用Geatpy里面的Problem类。 Problem类是Geatpy里面专门用来存储带求解问题的相关信息的一个类,它有八个属性,
分别是:name(可以自定义问题名字), M(维度), Maxormins(是求解最大值问题还是最小值问题,1代表最小化,-1代表最大化) Dim(决策变量的维数,简单理解决策变量就是x), varTypes(决策变量是连续的还是离散的,0代表连续,1代表离散), ranges(决策变量范围矩阵,第一行代表下界,第二行代表上界), borders(决策变量范围边界矩阵,0表示不包含边界,1表示包含边界), ReferObjV(存储目标函数参考值的矩阵,每一行对应一组目标函数参考值) 除了八大属性还有三个构造函数,这个案例只用到了一个,分别是 aimFunc(self,pop) //如果执行到这里抛出了异常,说明自定义的问题类没有重写该函数 输入参数:pop是class<Population>-种群对象 calReferObjV(self) //如果待优化的模型知道理论全局最优解,则可以在自定义问题类里 重写该函数,求出理论全局最优解对应的目标函数值矩阵 getReferObjV(self,reCalulate=false) //该函数用于读取/计算问题的目标函数参考值 输入参数:reCalculate:bool-----表示是否调用calReferObjV()来重新计算目标函数参考 值,当缺省的时候默认为false 输出参数:referenceObjV:存储着目标函数参考值的矩阵,每一行对应一组目标函数参 考值,每一列对应一个目标函数
class MyProblem(ea.Problem): # 继承Problem父类
定义函数 __init__(参数:self) //上下划线表示只能在类内进行调用,self表示类中的方法可以访问自己的成员变量
def __init__(self):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
M = 1 # 初始化M(目标维数)
maxormins = [-1] # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
Dim = 1 # 初始化Dim
# (决策变量维数)
varTypes = [0] * Dim # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
lb = [-1] # 决策变量下界
ub = [2] # 决策变量上界
lbin = [1] * Dim # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
ubin = [1] * Dim # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
# 调用父类构造方法完成实例化
ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin)
重新定义目标函数 aimFunc
def aimFunc(self, pop): # 目标函数
x = pop.Phen # 得到决策变量矩阵
pop.ObjV = x * np.sin(10 * np.pi * x) + 2.0 # 计算目标函数值,赋值给pop种群对象的ObjV属性
Population类,是用来存储种群相关信息的一个类,它有十个属性和十个函数,下面介绍一下:
sizes:种群的规模,就是种群的个体数目
ChromNum:染色体的数目,就是每个个体有多少条染色体
Encoding:染色体的编码方式,'BG'代表二进制
Field:译码矩阵
Chorm:种群染色体矩阵,每一行对应一个个体的一条染色体
Lind:种群染色体的长度
ObjV:种群目标函数矩阵,每一行对应一个个体的目标函数值,每一列对应一个目标
FitnV:种群个体适应度列向量,每一个元素对应一个个体的适应度,最小的适应度为0
CV:是用来定量描述违反约束条件程度的矩阵,每行对应一个个体,每列对应一个约束
Phen:种群表现型矩阵,就是种群各染色体解码后所代表的决策变量所组成的矩阵
函数:
__add__(self, pop)//描述个体合并
__getitem__(self, index)//种群的切片,即根据index下标向量选出种群中相应的个体组成一个新的种群。
__init__(self, Encoding, Field, NIND, Chrom=None, ObjV=None, FitnV=None, CV=None, Phen=None)//种群类的构造函数,用于实例化种群对象
__len__(self)//计算种群规模
__setitem__(self, index, pop)//种群个体的赋值
copy(self)//种群的复制
decoding(self)//种群染色体解码
initChrom(self, NIND=None)//初始化染色体矩阵
save(self, dirName='Result')//该函数将在字符串dirName所指向的文件夹下保存种群的信息
shuffle(self)//打乱种群个体的个体顺序
到此为止这个类就写完了,相当于重新的在父类Problem上进行编写一个新的Problem类,这个新类更加符合这个问题的要求。具体他想做的事情个人理解:初始化name,这样在主函数里进行调用的时候就可以用MyProblem进行调用而不是ea.Problem,因为这个待求解函数只有一个y,所以维数是一维,在maxormins里设置我要求的是最大值,x也是一维的,决策变量的类型是连续的,上下界(-1,2),包含边界,然后最后调用父类的方法进行实例化。第二步定义目标函数,把种群population类传进去,得到种群表现型矩阵,把目标函数值赋给ObjV属性。