下面使用一个具体的例子来解释遗传算法。
问题如下:
求函数
f(x)=9×sin(5x)+8×cos(4x), x∈[5,10]
的最大值。
设置参数
首先需要设定几个参数:
popsize = 30; % 种群规模
chromlength = 10; % 染色体长度
pc = 0.5; % 交叉概率
pm = 0.05; % 变异概率
maxgen = 20; % 最大迭代数
lx = 5; ux = 10;
上面分别设定了遗传算法的参数和自变量x的取值范围。
下面是对几个参数选取的说明:
参数 | 太大 | 太小 | 常用值 |
---|---|---|---|
种群规模 | 难以收敛且浪费资源 | 近亲交配,产生病态基因 | 0~100 |
变异概率 | 可能破坏已有的有利模式 | 多样性下降太快,容易丢失有效基因 | 0.0001~0.2 |
交叉概率 | 可能破坏已有的有利模式 | 不能有效更新种群 | 0.4~0.99 |
进化代数 | 容易早熟后浪费资源 | 不容易收敛 | 100~500 |
初始化
初始化的种群是随机的,这里使用二进制对自变量进行编码,初始化子程序如下:
function pop = initpop(popsize, chromlength)
% 初始化种群,二进制编码
% popsize input 种群规模
% chromlength input 染色体长度
% pop output popsize x chromelength的二进制矩阵
pop = round(rand(popsize, chromlength));
end
目标函数值
由于自变量采用二进制编码,因此需要首先将种群中的染色体从二进制转化为十进制。下面的子程序将二进制编码转换成十进制:
function rpop = decodebinary(pop)
% 将二进制矩阵中的每一行转化为十进制数
% pop input 二进制矩阵
% rpop output 十进制列向量
[n, l] = size(pop);
temp = zeros(l, 1);
for i = 1:l
temp(i,1) = 2^(l-i);
end
rpop = pop * temp;
end
使用该函数对染色体进行解码:
function rpop = decodechrom(pop, spoint, length)
% 将每行中列为spoint : spoint+length-1的二进制矩阵转化为十进制数
% pop input 种群
% spoint input 开始位置
% length input 长度
% rpop output 十进制列向量
tpop = pop(:, spoint: spoint+length-1);
rpop = decodebinary(tpop);
end
decodechrom()
与decodebinary()
的区别是,decodechrom()
可以使用参数spoint
和length
指定需要解码的列,而decodebinary()
不行。
最后,使用下面的子程序求出目标函数值:
function [objvalue] = calobjvalue(pop, lx, ux)
% 计算目标函数值,需根据实际情况重写
% pop input 种群
% lx input 自变量最小值
% ux input 自变量最大值
% objvalue output 目标函数值
decchrom = decodechrom(pop, 1, size(pop, 2)); % 将二进制转化为十进制
x = decchrom / (2^size(pop ,2)-1) * (ux - lx) + lx;
objvalue = 9 * sin(5 * x) + 8 * cos(4 * x);
end
calobjvalue()
函数首先将二进制解码为十进制,将解码后的数值对应到自变量变化范围,最后求出函数值。
适应值
设f(x)
为目标函数值,F(x)
为适应值,这里采用下面的策略求适应值,但是此方法并不适用于所有情况,需要需根据实际情况重写:
对于最小化问题:
对于最大化问题:
下面是代码实现:
function fitvalue = calfitvalue(objvalue, opt)
% 根据目标函数值生成适应度值,需根据实际情况重写
% objvalue input 目标函数值
% opt input 操作模式,指定为'min'或'max'
% fitvalue output 适应度值
fitvalue = zeros(size(objvalue,1), 1);
for i = 1 : size(objvalue, 1)
if strcmp(opt, 'min')
if objvalue(i) < 0
temp = -objvalue(i);
else
temp = 0;
end
else
if objvalue(i) > 0
temp = objvalue(i);
else
temp = 0;
end
end
fitvalue(i) = temp;
end
fitvalue = fitvalue';