今天来写1.1没写完的step3及后续~~~
Step3:这里执行的是交叉操作
交叉操作很简单,依据设定的交叉概率,判断是否进行交叉
遗传步骤就是将两条染色体上同一位置处的基因进行交换,如下图所示:
1 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
A
1 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
B
1 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
A*
1 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
B*
这里我们将A、B两条染色体上的10个基因全部进行交叉得到A*、B*两条新染色体
显然就是0-1对调,这里也体现了二进制编码基因的简便优越性
咱们直接上代码看看怎么弄!
%%%%%%%%基于概率的交叉操作%%%%%%%%%%%%%%for i=1:2:Npp=rand; %p为0-1之间的一个随机数if p<Pc %如果随机概率小于于设定的交叉概率,进行交叉q=randi([0,1],1,L); %令q为由0/1随机生成的1*20的矩阵for j=1:L if q(j)==1%下面这是很简单的复制转换语句temp=newf(i+1,j);newf(i+1,j)=newf(i,j);newf(i,j)=temp;endend endend
这里值得一提的是“ q=randi([0,1],1,L); %令q为由0/1随机生成的1*20的矩阵”这条语句的存在,这里是新随机生成了一个染色体为1*20的矩阵(上篇博客说了,L=20,是二进制编码长度)
这个新随机的单独的染色体是起到了一个参考作用,原本的50(Np=50)条染色体被分成了两两一组,交叉在组内进行,那么哪些位置上进行交叉操作,就是这个新随机生成的染色体要起的作用
其实完全可以用生成一个1-20的随机数,在20个位置上进行随机选择,就是这个意思
这里交叉操作就结束了
Step4:这里进行变异操作
这个变异咱们简单理解,就是染色体某个位置上的基因突变成了另一种等位基因
如图所示:A染色体上2号位置基因突变就是由0换成了等位的1,其余保持不变
1 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
A
1 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
A*
可见变异的概率非常小,通常取0.001-0.1
这里我们因为有强大的语言,只需要随机确定某一个染色体和某一个基因位置对其数值使用not非逻辑,那么就可以实现0-1对调,这也是二进制编码的好处,因为只有0-1两个量。
这里变异是小操作,所以执行的次数还是少的,有相当的限制
代码如下:
%%%%%%%%%%%%基于概率的变异操作%%%%%%%%%i =1;while i <= round(Np*Pm) %四舍五入NP*Pm的值即i<=5h = randi(Np); %随机生成一个1-50的整数,即随机选择一个要变异的染色体for j = 1:round(L*Pm) g = randi(L); %随机生成一个1-20的整数,即随机选择一个要变异的基因位置数newf(h,g) = ~newf(h,g); %help ~not - 计算逻辑 not 此 MATLAB 函数 返回与 A 大小相同的逻辑数组。如果 A 中元素为零值,则数组中对应元素为逻 辑值 1 (true) 值;如果 A 中元素为非零值,则数组中对应元素为逻辑值 0 (false)。endi = i+1;endf = newf;f(1,:) =fbest; %将第i代最优的染色体保存在新种群中value(generation) = Fitvaluemax; %历代最优适应度
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end
这里变异操作就结束了
Step5:最后进行绘图,展示结果
这里就会很明显的感受到目标函数和适应度函数的映射关系,其实就是拿过来用的,具体绘图用的不是原来的描点法,而是用遗传进化代替。
%%%%%%%%%%%%%%%%%绘图%%%%%%%%%%%
xbest;
figure
plot(value)
xlabel('迭代次数');
ylabel('目标函数值');
title('适应度进化曲线');
%%%%%%%%%%%%适应度函数的调用%%%%%%%%%%%%%%
function result = func(x)
Fitvalue = x+10*sin(5*x)+7*cos(4*x);
result = Fitvalue;
end
结果图对比,一个是遗传进化图,一个是计算机描点法通用作图
最后生成的具体极大值大约都是24.86,可能第二个图看起来像是贴近25了,其实不是,matlab用鼠标放上去会显示具体数值的确实是24.8左右
这里就可以看出遗传算法还是有非常强的求解能力的
下面是完整代码和详细注释,Ctrl+C\V可以直接运行出结果:(试了很多遍,嘻嘻~~)
%%%%%%%%%初始化参数%%%%%%%%
Np=50;%种群数量
L=20;%二进制编码长度
Pc=0.8;%交叉概率
Pm=0.1;%变异概率
G=100;%最大进化代数
Xmax=10;%自变量取值上限
Xmin=0;%自变量取值下限
f=randi([0,1],Np,L); %随机生成初始化种群,Np*L的矩阵%%%%%%%%%%遗传循环%%%%%%%%%%%
for generation=1:G
%%%%%将二进制解码成十进制%%%%%for i=1:NpA=f(i,:); %A为f矩阵的第i行m=0;for j=1:Lm=A(j)*2^(j-1)+m;endX(i)=Xmin+(Xmax-Xmin)*m/(2^L-1); %第i个染色体的表现型数值Fitvalue(i)=func(X(i)); %由目标函数映射的初始适应度数值大小endFitvaluemax=max(Fitvalue); %找出第i代中初始适应度函数最大值Fitvaluemin=min(Fitvalue); %找出第i代中初始适应度函数最小值location=find(Fitvalue==Fitvaluemax); %找到染色体适应度函数最大值所在的位置是第几行并返回给locationfbest=f(location(1,1),:); %location是个行向量,表示在f矩阵中适应度最大值所在行的整个染色体,记为第i代最优个体xbest=X(location(1,1)); %这个第i代中最优个体的表现型数值大小Fitvalue=(Fitvalue-Fitvaluemin)/(Fitvaluemax-Fitvaluemin); %将初始适应度函数值进行归一化操作
%%%%%%%%%%%%%基于轮盘赌的选择操作%%%%%%%%%%%%%%%%%%sum_Fitvalue=sum(Fitvalue);Fitvaluepercentage=Fitvalue./sum_Fitvalue;%计算出各个染色体被选择的概率Fitvaluepercentage=cumsum(Fitvaluepercentage);%cumsum和sum有所区别,是累加到所到之处,而不是直接全部累加sortuniform=sort(rand(Np,1));%生成50*1的[0,1]内的随机矩阵,就是50行个小于1,大于0的随机数fiti=1;newi=1;while newi<=Npif(sortuniform(newi))<Fitvaluepercentage(fiti)%随机概率和轮盘上的概率进行比较,若为真,则说明轮盘概率大newf(newi,:)=f(fiti,:); %被选择,则加入到新一代的种群矩阵中去 newi=newi+1;elsefiti=fiti+1;%没被选择,则保持不变endend
%%%%%%%%基于概率的交叉操作%%%%%%%%%%%%%%for i=1:2:Npp=rand; %p为0-1之间的一个随机数if p<Pc %如果随机概率小于于设定的交叉概率,进行交叉q=randi([0,1],1,L); %令q为由0/1随机生成的1*20的矩阵for j=1:L if q(j)==1%下面这是很简单的复制转换语句temp=newf(i+1,j);newf(i+1,j)=newf(i,j);newf(i,j)=temp;endend endend%%%%%%%%%%%%基于概率的变异操作%%%%%%%%%i =1;while i <= round(Np*Pm) %四舍五入NP*Pm的值即i<=5h = randi(Np); %随机生成一个1-50的整数,即随机选择一个要变异的染色体for j = 1:round(L*Pm) g = randi(L); %随机生成一个1-20的整数,即随机选择一个要变异的基因位置数newf(h,g) = ~newf(h,g); %help ~not - 计算逻辑 not 此 MATLAB 函数 返回与 A 大小相同的逻辑数组。如果 A 中元素为零值,则数组中对应元素为逻 辑值 1 (true) 值;如果 A 中元素为非零值,则数组中对应元素为逻辑值 0 (false)。endi = i+1;endf = newf;f(1,:) =fbest; %将第i代最优的染色体保存在新种群中value(generation) = Fitvaluemax; %历代最优适应度
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end%%%%%%%%%%%%%%%%%绘图%%%%%%%%%%%
x=0:0.01:10;
y=x+10*sin(5*x)+7*cos(4*x);
figure
plot(x,y)
xbest;
figure
plot(value)
xlabel('迭代次数');
ylabel('目标函数值');
title('适应度进化曲线');
%%%%%%%%%%%%适应度函数的调用%%%%%%%%%%%%%%
function result = func(x)
Fitvalue = x+10*sin(5*x)+7*cos(4*x);
result = Fitvalue;
end
制作不易,权当学习~~~~请批评指正