Matlab遗传算法与普通函数优化问题的结合
准备
在编写自己的代码之前应该了解的是算法的基本结构,具体可参考我之前的文章 点这里
文章虽然简单,但是也能了解基本该设置的参数与具体的算法结构。
遗传算法+普通函数优化问题
作为遗传算法最基本,也是最简单,也是最核心的内容,遗传算法对函数优化是内核,必须要掌握的。
选择较为简单的函数,
y
=
s
i
n
(
10
π
⋅
x
)
+
s
i
n
(
x
)
+
s
i
n
(
5
⋅
x
)
y=sin\left( 10\pi\cdot x \right) +sin\left(x\right) +sin\left( 5\cdot x \right)
y=sin(10π⋅x)+sin(x)+sin(5⋅x)
在matlab画出
[
0
,
5
]
\left[ \left. 0,5 \right] \right.
[0,5]范围的图像,可见在1.5左右存在最大值。
选择了谢菲尔德大学的Matlab遗传算法工具箱实现算法。
工具箱的导入较简单,可以自行在网上下载导入。
由于本文中关于交叉与变异的操作方法与适应度无关,仅在选择操作中的排序与适应度有关,因此排序决定了遗传算法整体的选取值趋向(最大值还是最小值)。
种群初始化
- 设置初始种族参数
%% 清屏
clc
clear
close all
%% 定义遗传算法参数
NIND=40; %个体数目
MAXGEN=50; %最大遗传代数
PRECI=10; %变量的二进制位数
GGAP=0.95; %代沟
px=0.7; %交叉概率
pm=0.01; %变异概率
lowb=0;upb=5; %个体的自变量范围
trace=zeros(2,MAXGEN); %寻优结果的初始值
FieldD=[PRECI;lowb;upb;1;0;1;1]; %区域描述器
Chrom=crtbp(NIND,PRECI); %初始种群
代沟
α
:
\alpha:
α:假设父代种群中的有
n
n
n个个体,则有
α
⋅
n
\alpha \cdot n
α⋅n个个体参与接下来的交叉变异操作,也决定了子代种群个体的数量。具体其他的参数含义见 点这里
关于最重要的crtbp()
函数,输入参数为个体数量与变量的二进制位数,在计算适应度前需要将该二进制数转化为十进制数。区域描述器正是用于二进制对十进制的转化。
F
i
e
l
d
D
=
[
l
e
n
;
l
b
;
u
b
;
c
o
d
;
s
c
a
l
e
;
l
b
i
n
;
u
b
i
n
]
FieldD=\left[ len;lb;ub;cod;scale;lbin;ubin \right]
FieldD=[len;lb;ub;cod;scale;lbin;ubin]
下表中解释了七个参数代表的含义,根据具体情况进行更改
len | lb | ub | code | scale | lbin | ubin | |||||
染色体长度 | 下界 | 上界 | 1:二进制\2:格雷编码 | 0:算数刻度\1:对数刻度 | 0:不包含边界\1:包含边界 |
该二进制位数仅代表进行进化操作中染色体的个数,在这里只需满足该二进制位数能够表示十进制中的[lowb,upb]
计算适应度
- 创建独立的.m文件计算适应度
function F=Fit_fun(X)
F=-(sin(10*pi*X)+sin(X)+sin(5*X));
end
为了求出最小值,将原函数的负值作为适应度。
个体选择
- 对适应度进行排序
- 采用随机遍历采样的方法从种群中选择个体
FitnV=ranking(ObjV); %分配适应度值
SelCh=select('sus',Chrom,FitnV,GGAP); %选择
r a n k i n g ranking ranking作为关键趋向决定函数这里摘录 m a t l a b matlab matlab的解释
This function ranks individuals represented by their associated cost, to be minimized, and returns a column vector FitnV containing the corresponding individual fitnesses.
For multiple subpopulations the ranking is performed separately for each subpopulation.
这个函数对个体进行排序,对于每个个体的相关代价取最小化,并返回一个个体适应度列向量FitnV。
对于多个子种群,对每个子种群分别排名。
可见该函数取最小值,因此整体的遗传算法优化对象为函数最小值,这也是为何适应度需取符号求最大值的原因。
交叉
- 采用单点交叉算子对个体的染色体进行重组
SelCh=recombin('xovsp',SelCh,px); %单点交叉
变异
- 采用离散变异对个体进行变异
SelCh=mut(SelCh,pm); %变异
- 除去使用专门的离散变异函数,还可以使用高级变异函数,采用该函数可以手动选择算子,更改算子更为方便。
SelCh=mutate('mut',SelCh,[],pm); %高级变异函数,可选择算子
S
e
l
C
h
=
m
u
t
a
t
e
(
M
U
T
,
C
h
r
o
m
,
F
i
e
l
d
D
R
,
M
u
t
O
p
t
)
SelCh=mutate(MUT, Chrom, FieldDR, MutOpt)
SelCh=mutate(MUT,Chrom,FieldDR,MutOpt)
M
U
T
MUT
MUT为算子名称,
C
h
r
o
m
Chrom
Chrom为当前种群,
F
i
e
l
d
D
R
FieldDR
FieldDR根据算子的不同参考如下:
[ ] | 矩阵行数为1 | 矩阵行数为2 |
---|---|---|
mut | mut | mutbga |
二进制编码 | 该位的进制数 | 变量范围 |
M
u
t
O
p
t
MutOpt
MutOpt在这里可以简单理解为变异概率。
例如输入:
F
i
e
l
d
D
R
=
[
2
,
2
,
5
,
5
,
5
]
;
FieldDR=\left[2,2,5,5,5 \right];
FieldDR=[2,2,5,5,5];
S
e
l
C
h
=
m
u
t
a
t
e
(
′
m
u
t
′
,
C
h
r
o
m
,
F
i
e
l
d
D
R
,
p
m
)
SelCh=mutate\left( 'mut',Chrom, FieldDR,pm \right)
SelCh=mutate(′mut′,Chrom,FieldDR,pm)注意FieldDR应与Chrom的列数相同
代表对原种群Chrom进行变异操作时,所有个体的第1,2位染色体是二进制编码,3,4,5位染色体是五进制编码.实际上这里的进制设置应在初始化种群时确定,后续的遗传算法中会涉及,这里可以不去理会。
鉴于组合不多且记忆麻烦建议直接使用mut
和mutbga
,但如果想要改进或者添加算法可以自定义变异算子,套用mutate
的模式。
程序中直接采用了mut
对种群进行变异操作。
插入子代记录最优解
- 子代重新插入保证了每一代的种群规模不变
- 因为求取目标函数的最小值所以取
min
- 记录当代最优解
[Chrom,ObjV]=reins(Chrom,SelCh,1,1,ObjV,ObjVSel); %子代重插入到父代,得到新种群
X=bs2rv(Chrom,FieldD); %转化为十进制
%获取每代的最优解及其序号,Y为最优解,I为个体的序号
[Y,I]=min(ObjV);
trace(1,gen)=X(I); %记下每代的最优值
trace(2,gen)=Y; %记下每代的最优值
gen=gen+1; %迭代增加
算法计算结果
![](https://i-blog.csdnimg.cn/blog_migrate/2ade018e8b3761caa5882dfaa933481c.png)
由于函数简单,在20多代左右最优解就已经稳定,此时已经产生了较好解,最优解如下:
![](https://i-blog.csdnimg.cn/blog_migrate/50bac6def8b38cbf52d1c8e7695c3eef.png)
代码地址
完整代码在 GitHub网站上,如果有条件可以支持一下。现在关注我你就是老粉了
参考文章
本文内容参考下列文章,如有任何问题还请联系该账号
史峰. MATLAB智能算法30个案例分析[M]. 北京航空航天大学出版社, 2011.