遗传算法是模拟自然界生物进化机制进行迭代优化的算法. 它通过模拟"适者生存, 优胜劣汰" 的法则, 在所有可能的解决方法中找出最符合该问题所要求的条件的解决办法.
在遗传算法中, 通过编码组成初始群体后, 遗传操作的任务就是通过对群体中的每个个体进行适应度评评估进而进行筛选, 从而实现"优胜劣汰"的"进化"过程. 从优化搜索的角度而言, 遗传操作可使问题的解一代代地优化, 从而逼近最优解.
遗传算法包含三个基本遗传算子(genetic operator): 选择, 交叉和变异.
需要注意的是, 虽然个体遗传算子的操作都是在随机扰动的情况下进行的, 但这种随机化操作和传统的随机搜索方法存在差别: 遗传操作所进行的是高效有向的搜索.
遗传操作的效果和上述三个遗传算子所取的操作概率, 编码方法, 群体大小, 初始群体和适应度函数的设定密切相关.
我们称"从群体中选择优胜的个体, 淘汰劣质的个体"的操作为 选择. 选择算子又称再生算子.
选择操作建立在群体中个体的适应度评估之上. 目前常用的选择算子有: 适应度比例法, 随机遍历抽样法, 局部选择法.
轮盘赌选择法 是最简单最常用的选择法. 在该方法中, 每个个体的被选概率与其适应度数值成正比例:
设群体大小为 n n n, 其中个体 i i i 的适应度为 f i f_{i} fi, 则 i i i 被选择的概率为 P i = f i ∑ i = 1 n f i . P_{i} = \frac{f_{i}}{\sum_{i=1}^{n}f_{i}}. Pi=∑i=1nfifi.
计算出群体中每个个体的被选概率后, 为了选择"交配"个体, 需要进行多轮选择. 每一轮选择中会产生一个介于 0 , 1 0,1 0,1 之间的均匀随机数, 并将其作为指针来确定被选个体. 个体被选中后, 可随机地组成交配对, 以供后续的交叉操作.
在自然界生物进化过程中起核心作用的是生物遗传因子的重组(包括变异). 对应地, 在遗传算法中起核心作用的是遗传操作的交叉算子, 交叉即指将两个父代个体的部分结构加以替换重组, 从而生成全新个体的操作.
交叉算子根据交叉率将种群中的两个个体随机地交换某些"基因", 根据"基因"编码表示的差异. 有离散重组, 中间重组, 线性重组, 扩展线性重组, 单点/多点交叉, 均匀交叉, 洗牌交叉, 缩小代理交叉等算子. 最常用的交叉算子是单点交叉. 其具体操作是: 在个体串中随机设定一个交叉点, 实行交叉时该点前或该点后的两个个体的部分结构进行互换, 并生成两个新的个体.
变异算子对群体中的个体串上的某些"基因座"上的"基因值"做变动. 依据个体编码表示方法的不同, 可以有以下算法: 实值变异和二进制变异.
一般来说, 变异算子的基本操作步骤如下:
在遗传算法中引入"变异"概念和功能的目的有二:
在遗传算法中, 交叉算子因其全局搜索能力强的特点而作为主要算子, 变异算子因其局部搜索能力突出的特点作为辅助算子. 通过这两种算子的配合, 遗传算法得以兼顾全局搜索和局部搜索的均匀搜索能力.
当群体在进化中陷于搜索空间的某个超平面, 而仅靠交叉无法摆脱时, 通过变异操作可以摆脱该超平面.
当已通过交叉算子形成所期望形成的"算法块"时, 变异操作反而有可能将其破坏.
当最优个体的适应度达到设定的阈值, 或最优个体的适应度和群体适应度不再上升, 或迭代次数达到阈值时, 算法终止. 预设的迭代次数一般为 100 − 500 100-500 100−500 代.
本节对遗传算法的程序设计和 MATLAB工具箱进行讲解:
随机初始化种群 P ( t ) = x 1 , x 2 , ⋯ , x n P(t) = {x_{1},x_{2},\cdots,x_{n}} P(t)=x1,x2,⋯,xn, 计算 P ( t ) P(t) P(t) 中个体的适应值:
Begin
t = 0
initialize P(t)
calculate the fitness value of P(t)
while(Not satisfied with the stopping critiria)
do
begin
t += 1
choose P(t) from P(t+1)
reassemble P(t)
calculate the fitness value of P(t)
end
[例]
求函数:
f ( x ) = 9 s i n ( 5 x ) + 8 c o s ( 4 x ) , x ∈ [ 0 , 15 ] f(x) = 9sin(5x) + 8cos(4x),\ \ \ \ x \in [0,15] f(x)=9sin(5x)+8cos(4x), x∈[0,15]
的最大值.
[解]
initpop.m
initpop.m 用于实现群体初始化. popsize 表示群体大小, chromlength表示染色体长度. 其取决于变量二进制编码长度.
%初始化
function pop = initpop(popsize, chromlength)
pop = round(rand(popsize, chromlength));
%rand 函数随机产生每个单元为 {0,1} ,行数为 popsize ,列数为 chromlength 的矩阵
%round 函数对矩阵中的每个单元进行圆整, 如此产生随机的初始种群
end
decodechrom.m
二进制数转化为十进制数: decodechrom.m
函数的功能是将染色体(二进制编码)转换为十进制.
function pop2 = decodebinary(pop)
[px,py] = size(pop); %求pop的行,列数
for i = 1:py
pop1(:,i) = 2.^(py-i).*pop(:,i);
end
pop2 = sum(pop1,2); %求pop1的每行元素和
end
%截取编码长度
function pop2 = decodechrom(pop,spoint,length)
pop1 = pop(:,spoint:spoint+length-1);
pop2 = decodebinary(pop1);
end
calobjvalue.m
function[objvalue] = calobjvalue(pop)
temp1 = decodechrom(pop,1,10);
x = temp1*10/1023;
objvalue = 10*sin(5*x)+7*cos(4*x);
end
calfitvalue.m
function fitvalue = calfitvalue(objvalue)
global Cmin;
Cmin = 0;
[px,py] = size(objvalue);
for i = 1:px
if objvalue(i) + Cmin>0
temp = Cmin + objvalue(i);
else
temp = 0.0;
end
fitvalue(i) = temp;
end
fitvalue = fitvalue'
selection.m
function [newpop] = selection(pop,fitvalue)
totalfit = sum(fitvalue); %计算适应值之和
fitvalue = fitvalue/totalfit; %计算单个个体被选的概率
fitvalue = cumsum(fitvalue);
[px,py] = size(pop);
ms = sort(rand(px,1)); %从小到大排列
fitin = 1;
newin = 1;
while newin <= px
if(ms(newin))
crossover.m
pc
交叉.function [newpop] = crossover(pop,pc)
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:2:px-1
if(rand
mutation.m
pm
随机翻转.function [newpop] = mutation(pop,pm)
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:px
if (rand
best.m
function [bestindividual,bestfit] = best(pop,fitvalue)
[px,py] = size(pop);
bestindividual = pop(1,:);
bestfit = fitvalue(1);
for i=2:px
if fitvalue(i)>bestfit
bestindividual = pop(i,:);
bestfit = fitvalue(i);
end
end
main.m
clc;clear all;
popsize = 200; %群体大小
chromlength = 10; %字符串长度
pc = 0.7; %交叉概率
pm = 0.005; %变异概率
pop = initpop(popsize, chromlength);
for i = 1:200
[objvalue] = calobjvalue(pop);
fitvalue = calfitvalue(objvalue);
[newpop] = selection(pop,fitvalue);
[newpop] = crossover(pop,pc);
[newpop] = mutation(pop,pc);
[bestindividual,bestfit] = best(pop,fitvalue);
y(i) = max(bestfit);
n(i) = i;
pop5 = bestindividual;
x(i) = decodechrom(pop5,1,chromlength)*10/1023;
pop = newpop;
end
fplot('9*sin(5*x) + 8*cos(4*x)',[0 15])
hold on
plot(x,y,'r*')
hold off
运行主程序, 得到结果如下: