遗传算法的matlab实现(更新了种群演变动画)
注:智能算法的难点在于如何将方法与具体问题结合
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Genetic Algorithms %
% Author:Ji Jungang Time:2020/08/23 %
% 对于多变量问题,交叉和变异以及fitness需要修改,若采用实值编码交叉 %
%和变异也需修改 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 主函数
function GA_JJG()
clear;clc;
%种群大小
popsize=300;
%二进制编码长度
chromlength=10;
%交叉概率
pc=0.7;
%变异概率
pm=0.001;
%初始种群
pop=initpop(popsize,chromlength);
%制作种群演化动图
c=zeros(200,300);
d=zeros(200,300);
for i=1:200
%计算适应度
objvalue=cal_objvalue(pop);
fitvalue=15+objvalue;%有时目标函数需要转变
%选择操作
newpop=selection(pop,fitvalue);
%交叉操作
newpop=crossover(newpop,pc);
%变异操作
newpop=mutation(newpop,pm);
%寻找最优解
[bestindividual,bestfit]=best(pop,fitvalue);
x2=binary2decimal(bestindividual);
x1=binary2decimal(newpop);
y1=cal_objvalue(newpop);
y2=bestfit-15;
c(i,:)=x1;
d(i,:)=y1;
if(mod(i,20)==0) % 绘图
figure
fplot(@(x)10*sin(5*x)+7*cos(4*x),[0 10])
hold on
plot(x1,y1,'*')
plot(x2,y2,'go')
title(['迭代次数n=' num2str(i)]);
end
pop=newpop;
end
%制作种群演化动图
for k=1:200
fplot(@(x)10*sin(5*x)+7*cos(4*x),[0 10])
hold on
plot(c(k,:),d(k,:),'*')
hold off
pause(1)
drawnow;
end
end
%% 种群生成函数
function pop=initpop(popsize,chromlength)
pop=round(rand(popsize,chromlength));
end
% round四舍五入,rand矩阵
%% 解码(二进制变十进制,独立函数对于多变量情况直接调用)
function pop2=binary2decimal(pop)
[~,py]=size(pop);
for i=1:py
pop1(:,i)=2.^(py-i).*pop(:,i);
end
temp=sum(pop1,2);
pop2=temp*10/1023+0;
end
%% 计算适应度值(包含解码和目标函数)
function [objvalue]=cal_objvalue(pop)
x=binary2decimal(pop);
objvalue=10*sin(5*x)+7*cos(4*x);
end
%% 选择新个体(轮盘赌选择复制新个体)
function [newpop]=selection(pop,fitvalue)
[px,~]=size(pop);
totalfit=sum(fitvalue);
p_fitvalue=fitvalue/totalfit;
p_fitvalue=cumsum(p_fitvalue);%概率求和和排序
ms=sort(rand(px,1));%产生随机数并从小到大排列
fitin=1;
newin=1;
while newin<=px
if(ms(newin))<p_fitvalue(fitin)
newpop(newin,:)=pop(fitin,:);
newin=newin+1;
else
fitin=fitin+1;
end
end
end
%% 交叉(随机产生交叉节点,相邻两个交叉)
function newpop=crossover(pop,pc)
[px,py]=size(pop);
pop2=pop;
for i=1:2:px-1
if(rand<pc)
cpoint=randi([1 py-1]);
pop1(i,:)=[pop2(i,1:cpoint) pop2(i+1,cpoint+1:py)];
pop1(i+1,:)=[pop2(i+1,1:cpoint) pop2(i,cpoint+1:py)];
else
pop1(i,:)=pop2(i,:);
pop1(i+1,:)=pop2(i+1,:);
end
end
newpop=pop1;
end
%% 变异(随机产生变异节点)
function [newpop]=mutation(pop,pm)
[px,py]=size(pop);
pop2=pop;
for i=1:px
if(rand<pm)
mpoint=randi([1 py-1]);
pop1(i,:)=[pop2(i,1:mpoint) ~pop2(i,mpoint+1:py)];
else
pop1(i,:)=pop2(i,:);
end
end
newpop=pop1;
end
%% 寻找最优
function [bestindividual,bestfit]=best(pop,fitvalue)
[bestfit,index]=max(fitvalue);%index索引指出最大值所在行
bestindividual=pop(index,:);%提出所对应的行
end
上述代码是利用二进制编码实现寻找函数最大值的例子,是最基本的遗传算法。下列的图展示的是不同迭代次数下种群中所有个体的分布情况: