实值遗传算法求解函数极值问题(基于MATLAB)
声明:
1.本文源代码来自书目《智能优化算法及其MATLAB实例(第3版)》,目的在于为MATLAB初学者提供更简明的代码解析,方便读者了解算法及MATLAB编程基本原理。
2.文中代码每一行后都有相应注释,因此本文是一篇适合所有代码水平的学习者阅读的文章。
在例2.1中我们采用的是标准遗传算法,即采用二进制来进行基因编码。而另一种常用的编码方式为实值编码,即每个基因位不再是0或1,变成了一个实数。本文就是讨论在这样的编码机制下,利用MATLAB编程求解函数的极值问题。
补充知识:”君主法“选择交叉方式
在定义适应度函数后,对种群按适应度值升序排列,选取最优个体作为君主染色体,并按照排列后的顺序选取偶数位的染色体依次与君主染色体交叉,完成交叉过程。将得到的子代与父代合并后,再次按适应度值排序后取前NP个染色体作为下一次循环的种群,这就完成了选择过程。
例2.2 计算函数f(x)=x12+x22+···xn2(-20<=xi<=20)的最小值,其中个体x的维数n=10。这是一个简单的平方和函数,只有一个极小点在0处取得为0。
基于实值遗传算法的MATLAB求解代码如下:
%%%%%实值遗传算法求解求和函数极值问题%%%%%%%%
%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%
clear all; %清除所有变量
close all; %清图
clc; %清屏
D=10; %单条染色体上基因数目为10
NP=100; %染色体数目,即种群规模或取样样本数目
Xs=20; %上限
Xx=-20; %下限
G=1000; %最大遗传代数
f=zeros(D,NP); %创建并初始化初始种群二维数组
nf=zeros(D,NP); %创建并初始化子代种群二维数组由于我们选择和交叉采用君主方案,所以每代数目都为NP
Pc=0.8; %交叉概率
Pm=0.1; %变异概率
f=rand(D,NP)*(Xs-Xx)+Xx;%随机生成初始种群,rand(A,B)表示生成A行B列【0,1】随机小数矩阵
%%%%%%%%%%%%按适应度升序排列%%%%%%%%%%%%%%%%
for np=1:NP %对于初始种群中的每条染色体
FIT(np)=func2(f(:,np));%定义第np个体的适应度函数,以第np个个体的染色体基因序列数组为自变量
end
[SortFIT,Index]=sort(FIT);%按照升序对适应度函数值排序,
%返回的SortFIT是排序好的适应度函数值数组,
%返回Index是新数组中元素对应原索引值数组。
Sortf=f(:,Index); %sortf为排序好的种群矩阵
%%%%%%%%%%%%遗传算法循环%%%%%%%%%%%%%%%%%%%%
for gen=1:G
%%%%%%%采用君主方案进行选择和交叉操作%%%%%%%%%%%%%%
Emper=Sortf(:,1); %选出君主染色体数组(由于最终求的是最小值,故适应度最低的是最优个体)
NoPoint=round(D*Pc); %每次交叉点的个数,round为四舍五入取整
PoPoint=randi([1,D],NoPoint,NP/2);%随机生成发生交叉的偶数染色体上发生交叉基因的位置矩阵
nf=Sortf;
for i=1:NP/2 %进行交叉
nf(:,2*i-1)=Emper;%在排序好的种群中把所有奇数位(不参与交叉的那些)替换为君主染色体
nf(:,2*i)=Sortf(:,2*i);
for k=1:NoPoint
nf(PoPoint(k,i),2*i-1)=nf(PoPoint(k,i),2*i);%奇数位和偶数位染色体在前面求得的交叉位置发生交叉
nf(PoPoint(k,i),2*i)=Emper(PoPoint(k,i));
end
end
%%%%%%%%变异操作%%%%%%%%%%%%%
for m=1:NP %对种群中每一个个体
for n=1:D %对第m个个体的第n个基因位
r=rand(1,1);%生成一个【0,1】随机数
if r<Pm
nf(n,m)=rand(1,1)*(Xs-Xx)+Xx;%若满足变异条件,则随机生成题述范围内的实值替换相应位置完成变异
end
end
end
%%%%%%%子种群按适应度升序排列%%%%%%%%%
for np=1:NP %模仿对初始种群操作即可
NFIT(np)=func2(nf(:,np));
end
[NSortFIT,Index]=sort(NFIT);
NSortf=nf(:,Index);
%%%%%%产生新种群%%%%%%%%%%%%%%%%%%%%%%
f1=[Sortf,NSortf]; %先对父代和子代进行合并
FIT1=[SortFIT,NSortFIT];%对父代和子代的适应度值合并
[SortFIT1,Index]=sort(FIT1);%对新的适应度函数值数组进行升序排列
Sortf1=f1(:,Index); %按适应度排列个体
SortFIT=SortFIT1(1:NP); %排序后取前NP个个体构成下一次循环种群适应度值数组
Sortf=Sortf1(:,1:NP); %下一次循环种群矩阵
trace(gen)=SortFIT(1); %记录历代最优适应度值
end
Bestf=Sortf(:,1) %输出最优个体基因序列数组,即取最小值时的【xi】取值
disp(['最终得到最优个体适应度值,即函数最小值为:']);
trace(end) %命令行中输出函数最小值(想要把值输出来就不要加分号)
figure %画出适应度进化曲线
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')
%%%%%%%%适应度进化函数%%%%%%%%%%%%%
function result=func2(x)
summ=sum(x.^2);%以目标函数作为适应度函数
result=summ;
end
最终运行结果如下所示: