遗传算法基本原理
借鉴物种进化的思想,将欲求解问题编码,把可行解转化为字符串形式。初始化随机产生一个种群,用合理的评价函数对种群进行评估,在此基础上进行选择、交叉、变异的操作。选择算子根据父代中个体适值大小进行选择或淘汰,保证了算法的最优搜索方向。
交叉算子模拟基因重组及随机信息交换,产生更好的1个体,使其在可行域中有效搜索。
变异算子模拟基因突变,保证了算法的全局搜索能力,避免陷入局部最优。
遗传算法基本过程
1.编码
有多种编码方式,一般采用二进制编码
2.解码
目的是为了将不直观的二进制数据串还原成十进制
3.初始种群
利用随机函数产生k位(假设二进制数的最大长度为k)的0、1排列,将该排列数表示一个染色体,每个染色体代表一个初始值
4.选择
根据个体适应值的比例来确定个体的选择概率,是一个随机采用的过程,一般再用轮盘赌算法来进行选择。
这里来举个🌰栗子来解释轮盘赌算法
个体序号 1 2 3 4 5 6 7 8 9 10
适应度 8 2 17 2 12 11 7 3 7
适应度累计值 8 10 27 34 36 48 59 66
随机数 23 49 76 13 1 27 57
被选中的个体号 3 7 10 3 1 3 7
设个体序号为i ,适应度累计值 为 个体序号1~i的适应度的累加和;
被选中的个体号为 比随机数大的最小的适应度累计值的索引
5.交叉
随机产生一个1到k-1的数(假设二进制数的最大长度为k),个体A、B在该位后的染色体进行交换

6.变异
为了避免在算法迭代后期出现种群过早收敛,随机选取1~k中的某位若其为0将其变为1,若其为1将其变为0
7.个体适应度评估
在设计适应度函数时要考虑:
1.适应度函数能否反映解的优劣
2.该函数是否时单值的和非负的
对于函数优化问题,适应度可取为函数值
8.复制
将子代复制为父代
无约束目标函数的最大值的求解
%target.m
% 案例一:无约束目标函数的最大值
% 求解maxf(x)=200*e(−0.05x)*sinx; x∈[−2,2]
%主程序:用遗传算法求解y=200*exp(-0.05*x).*sin(x)在[-2 2]区间上的最大值
clc;
global BitLength %全局变量,计算如果满足求解精度至少需要编码的长度
global boundsbegin %全局变量,自变量的起始点
global boundsend %全局变量,自变量的终止点
bounds=[-2 2];%一维自变量的取值范围
precision=0.0001;%运算精度
boundsbegin=bounds(:,1);
boundsend=bounds(:,2);
%计算满足求解精度至少需要多长的染色体
BitLength=ceil(log2((boundsend-boundsbegin)'./precision));
popsize=50;%初始种群大小
Generationnmax=20;%最大代数
pcrossover=0.9;%交配概率
pmutation=0.09;%变异概率
%产生初始种群
%Round函数返回一个数值,该数值是按照指定的小数位数进行四舍五入运算的结果。可是当保留位跟着的即使是5,有可能进位,也有可能舍去,机会各50%。
population=round(rand(popsize,BitLength));%随机产生初始种群,行为种群大小,列为二进制长度
%计算适应度,返回适应度Fitvalue和累计概率cumsump
[Fitvalue,cumsump]=fitnessfun(population);%输入population返回适应度和累计概率
Generation=1;
while Generation<Generationnmax+1
for j=1:2:popsize %1对1对的群体进行交叉、变异
%选择操作
seln=selection(population,cumsump);%选择两个个体,返回个体的序号
%交叉操作
scro=crossover(population,seln,pcrossover);
scnew(j,:)=scro(1,:);%先两个个体交叉,再分别对两个个体进行变异
scnew(j+1,:)=scro(2,:);
%变异操作 在交叉基础上变异
smnew(j,:)=mutation(scnew(j,:),pmutation);
smnew(j+1,:)=mutation(scnew(j+1,:),pmutation);
end
population=smnew;%产生了新的种群
%计算新种群的适应度
[Fitvalue,cumsump]=fitnessfun(population);
%记录当前代最好的适应度和平均适应度
[fmax,nmax]=max(Fitvalue);%最好的适应度为fmax(函数值最大),其对应个体为nmax
fmean=mean(Fitvalue);%平均适应度
ymax(Generation)=fmax;%每代中最好的适应度
ymean(Generation)=fmean;%每代中的平均适应度
%记录当前代的最佳染色体个体
x=transform2to10(population(nmax,:));%population(nmax,:)为最佳染色体个体,x返回的时其对应的十进制数
%自变量取值范围[-2,2],需要把经过遗传运算的最佳染色体整合到[-2,2]区间
xx=boundsbegin+x*(boundsend-boundsbegin)/(power(2,BitLength)-1);
xmax(Generation)=xx;
Generation=Generation+1;
end
Generation=Generation-1;
targetfunvalue=targetfun(xmax);
[Besttargetfunvalue,nmax]=max(targetfunvalue);
Bestpopulation=xmax(nmax);
figure(1);
hand1=plot(1:Generation,ymax);
set(hand1,'linestyle','-','linewidth',1.8,'marker','*','markersize',6);
hold on;
hand2=plot(1:Generation,ymean);
set(hand2,'color','r','linestyle','-','linewidth',1.8,'marker','h','markersize',6);
xlabel('进化代数');ylabel('最大/平均适应度');
xlim([1 Generationnmax]);
legend('最大适应度','平均适应度');
hold off;
%fitnessfun.m
%计算适应度函数 返回适应度 累计概率
function [Fitvalue,cumsump]=fitnessfun(population)
global BitLength;
global boundsbegin;
global boundsend;
popsize=size(population,1);%计算个体个数,有popsize个个体
for i=1:popsize
x=transform2to10(population(i,:));%将二进制转换为十进制
%译码过程 转化为[-2,2]区间的实数
xx=boundsbegin+x*(boundsend-boundsbegin)/(power(boundsend,BitLength)-1);
Fitvalue(i)=targetfun(xx);%计算函数值即适应度,保存在行向量中
end
%给适应度函数加上一个大小合理的数以便保证种群适应值为正数
Fitvalue=Fitvalue'+230;%转化为列向量
%计算选择概率
fsum=sum(Fitvalue);
Pperpopulation=Fitvalue/fsum;%适应度归一化,及被复制的概率
%计算累计概率
cumsump(1)=Pperpopulation(1);
for i=2:popsize
cumsump(i)=cumsump(i-1)+Pperpopulation(i);%求累计概率
end
cumsump=cumsump';%累计概率 转化为行向量
end
%selection.m
%新种群选择操作 选择两个个体,返回个体序号,可能两个序号相同
function seln=selection(population,cumsump)%参数 种群 个体累积概率
%从种群中选择两个个体 所以下面的过程循环两次
for i=1:2
r=rand;%产生一个随机数
%模拟轮盘赌算法
prand=cumsump-r;
j=1;
while prand(j)<0
j=j+1;
end
seln(i)=j;%选中个体的序号
end
end
%IfCroIfMut.m %判断遗传运算是否需要进行交叉或变异 %mutORcro为动作(交叉、变异)发生的概率 %根据概率mutORcro决定是否进行操作,产生1的概率是mutORcro,产生0的概率为1-mutORcro function pcc=IfCroIfMut(mutORCro) test(1:100)=0;%1*100的行向量 l=round(100*mutORCro); test(1:l)=1; n=round(rand*99)+1; pcc=test(n); end
%crossover.m
%新种群交叉操作
function scro=crossover(population,seln,pc)%参数 种群 选择的两个个体 交配的概率
BitLength=size(population,2);%二进制的个数
pcc=IfCroIfMut(pc);%根据交叉概率决定是否进行交叉操作,1则是,0则否
if pcc==1 %进行交叉操作
%获取交换位前面一位的index
chb=round(rand*(BitLength-2))+1;%在[1,BitLength-1]范围内随机产生一个交叉位
scro(1,:)=[population(seln(1),1:chb) population(seln(2),chb+1:BitLength)];
scro(2,:)=[population(seln(2),1:chb) population(seln(1),chb+1:BitLength)];
else
scro(1,:)=population(seln(1),:);
scro(2,:)=population(seln(2),:);
end
end
%mutation.m
%新种群变异操作
%snew为一个个体
function snnew=mutation(snew,pmutation)
BitLength=size(snew,2);%获取个体的二进制长度
snnew=snew;
pmm=IfCroIfMut(pmutation);%根据变异概率决定是否进行变异操作,1则是,0则否
if pmm==1
chb=round(rand*(BitLength-1))+1;%在[1,BitLength]范围内随机产生一个变异位
snnew(chb)=abs(snew(chb)-1);%0变成1,1变成0
end
end
%transform2to10.m将二进制转换为十进制
function x=transform2to10(population)
BitLength=size(population,2);%Population的列,即二进制的长度
x=population(BitLength);%x=末位
for i=1:BitLength-1
x=x+population(BitLength-i)*power(2,i);
end
end
%targetfun.m %对于优化最大值或极大值函数问题,目标函数可以作为适应度函数 function y=targetfun(x) y=200*exp(-0.05*x).*sin(x); end

