遗传算法
遗传算法是模拟自然界生物进化机制进行迭代优化的算法. 它通过模拟"适者生存, 优胜劣汰" 的法则, 在所有可能的解决方法中找出最符合该问题所要求的条件的解决办法.
文章目录
- 遗传算法
- 1. 基本原理
- 1.1 选择
- 1.2 交叉
- 1.3 变异
- 1.4 终止条件
- 2. 程序设计
1. 基本原理
在遗传算法中, 通过编码组成初始群体后, 遗传操作的任务就是通过对群体中的每个个体进行适应度评评估进而进行筛选, 从而实现"优胜劣汰"的"进化"过程. 从优化搜索的角度而言, 遗传操作可使问题的解一代代地优化, 从而逼近最优解.
遗传算法包含三个基本遗传算子(genetic operator): 选择, 交叉和变异.
需要注意的是, 虽然个体遗传算子的操作都是在随机扰动的情况下进行的, 但这种随机化操作和传统的随机搜索方法存在差别: 遗传操作所进行的是高效有向的搜索.
遗传操作的效果和上述三个遗传算子所取的操作概率, 编码方法, 群体大小, 初始群体和适应度函数的设定密切相关.
1.1 选择
我们称"从群体中选择优胜的个体, 淘汰劣质的个体"的操作为 选择. 选择算子又称再生算子.
选择操作建立在群体中个体的适应度评估之上. 目前常用的选择算子有: 适应度比例法, 随机遍历抽样法, 局部选择法.
轮盘赌选择法 是最简单最常用的选择法. 在该方法中, 每个个体的被选概率与其适应度数值成正比例:
设群体大小为 , 其中个体 的适应度为 , 则 被选择的概率为
计算出群体中每个个体的被选概率后, 为了选择"交配"个体, 需要进行多轮选择. 每一轮选择中会产生一个介于
1.2 交叉
在自然界生物进化过程中起核心作用的是生物遗传因子的重组(包括变异). 对应地, 在遗传算法中起核心作用的是遗传操作的交叉算子, 交叉即指将两个父代个体的部分结构加以替换重组, 从而生成全新个体的操作.
交叉算子根据交叉率将种群中的两个个体随机地交换某些"基因", 根据"基因"编码表示的差异. 有离散重组, 中间重组, 线性重组, 扩展线性重组, 单点/多点交叉, 均匀交叉, 洗牌交叉, 缩小代理交叉等算子. 最常用的交叉算子是单点交叉. 其具体操作是: 在个体串中随机设定一个交叉点, 实行交叉时该点前或该点后的两个个体的部分结构进行互换, 并生成两个新的个体.
1.3 变异
变异算子对群体中的个体串上的某些"基因座"上的"基因值"做变动. 依据个体编码表示方法的不同, 可以有以下算法: 实值变异和二进制变异.
一般来说, 变异算子的基本操作步骤如下:
- 对群中全部个体以事先设定的变异概率判断是否进行变异.
- 对确定要进行变异的个体随机选择变异位进行变异.
在遗传算法中引入"变异"概念和功能的目的有二:
- 使遗传算法具备局部随机搜索能力. 当遗传算法通过交叉算子接近最优解邻域时, 利用变异算子的这种局部随机搜索能力可以加速向最优解收敛.
- 使遗传算法可维持群体多样性, 避免出现未成熟收敛现象.
在遗传算法中, 交叉算子因其全局搜索能力强的特点而作为主要算子, 变异算子因其局部搜索能力突出的特点作为辅助算子. 通过这两种算子的配合, 遗传算法得以兼顾全局搜索和局部搜索的均匀搜索能力.
当群体在进化中陷于搜索空间的某个超平面, 而仅靠交叉无法摆脱时, 通过变异操作可以摆脱该超平面.
当已通过交叉算子形成所期望形成的"算法块"时, 变异操作反而有可能将其破坏.
1.4 终止条件
当最优个体的适应度达到设定的阈值, 或最优个体的适应度和群体适应度不再上升, 或迭代次数达到阈值时, 算法终止. 预设的迭代次数一般为
2. 程序设计
本节对遗传算法的程序设计和 MATLAB工具箱进行讲解:
随机初始化种群 , 计算
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
[例]
求函数:
的最大值.
[解]
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))<fitvalue(fitin)
newpop(newin) = pop(fitin);
newin = newin + 1;
else
fitin = fitin + 1;
end
end
-
crossover.m
该函数功能为使群体中的每个个体之间都以概率pc
交叉.
function [newpop] = crossover(pop,pc)
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:2:px-1
if(rand<pc)
cpoint = round(rand*py);
newpop(i,:) = [pop(i,1:cpoint),pop(i+1,cpoint+1:py)];
newpop(i+1,:) = [pop(i+1,1:cpoint),pop(i,cpoint+1:py)];
else
newpop(i,:) = pop(i);
newpop(i+1,:) = pop(i+1);
end
end
-
mutation.m
该函数功能为实现变异: 父代中的每一个个体的每一位都以概率pm
随机翻转.
function [newpop] = mutation(pop,pm)
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:px
if (rand<pm)
mpoint = round(rand*py);
if mpoint <=0
mpoint = 1;
end
newpop(i) = pop(i);
if any(newpop(i,mpoint)) == 0
newpop(i,mpoint) = 1;
else
newpop(i,mpoint) = 0;
end
else
newpop(i) = pop(i);
end
end
-
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
运行主程序, 得到结果如下: