GEATPY快速入门

目录

1. 安装

2. 入门示例 

2.1 脚本编程法

2.1.1 问题

2.1.2 代码       

 2.1.3 脚本详细解析

2.2 采用面向对象的进化算法框架

2.2.1 带约束的单目标优化问题

2.2.2 带约束的多目标优化问题


1. 安装

        你可以通过联网安装或本地安装来安装 Geatpy。在安装前,你需要安装 Numpy、 Scipy 以及 matplotlib。

联网安装:

pip install geatpy

本地安装:

在 github 下载 Geatpy 安装包,在本地控制台执行以下代码安装: 

python setup.py install

查看版本号:

        在 python 中执行: 

import geatpy as ea

print(ea.__version__) 

更新方法:

在本地控制台执行: 

pip install --upgrade --user geatpy

2. 入门示例 

在 Geatpy 上有 3 种基本的方法来求解问题:

• 直接使用工具箱提供的库函数,通过编写脚本来实现进化算法并且求解问题。

• 使用 Geatpy 提供的面向对象进化算法框架,利用内置的算法模板求解问题。

• 使用 Geatpy 提供的面向对象进化算法框架,通过自定义进化算法模板实现进化算法 并且求解问题。 本章将主要介绍如何使用前两种方法:

2.1 脚本编程法

        脚本编程法是 Geatpy 最原生、最基础的使用方式。它通过直接调用工具箱的库函 数来实现进化算法,不涉及面向对象的编程方法,编程风格与 Matlab 比较相似,缺点是代码量比较大。我们将用它来快速入门。

2.1.1 问题

        以求解标准测试函数——McCormick 函数的最小化搜索问题为例,其表达式为:

         它是一个二元函数,它具有一个全局极小点:f = (−0.54719, −1.54719) = −1.9133, 函数图像如下:

2.1.2 代码       

         拟采用带精英保留的遗传算法”Elitist Reservation GA” 来求解上述问题,于是编写如下执行脚本:

# -*- coding: utf-8 -*-
"""demo.py"""
import numpy as np
import geatpy as ea # 导入geatpy库
import time
"""============================目标函数============================"""
def aim(Phen): # 传入种群染色体矩阵解码后的基因表现型矩阵
    x1 = Phen[:, [0]] # 取出第一列,得到所有个体的第一个自变量
    x2 = Phen[:, [1]] # 取出第二列,得到所有个体的第二个自变量
    return np.sin(x1 + x2) + (x1 - x2) ** 2 - 1.5 * x1 + 2.5 * x2 +1
"""============================变量设置============================"""
x1 = [-1.5, 4] # 第一个决策变量范围
x2 = [-3, 4] # 第二个决策变量范围
b1 = [1, 1] # 第一个决策变量边界,1表示包含范围的边界,0表示不包含
b2 = [1, 1] # 第二个决策变量边界,1表示包含范围的边界,0表示不包含
# 生成自变量的范围矩阵,使得第一行为所有决策变量的下界,第二行为上界
ranges=np.vstack([x1, x2]).T
# 生成自变量的边界矩阵
borders=np.vstack([b1, b2]).T
varTypes = np.array([0, 0]) # 决策变量的类型,0表示连续,1表示离散
"""==========================染色体编码设置========================="""
Encoding = 'BG' # 'BG'表示采用二进制/格雷编码
codes = [1, 1] # 决策变量的编码方式,两个1表示变量均使用格雷编码
precisions =[6, 6] 
#决策变量的编码精度,表示解码后能表示的决策变量的精度可达到小数点后6位
scales = [0, 0] # 0表示采用算术刻度,1表示采用对数刻度
# 调用函数创建译码矩阵
FieldD =ea.crtfld(Encoding,varTypes,ranges,borders,precisions,codes,scales)
"""=========================遗传算法参数设置========================"""
NIND = 20 # 种群个体数目
MAXGEN = 100 # 最大遗传代数
maxormins = np.array([1]) 
#表示目标函数是最小化,元素为-1则表示对应的目标函数是最大化
selectStyle = 'sus' # 采用随机抽样选择
recStyle = 'xovdp' # 采用两点交叉
mutStyle = 'mutbin' # 采用二进制染色体的变异算子
Lind = int(np.sum(FieldD[0, :])) # 计算染色体长度
pc = 0.9 # 交叉概率
pm = 1/Lind # 变异概率
obj_trace = np.zeros((MAXGEN, 2)) # 定义目标函数值记录器
var_trace = np.zeros((MAXGEN, Lind)) 
#染色体记录器,记录历代最优个体的染色体
"""=========================开始遗传算法进化========================"""
start_time = time.time() # 开始计时
Chrom = ea.crtpc(Encoding,NIND, FieldD) # 生成种群染色体矩阵
variable = ea.bs2real(Chrom, FieldD) # 对初始种群进行解码
ObjV = aim(variable) # 计算初始种群个体的目标函数值
best_ind = np.argmin(ObjV) # 计算当代最优个体的序号
# 开始进化
for gen in range(MAXGEN):
    FitnV = ea.ranking(maxormins * ObjV) # 根据目标函数大小分配适应度值
    SelCh = Chrom[ea.selecting(selectStyle,FitnV,NIND-1),:] # 选择
    SelCh = ea.recombin(recStyle, SelCh, pc) # 重组
    SelCh = ea.mutate(mutStyle, Encoding, SelCh, pm) # 变异
    # 把父代精英个体与子代的染色体进行合并,得到新一代种群
    Chrom = np.vstack([Chrom[best_ind, :], SelCh])
    Phen = ea.bs2real(Chrom, FieldD) # 对种群进行解码(二进制转十进制)
    ObjV = aim(Phen) # 求种群个体的目标函数值
    # 记录
    best_ind = np.argmin(ObjV) # 计算当代最优个体的序号
    obj_trace[gen,0]=np.sum(ObjV)/ObjV.shape[0]
    #记录当代种群的目标函数均值
    obj_trace[gen,1]=ObjV[best_ind] #记录当代种群最优个体目标函数值
    var_trace[gen,:]=Chrom[best_ind,:] #记录当代种群最优个体的染色体
# 进化完成
end_time = time.time() # 结束计时
ea.trcplot(obj_trace, [['种群个体平均目标函数值',
'种群最优个体目标函数值']]) # 绘制图像

运行结果:

        若要输出相关的数据结果,则可以在上面脚本最下方添加以下代码: 

"""============================输出结果============================"""
best_gen = np.argmin(obj_trace[:, [1]])
print('最优解的目标函数值:', obj_trace[best_gen, 1])
variable = ea.bs2real(var_trace[[best_gen], :], FieldD) 
#解码得到表现型(即对应的决策变量值)
print('最优解的决策变量值为:')
for i in range(variable.shape[1]):
    print('x'+str(i)+'=',variable[0, i])
print('用时:', end_time - start_time, '秒')

 2.1.3 脚本详细解析

        编写 Geatpy 脚本风格与 Matlab 非常相近,对于新的问题,你可以复制上面的脚本, 结合实际问题修改函数定义和变量设置,以及绘图和输出便可以对新问题进行求解。实 际上你会发现脚本中大部分基本上可以固定不变的,因此在后面的章节中,我们会讲解 如何用更为方便的面向对象进化算法框架来解决问题,这样会大大节省开发时间。

        下面详细讲解编写类似上述编程脚本的流程,你需要做以下步骤:

        1. 导入相关库,如 numpy、Geatpy 等。

        2. 定义了优化目标函数。(在后面的章节中,我们会详细介绍如何用问题类来取代 这种把函数定义写在脚本内部的方法)。

        3. 优化问题的变量设置。

        其中 ranges、borders 是根据实际问题而编写的,但写法格式是固定的。

        假如优化函数中包含 3 个变量,那么我们可以这么写:

        x1 = [下界, 上界]

        x2 = [下界, 上界]

        x3 = [下界, 上界]

        b1 = [0, 1] # (这里 0 表示变量 x1 不包含下界,1 表示包含上界)

        b2 = [1, 0]

        b3 = [1, 1]

        ranges = np.vstack([x1, x2, x3]).T

        # 根据 x1,x2,x3 生成一个矩阵来表示所有变量的范围

        borders = np.vstack([b1, b2, b3]).T ...

        varTypes 是一个存储决策变量类型的行向量。元素为 0 则对应的决策变量是连续型变量;为 1 则表示离散型决策变量。比如 array([0,0,1]) 表示三个决策变量中的前 2 个是连续型变量,第三个是离散型变量。

        4. 染色体编码设置:这一部分将设置进化算法采用何种编码的染色体种群进行进化。Encoding 指定了染色体的编码方式。Encoding 有三种类型:’BG’(二进制/格雷编码)、 ’RI’(实整数编码) 以及’P’(排列编码)(详见前面“Geatpy 数据结构”章节)。当 Encoding 为’BG’ 时,需要用到 codes、precisions、scales 三个参数。这三个参数是给“crtfld”函数 来自动化生成译码矩阵用的。详细用法可在 Python 控制台中输入以下代码查看 API 文 档(或查看官网的 API 文档):

        import geatpy as ea

        help(ea.crtfld)

        准备好这些参数后,就可以调用 crtfld() 函数自动化生成译码矩阵 (当然你也可以手 动创建)。crtfld 函数会根据变量的边界和精度自动地调整变量的范围,返回一个符合规 范的译码矩阵。译码矩阵有“FieldD”和“FieldDR”两种类型,详见前面“Geatpy 数据结构”章节的相关描述。 

        5. 对进化算法的运行参数进行设置,比如确定种群规模 (即种群包含多少个个体)、 最大遗传代数、重组算子、变异算子、重组概率以及变异概率等。

        6. 根据创建的译码矩阵计算染色体的长度。前面“Geatpy 数据结构”章节中讲解了译码矩阵 FieldD 的第一行是代表控制各个变量的染色体基因数目。因此对它求和便可算出染色体的长度。

        7. 创建进化记录器,它的写法也是固定的,2 表示该进化记录器有 2 列,每一列存 放不同的数据。本例中,它的第一列是存放各代种群最优个体的目标函数值;第二列是存放各代种群的平均目标函数值。

        8. 创建最优个体记录器,记录各代种群的最优个体的染色体。

        9. 做完这些基本步骤后,就开始初始化种群以及进化了,这些都是遗传算法的基本流程了,上面的注释中有详细解释,这里不再重复讲解。

        10. 绘图和输出寻优结果。Geatpy 中提供 trcplot 函数来根据进化记录器绘制进化过 程追踪图。关于其具体用法可在 Python 控制台中输入以下代码查看 API 文档(或查看 官网的 API 文档):

import geatpy as ea

help(ea.trcplot)

特别注意:

        1) Geatpy 的适应度计算均遵循” 目标函数越大,适应度越小” 的约定。因此在涉及 需要利用目标函数来求适应度,抑或是根据目标函数来进行非支配排序,或者是根据 其来进行个体保留,等等,都要对目标函数乘上一个“目标最小最大化标记列表”—— maxormins。它是一个长度等于目标函数个数的 Numpy array 类型行向量,元素为 1 表 示对应的目标是最小化目标,元素为-1 表示对应的是最大化目标。例如 maxormins = array([1,1,-1]),表示有三个目标函数,其中前两个是最小化目标,第三个是最大化目标。

        2) 使用 Geatpy 过程中最容易出错的地方在于目标函数值矩阵 ObjV 的计算。Geatpy 要求目标函数值矩阵 ObjV 的行数必须等于种群染色体矩阵 Chrom 的行数,以保持个体 属性的一一对应关系。详见上一章“Geatpy 数据结构”。 

2.2 采用面向对象的进化算法框架

        上面的脚本编程法虽然可以很深入到进化算法的每个步骤,但代码量确实是太大 了。虽然它也具备一定的通用性,比如当需要求解另一个优化问题时,可以通过修改 aim() 目标函数以及修改变量范围设置等来适应新的问题,但会比较容易出错。此外,上 述编程脚本所实现的仅仅是简单的带精英保留的遗传算法,当需要修改算法、采用新的 更好的进化算法进行问题的求解时,所需要改动的代码就非常大了。因此,更好、更简 便的方式是采用 Geatpy 提供的面向对象进化算法框架。

        在前面的“Geatpy 总览”章节中提到 Geatpy 的进化算法框架由四个大类构成:算法模板类 (Algorithm)、种群类 (Population)、多染色体混合编码种群类 (PsyPopulation) 以及问题类 (Problem)。其中 Population 类和 PsyPopulation 类是可以直接被实例化成对象去来使用的类;Algorithm 类和 Problem 类是父类,需要实例化其子类来使用。下面以两个案例(一个单目标优化、一个多目标优化)来展示如何使用 Geatpy 所提供的面向对象进化算法框架。

2.2.1 带约束的单目标优化问题

        请移步下面博客:约束的单目标优化问题遗传算法解决带约束的单目标优化问题_要努力呦的博客-CSDN博客

2.2.2 带约束的多目标优化问题

        请移步下面博客:带约束的多目标优化问题

遗传算法解决带约束的多目标优化问题_要努力呦的博客-CSDN博客

  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值