原理
遗传算法是用于解决最优化的一种搜索启发式算法,是进化算法的一种。这种启发式通常用来生成有用的解决方案来优化和搜索问题。
遗传操作是模拟生物基因遗传的做法。在遗传算法中,通过编码组成初始群体后,遗传操作的任务就是对群体的个体按照它们对环境适应度(适应度评估)施加一定的操作,从而实现优胜劣汰的进化过程。从优化搜索的角度而言,遗传操作可使问题的解一代又一代地优化,并逼近最优解(通常每次算法执行的结果,可能会有不同)。
遗传操作包括以下三个基本遗传算子:选择,交叉,变异。
个体遗传算子的操作都是在随机扰动的情况下进行的。因此群体中个体向最优解迁移的规则是随机的。不过这种随机搜索是有向搜索而不是无向搜索(这也是遗传算法与传统搜索方法的区别)。
1、选择
从群体中选择优胜的个体,淘汰劣质个体的操作叫做选择。主要是为了将优化的个体直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。
选择操作是建立在群体中个体的适应度评估基础上的。目前常用算子有:适应度比例方法,随机遍历抽样法,局部选择法。
这里重点介绍以下轮盘赌法(适应度越大,概率越大):
设群体大小为n,其中个体i的适应度为fi,所有个体的总适应度是sumf,则i被选择的概率为:
pi = fi / sumf
概率反映了个体i的适应度在整个群体的个体适应度总和中所占的比例。
2、交叉
把两个父代个体的部分结构加以替换重组而生成新个体的操作。交叉算子根据交叉率将种群中的两个个体随机地交换某些基因,能够产生新的基因组合,期望将有益基因组合在一起。
有以下编码算法:
(1)实值重组:离散重组、中间重组、线性重组、扩展线性重组
(2)二进制交叉:单点交叉、多点交叉、均匀交叉、洗牌交叉、缩小代理交叉
这里重点介绍一下单点交叉:在个体中随机设定一个交叉点,实行交叉时,该点前或后的两个个体的部分结构进行互换,并生成两个新个体。
3、变异
对群体中的个体的某些基因座上的基因值做变动。一般有实值变异、二进制变异。
基本步骤如下:
(1)对群体中所有个体以实现设定的变异概率判断是否进行变异
(2)对进行变异的个体随机选择变异位进行变异
遗传算法中,交叉算子因其全局搜索能力而作为主要算子,变异算子因其局部搜索能力而作为辅助算子(变异率一般很小0.001~0.1之间取值)。
(4)终止条件
当最优个体的适应度达到给定的阈值,或者最优个体的适应度和群体适应度不再上升时,或者迭代次数达到预设的次数时,算法终止。(预设的代数一般设为100~500)
代码
利用遗传算法求解函数极值
%解决的问题:求函数f(x)=11*sin(6*x)+7*cos(5*x) x∈[-pi,pi]的最大值
%主程序
clear all
clc
popsize=30; %设置初始参数,群体大小
chromlength=8; %字符串长度(个体长度),染色体长度
pc=0.7; %设置交叉概率
pm=0.02; %设置变异概率
pop=initpop(popsize,chromlength); %运行初始化函数,随机产生初始群体
for i=1:30 %20为迭代次数
[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('11*sin(6*x)+7*cos(5*x)',[-pi pi])
grid on
hold on
plot(x,y,'r*')
xlabel('自变量')
ylabel('目标函数值')
title('种群中的个体数目为30,二进制编码长度为8,交叉概率为0.7,变异概率为0.02')
fmax=max(y);
hold off
%初始化函数
function pop=initpop(popsize,chromlength)
pop=round(rand(popsize,chromlength));
%popsize表示群体的大小,chromlength表示染色体的长度(二值数的长度)
%计算目标函数值
%产生 [2^n 2^(n-1) ... 1] 的行向量,然后求和,将二进制转化为十进制
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);
end
%将二进制编码转换成十进制
function pop2=decodechrom(pop,spoint,length)
pop1=pop(:,spoint:spoint+length-1);
%取出第“spoint”位开始到第“spoint+length-1”位的参数
pop2=decodebinary(pop1);
%利用上面函数“decodebinary(pop)”将用二进制表示的个体基因变为十进制数
end
%将二进制编码转换成十进制
function pop2=decodechrom(pop,spoint,length)
pop1=pop(:,spoint:spoint+length-1);
%取出第“spoint”位开始到第“spoint+length-1”位的参数
pop2=decodebinary(pop1);
%利用上面函数“decodebinary(pop)”将用二进制表示的个体基因变为十进制数
end
%实现目标函数的计算
function [objvalue]=calobjvalue(pop)
temp1=decodechrom(pop,1,8); %将pop每行转化成十进制数
x=temp1*10/1023; %将二值域中的数转化为变量域的数
objvalue=11*sin(6*x)+7*cos(5*x);%计算目标函数值
end
%计算个体的适应值
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';
end
%选择复制
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; %fitvalue(fitin)代表第fitin个个体的单个个体被选择的概率
newin=1;
while newin<=px
if(ms(newin))<fitvalue(fitin)
%ms(newin)表示的是ms列向量中第"newin"位数值,小于fitvalue(fitin)
newpop(newin,:)=pop(fitin,:);
%赋值 ,即将旧种群中 的第fitin个个体保留到下一代(newpop)
newin=newin+1;
else
fitin=fitin+1;
end
end
end
%交叉
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
end
%变异
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
end
%求出群体中最大的适应值及其个体
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
end
%求出最佳个体的对应X值
function t=decodebinary2(pop)
[px,py]=size(pop);
for j=1:py;
pop1(:,j)=2.^(py-1).*pop(:,j);
py=py-1;
end
temp2=sum(pop1,2);
t=temp2*2*pi/1023;
end
遗传算法在TSP中的应用
%主函数
clear;
clc;
%输入参数
N=10; %%城市的个数
M=20; %%种群的个数
C=100; %%迭代次数
C_old=C;
m=2; %%适应值归一化淘汰加速指数
Pc=0.8; %%交叉概率
Pmutation=0.2; %%变异概率
%生成城市的坐标
pos=randn(N,2);
%生成城市之间距离矩阵
D=zeros(N,N);
for i=1:N
for j=i+1:N
dis=(pos(i,1)-pos(j,1)).^2+(pos(i,2)-pos(j,2)).^2;
D(i,j)=dis^(0.5);
D(j,i)=D(i,j);
end
end
%生成初始群体
popm=zeros(M,N);
for i=1:M
popm(i,:)=randperm(N);
end
%随机选择一个种群
R=popm(1,:);
figure(1);
scatter(pos(:,1),pos(:,2),'k.');
xlabel('横轴')
ylabel('纵轴')
title('随机产生的种群图')
axis([-3 3 -3 3]);
figure(2);
plot_route(pos,R);
xlabel('横轴')
ylabel('纵轴')
title('随机生成种群中城市路径情况')
axis([-3 3 -3 3]);
%初始化种群及其适应函数
fitness=zeros(M,1);
len=zeros(M,1);
for i=1:M
len(i,1)=myLength(D,popm(i,:));
end
maxlen=max(len);
minlen=min(len);
fitness=fit(len,m,maxlen,minlen);
rr=find(len==minlen);
R=popm(rr(1,1),:);
for i=1:N
fprintf('%d ',R(i));
end
fprintf('\n');
fitness=fitness/sum(fitness);
distance_min=zeros(C+1,1); %%各次迭代的最小的种群的距离
while C>=0
fprintf('迭代第%d次\n',C);
%%%选择操作%%%%
nn=0;
for i=1:size(popm,1)
len_1(i,1)=myLength(D,popm(i,:));
jc=rand*0.3;
for j=1:size(popm,1)
if fitness(j,1)>=jc
nn=nn+1;
popm_sel(nn,:)=popm(j,:);
break;
end
end
end
%每次选择都保存最优的种群
popm_sel=popm_sel(1:nn,:);
[len_m len_index]=min(len_1);
popm_sel=[popm_sel;popm(len_index,:)];
%交叉操作
nnper=randperm(nn);
A=popm_sel(nnper(1),:);
B=popm_sel(nnper(2),:);
for i=1:nn*Pc
[A,B]=cross(A,B);
popm_sel(nnper(1),:)=A;
popm_sel(nnper(2),:)=B;
end
%变异操作
for i=1:nn
pick=rand;
while pick==0
pick=rand;
end
if pick<=Pmutation
popm_sel(i,:)=Mutation(popm_sel(i,:));
end
end
%求适应度函数
NN=size(popm_sel,1);
len=zeros(NN,1);
for i=1:NN
len(i,1)=myLength(D,popm_sel(i,:));
end
maxlen=max(len);
minlen=min(len);
distance_min(C+1,1)=minlen;
fitness=fit(len,m,maxlen,minlen);
rr=find(len==minlen);
fprintf('minlen=%d\n',minlen);
R=popm_sel(rr(1,1),:);
for i=1:N
fprintf('%d ',R(i));
end
fprintf('\n');
popm=[];
popm=popm_sel;
C=C-1;
pause(1);
end
figure(3)
plot_route(pos,R);
xlabel('横轴')
ylabel('纵轴')
title('优化后的种群中城市路径情况')
axis([-3 3 -3 3]);
%适应度函数
function fitness=fit(len,m,maxlen,minlen)
fitness=len;
for i=1:length(len)
fitness(i,1)=(1-(len(i,1)-minlen)/(maxlen-minlen+0.0001)).^m;
end
end
%个体距离计算函数
function len=myLength(D,p)
[N,NN]=size(D);
len=D(p(1,N),p(1,1));
for i=1:(N-1)
len=len+D(p(1,i),p(1,i+1));
end
end
%交叉操作函数
function [A,B]=cross(A,B)
L=length(A);
if L<10
W=L;
elseif ((L/10)-floor(L/10))>=rand&&L>10
W=ceil(L/10)+8;
else
W=floor(L/10)+8;
end
p=unidrnd(L-W+1);
fprintf('p=%d ',p);
for i=1:W
x=find(A==B(1,p+i-1));
y=find(B==A(1,p+i-1));
[A(1,p+i-1),B(1,p+i-1)]=exchange(A(1,p+i-1),B(1,p+i-1));
[A(1,x),B(1,y)]=exchange(A(1,x),B(1,y));
end
end
%对调函数
function [x,y]=exchange(x,y)
temp=x;
x=y;
y=temp;
end
%变异函数
function a=Mutation(A)
index1=0;index2=0;
nnper=randperm(size(A,2));
index1=nnper(1);
index2=nnper(2);
%fprintf('index1=%d ',index1);
%fprintf('index2=%d ',index2);
temp=0;
temp=A(index1);
A(index1)=A(index2);
A(index2)=temp;
a=A;
end
%连点画图函数
function plot_route(a,R)
scatter(a(:,1),a(:,2),'rx');
hold on;
plot([a(R(1),1),a(R(length(R)),1)],[a(R(1),2),a(R(length(R)),2)]);
hold on;
for i=2:length(R)
x0=a(R(i-1),1);
y0=a(R(i-1),2);
x1=a(R(i),1);
y1=a(R(i),2);
xx=[x0,x1];
yy=[y0,y1];
plot(xx,yy);
hold on;
end
end
遗传算法的求解优化
function f=GAtestfcn(x)
for j = 1:size(x,1)
y = x(j,:);
temp1 = 0;
temp2 = 0;
y1 = y(1);
y2 = y(2);
for i = 1:10
temp1 = temp1 + i.*cos((i+1).*y1+i);
temp2 = temp2 + i.*cos((i+1).*y2+i);
end
f(j) = temp1.*temp2;
end
%在命令行窗口运行
[x, fal, exitflag, output] = ga(@GAtestfcn,2)