进化算法——遗传算法 使用Geatpy库实现
Geatpy
import geatpy as ea
import numpy as np
种群初始化
- crtfld (生成译码矩阵,俗称“区域描述器”)
- crtbp (创建二进制种群染色体矩阵)
- crtip (创建元素是整数的种群染色体矩阵)
- crtpp (创建排列编码种群染色体矩阵)
- crtrp (创建元素是实数的种群染色体矩阵)
- meshrng (网格化决策变量范围)
help(ea.crtfld)
Help on cython_function_or_method in module crtfld:
crtfld(Encoding, varTypes, ranges, borders=None, precisions=None, codes=None, scales=None)
crtfld : function - 译码矩阵生成函数
描述:该函数根据输入的参数生成译码矩阵FieldD或FieldDR。
语法:
当Encoding为'RI'或'P'时:
FieldDR = crtfld(Encoding, varTypes, ranges, borders)
FieldDR = crtfld(Encoding, varTypes, ranges, borders, contraction)
当Encoding为'BG'时:
FieldD = crtfld(Encoding, varTypes, ranges, borders, precisions)
FieldD = crtfld(Encoding, varTypes, ranges, borders, precisions, codes)
FieldD = crtfld(Encoding, varTypes, ranges, borders, precisions, codes, scales)
输入参数:
Encoding : str - 染色体编码方式,
'BG':二进制/格雷编码;
'RI':实整数编码,即实数和整数的混合编码;
'P':排列编码。
相关概念:“实值编码”包含实整数编码和排列编码,
它们共同的特点是染色体不需要解码即可直接表示对应的决策变量。
"实整数"指的是种群染色体既包含实数的小数,也包含实数的整数。
varTypes : array - 连续或离散标记,0表示该种群染色体解码后的对应的决策变量是连续的;
1表示该种群染色体解码后的变量是离散的。
当变量是离散时,该函数会对borders标记为0的变量的范围往里收缩并取整,
同时对其他非整数范围进行向里取整,最后把borders元素全设为1。例如:
若varTypes=[0, 1, 1],表示有3个变量,第1个变量是实数,第2、3个变量是整数。
此时若有:
ranges=[[1.1, 2, 3.1],
[3, 4, 5]]
borders = [[1, 0, 1],
[1, 1, 1]]
则ranges会被修正为[[1.1, 3, 4],
[3, 4, 5]]
borders会被修正为:[[1, 1, 1],
[1, 1, 1]]
注意:'P'(排列编码)时,会无条件地会把varTypes的元素设置成全为1。
ranges : array - 代表自变量的范围矩阵,要求上界必须大于下界。
例如:[[1, 2, 3],
[3, 4, 5]]
表示有3个决策变量,其范围分别是1-3, 2-4, 3-5。
borders : list - (可选参数)代表是否包含变量范围的边界,为1代表决策变量的范围包含该边界,
当为None时,默认设置为全是1的矩阵。
例如:[[1, 0, 1],
[0, 1, 1]]
表示上面的三个决策变量的范围分别是:[1, 3)、(2, 4]、[3, 5]。
contraction : list - (可选参数)代表决策变量的“边界收缩率”,其元素必须不小于1。当不含边界时,
变量范围会往里收缩0.1^contraction,最后把borders元素全设为1,
例如:ranges=[[1, 2, 3],
[3, 4, 5]]
borders = [[1, 0, 1],
[0, 1, 1]]
此时若contraction为[1, 1, 1],
则ranges会被修正为[[1, 2.1, 3],
[2.9, 4, 5]]
borders会被修正为:[[1, 1, 1],
[1, 1, 1]]
注:contraction仅在Encoding为'RI'时有效,
当contraction缺省或为None时,默认它为元素全为4的列表。
当Encoding为'BG'时,
本函数的第四个参数的含义将不再是contraction而是precisions。
precisions : list - (可选参数)代表决策变量的二进制/格雷编码精度(仅在Encoding为'BG'时有效),
precision的元素必须不小于0。
如等于4,表示对应的决策变量的编码可以精确到小数点后4位。
当precisions参数缺省或为None时,默认precision为元素全为4的列表。
但当对应的决策变量为整数时,即便传入precisions,但不会产生作用,
这是因为整数的二进制/格雷码编码不需要用到精度。
例如varTypes=[0, 1, 1],表示有3个变量,第1个变量是实数,第2、3个变量是整数,
此时若precisions=[4,5,5],则只有第1位是起作用的。
codes : list -(可选参数)代表变量的编码方式,(0:binary | 1:gray),默认采用二进制编码。
该参数在Encoding为'BG'时使用。
scales : list - (可选参数)指明每个变量在解码时使用对数还是算术刻度(仅在Encoding为'BG'时有效),
0为使用算术刻度,1为使用对数刻度,默认采用算术刻度,
当采用对数刻度时,决策变量的范围不能包含0。
类似于precisions,scales仅对于varTypes中元素为0对应的变量起作用,
这同样是因为整数的二进制/格雷码编码不需要采用对数刻度进行变换。
输出参数:
FieldD : array - 二进制/格雷码种群译码矩阵,Encoding为'BG'时返回的是这种结构的译码矩阵。
它是描述种群每个个体的染色体长度和如何解码的矩阵,它有以下结构:
[lens; 每个决策变量编码后在染色体中所占的长度。
lb; 指明每个变量使用的下界。
ub; 指明每个变量使用的上界。
codes; (0:binary | 1:gray) 指明子串是怎么编码的,
0为标准二进制编码,1为格雷编码。
scales; (0: rithmetic | 1:logarithmic) 指明每个子串是否使用对数或算术刻度,
1为使用对数刻度,0为使用算术刻度。
lbin; (0:excluded | 1:included)。
ubin; (0:excluded | 1:included)。
varTypes] (0:continued | 1:discrete)。
lbin和ubin指明范围中是否包含每个边界。
lbin=0或ubin=0,表示范围中不包含相应边界。
lbin=1或ubin=1,表示范围中包含相应边界。
或FieldDR : array - 实值编码种群的译码矩阵,Encoding为'RI'或'P'时返回的是这种结构的译码矩阵。
[lb; 指明每个变量使用的下界。
ub; 指明每个变量使用的上界。
varTypes] (0:continued | 1:discrete)。
注意:
1.参数codes和scales是在当Encoding为'BG'时才起作用的,因此当Encoding为'RI'或'P'时,
codes和scales就算赋值也不会起作用。
2.本函数会根据borders及边界收缩率对范围进行相应的调整,因此得到的范围可能会跟原来的ranges不一致,
可使用print函数输出译码矩阵查看。
Created on Sat Jun 30 10:18:01 2018
@author: jazzbin
Changed on Sat Jul 13 20:15:01 2019
@author: jazzbin
help(ea.crtip)
Help on built-in function crtip in module crtip:
crtip(...)
crtip : function - (Create Integer Points)创建一个整数值种群染色体矩阵
描述:
该函数随机生成一个给定了大小和结构的整数型种群染色体矩阵。
语法:
Chrom = crtip(Nind, FieldDR)
Chrom = crtip(Nind, FieldDR, Parallel)
输入参数:
Nind : int - 表示种群的个体数
FieldDR : array - 实值种群译码矩阵,Encoding为'RI'或'P'时使用的是这种结构的译码矩阵。
[lb; 指明每个变量使用的下界。
ub; 指明每个变量使用的上界。
varTypes] (0:continued | 1:discrete)。
注意:传入该函数的FieldDR中的varTypes是无用参数,因为该函数只生成元素是整数的染色体矩阵。
Parallel : bool - (可选参数)表示是否采用并行计算,缺省或为None时默认为False。
输出参数:
Chrom : array - 一个以种群个体数为行数、以染色体长度为列数的元素为随机整数值的矩阵。
Created on Sun July 1 13:01:23 2018
@author: jazzbin
Example
'''定义参数'''
MAXGEN = 50
maxormins = -1 #表示目标函数最小最大化标记,1表示最小化,-1表示最大化
recombine_rate = 0.7
mut_rate = 0.05
Nind = 10
num_hidden_neurons = 6
Encoding = "RI"
'''边界定义'''
ub_hidden_n = [1024] * num_hidden_neurons
lb_hidden_n = [32] * num_hidden_neurons
ub_lr = [1000]
lb_lr = [1]
ub_batch_size = [2]
lb_batch_size = [1]
'''生成需要的ranges, varTypes, borders等'''
ub = np.hstack((ub_hidden_n, ub_lr, ub_batch_size))
lb = np.hstack((lb_hidden_n, lb_lr, lb_batch_size))
ranges = np.vstack((lb, ub))
varTypes = np.ones(num_hidden_neurons + 2)
borders = np.ones((2, num_hidden_neurons + 2))
'''生成译码矩阵FieldDR'''
FieldDR = ea.crtfld(Encoding, varTypes, ranges, borders)
FieldDR
array([[3.200e+01, 3.200e+01, 3.200e+01, 3.200e+01, 3.200e+01, 3.200e+01,
1.000e+00, 1.000e+00],
[1.024e+03, 1.024e+03, 1.024e+03, 1.024e+03, 1.024e+03, 1.024e+03,
1.000e+03, 2.000e+00],
[1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00,
1.000e+00, 1.000e+00]])
'''生成种群Chrom'''
Chrom = ea.crtip(Nind, FieldDR) #crtip (创建元素是整数的种群染色体矩阵)
Chrom
array([[ 554, 437, 100, 401, 908, 653, 866, 1],
[ 746, 410, 992, 55, 101, 456, 626, 1],
[ 391, 409, 388, 975, 899, 897, 660, 1],
[ 469, 771, 993, 760, 1002, 624, 972, 2],
[ 36, 72, 900, 912, 694, 767, 960, 1],
[ 153, 951, 439, 222, 383, 67, 226, 2],
[ 444, 612, 692, 319, 484, 354, 482, 2],
[ 101, 478, 657, 79, 77, 629, 551, 1],
[ 670, 454, 962, 339, 196, 922, 697, 1],
[ 849, 137, 507, 207, 172, 731, 893, 2]], dtype=int32)
进化迭代相关的函数
当完成了种群染色体的初始化后,就可以进行进化迭代了。这部分是在进化算法模板里调用。
迭代过程中包括:
- 调用ranking 或scaling 等计算种群适应度。
- 调用selecting 进行选择操作(也可以直接调用低级选择函数)。
- 调用recombin 进行重组操作(也可以直接调用低级重组函数)。
- 调用mutate 进行变异操作(也可以直接调用低级变异函数)。
选择 ea.selecting()
- dup (Duplication,基于适应度排序的直接复制选择)
- ecs (Elite Copy Selection,精英复制选择)
- etour (精英保留锦标赛选择)
- otos (One-to-One Survivor Selection,一对一生存者选择)
- rcs (Random Compensation Selection,随机补偿选择)
- rps (Random Permutation Selection,随机排列选择)
- rws (Roulette Wheel Selection,轮盘赌选择)
- sus (Stochastic Universal Sampling,随机抽样选择)
- tour (Tournament,锦标赛选择)
- urs (Uncommitted Random Selection,无约束随机选择)
Example
FitnV = np.random.rand(Nind)
FitnV = FitnV.reshape(-1,1)
FitnV
array([[0.47246408],
[0.6966635 ],
[0.8280383 ],
[0.35520503],
[0.60798975],
[0.91590692],
[0.69238913],
[0.58686945],
[0.45008303],
[0.82214108]])
SelCh_sel = Chrom[ea.selecting('rws', FitnV, Nind-1), :] #选择,采用‘rws’轮盘赌选择
SelCh_sel
array([[391, 409, 388, 975, 899, 897, 660, 1],
[101, 478, 657, 79, 77, 629, 551, 1],
[444, 612, 692, 319, 484, 354, 482, 2],
[ 36, 72, 900, 912, 694, 767, 960, 1],
[746, 410, 992, 55, 101, 456, 626, 1],
[153, 951, 439, 222, 383, 67, 226, 2],
[849, 137, 507, 207, 172, 731, 893, 2],
[153, 951, 439, 222, 383, 67, 226, 2],
[153, 951, 439, 222, 383, 67, 226, 2]], dtype=int32)
SelCh_sel2 = Chrom[ea.selecting('tour', FitnV, Nind-1), :] #选择,采用‘rws’轮盘赌选择
SelCh_sel2
array([[101, 478, 657, 79, 77, 629, 551, 1],
[444, 612, 692, 319, 484, 354, 482, 2],
[849, 137, 507, 207, 172, 731, 893, 2],
[153, 951, 439, 222, 383, 67, 226, 2],
[849, 137, 507, 207, 172, 731, 893, 2],
[153, 951, 439, 222, 383, 67, 226, 2],
[746, 410, 992, 55, 101, 456, 626, 1],
[391, 409, 388, 975, 899, 897, 660, 1],
[391, 409, 38