差分进化算法原理及matlab代码实现
差分进化算法介绍:
在自然界中,遗传,变异,选择的作用,使得生物体优胜略汰,不断由低级向高级进化,人们发现适者生存这一规律可以模式化,从而构成一些列优化算法。差分进化算法就是从这种模式中产生的一种智能优化算法。差分进化算法是基于群体只能理论的优化算法,与进化算法相比,保留了基于种群的全局搜索策略,采用实数编码,基于差分的简单变异操作操作和“一对一”的竞争生存策略。降低了操作的复杂性,差分进化算法特有的记忆能力使其可以动态的跟踪当前的搜索情况,以调整其搜索策略,具有较强的收敛能力和稳健性,且不需要借助问题的特侦信息。
算法流程:
1. 初始化:(与遗传算法类似)
种群中的个体可以表示为:(种群大小为NP)
其中: i=1,2,....NP
初始种群一般在给定的约束边界内随机生成
2. 变异
对于种群中每个个体,差分进化算法的变异向量按照下面的方式产生:
其中:在种群中随机选择且
,参数
,用于控制偏差的放大作用。
除此之外,偏差向量还可以由其他的方式产生:表示方法:DE/x/y/z, x当前被变异的向量是随机的还是最优的,y差向量的个数,z交叉程序的操作方法(bin)
DE/best/1/bin:
DE/rand-to-best/1/bin:
DE/best/2/bin:
DE/rand/2/bin:
3. 交叉
这里的交叉和遗传算法的交叉操作有所区别,这里的交叉操作是针对整个种群的某一维度,而遗传算法中的交叉是针对种群中的每一个个体。
4.选择:
差分进化算法按照贪婪准则,从实验种群u中选择个体作为下一代种群x中的个体,具体的选择方式是:
其中:fit(x)为x的适应度。
5. 边界条件处理:
对于这一类的算法,通常会对种群中的个体执行一些列的操作(如交叉,变异),这会导种群中个体的范围(即决策变量的范围)超出给定的范围,所以需要对上述操作后所得到种群进行边界条件检查和处理,对于边界之外的个体一般有两种处理方法:
1. 边界吸收:
假设x的范围是x_max, x_min, x'是经过变异或者交叉操作后所得的新的个体:则新个体的边界检查和处理规则为:
2. 重新随机生成新的个体:
基本差分进化算法的流程:
算法中的参数:
1. 种群大小NP
2. 变异算子F ,
一般取[0,2],决定偏差向量的放大比例。F过小,造成算法早熟,F过大,导致算法的收敛性变差
3.交叉算子CR
4. 进化代数G
5.终止条件
matlab代码实现:
测试函数为:
取n=10,决策变量的范围为[-20,20]
close all; clear all; clc; NP=50; D=10; % 染色体长度 G=200; F0=0.4; CR=0.1; a=-20; % 寻优区间 b=20; yz=10^-6; x=zeros(NP,D); % 初始种群 v=zeros(NP,D); % 变异种群 u=zeros(NP,D); % 选择种群 % 种群怫初值 x=rand(NP,D)*(b-a)+a; % 计算目标参数 for i=1:1:NP ob(i)=sum(x(i,:).^2); end trace(1)=min(ob); % 差分进化循环 for gen=1:G % 变异操作 for m=1:NP r1=randi([1,NP],1,1); while(r1==m) r1=randi([1,NP],1,1); end r2=randi([1,NP],1,1); while(r2==r1)||(r2==m) r2=randi([1,NP],1,1); end r3=randi([1,NP],1,1); while(r3==m)||(r3==r2)||(r3==r1) r3=randi([1,NP],1,1); end % 产生不同的r1,r2,r3 v(m,:)=x(r1,:)+F0*(x(r2,:)-x(r3,:)); end % 交叉操作 r=randi([1,D],1,1); % 这个变异是针对整个种群的变异,不正对单个个体 for n=1:D cr=rand; if (cr<=CR)||(n==r) u(:,n)=v(:,n); else u(:,n)=x(:,n); end end % 边界条件处理 for m=1:NP for n=1:D if u(m,n)<a u(m,n)=a; end if u(m,n)>b u(m,n)=b; end end end % 自然选择 % 计算新的适应度 for m=1:NP ob_1(m)=sum(u(m,:).^2); end for m=1:NP if ob_1(m)<ob(m) x(m,:)=u(m,:); else x(m,:)=x(m,:); end end % 现在x为经过选择后的种群 for m=1:NP ob(m)=sum(x(m,:).^2); end trace(gen+1)=min(ob); tt=min(ob); end x(1,:); figure(1); title(['差分进化算法(DE)', '最小值: ', num2str(tt)]); xlabel('迭代次数'); ylabel('目标函数值'); plot(trace);
寻优结果:
差分进化算法的该改进:
自适应差分进化算法:
差分进化算法的变异系数F的确定:在实际的应用中,若果F取为常数,F过大,则会导致算法的收敛速度变慢,求得的全局最优解精度降低,F过小,会导致种群的多样性降低,出现早熟,所以可以将参数F设置为一个随着迭代次数变化的值,在迭代初期的时候,F较大,可以保持种群的多样性,随着迭代次数的增加,F减小,能够保存优良的种群信息,避免破坏最优解。
自适应算子如下所示:
其中Gm表示最大迭代次数,G表示当前迭代次数
变异系数F表示为:
改进的差分进化算法:
clear all; close all; clc; NP=40; % 种群大小 G=100; % 迭代次数 D=2; % 决策变量个数 F0=0.3; % 初始的变异系数 CR=0.5*(1+rand()); X_min=-100; X_max=100; % 偏差向量的生成方式 DE_vector = 4; % DE_vector=1,2,3,4,0 % DE_vector=0 表示DE/best/1/bin % DE_vector=1 表示DE/best/1/bin % DE_vector=2 表示DE/rand-to-best/1/bin % DE_vector=3 表示DE/best/2/bin % DE_vector=4 表示DE/rand/2/bin mode = 'Schaffer'; % 测试函数 % mode = 'self_define'; if strcmp(mode, 'Schaffer') figure(1) x = -4:0.1:4; y = -4:0.1:4; [X,Y] = meshgrid(x,y); % Z = 3*cos(X.*Y)+X+Y.^2; Z = 0.5-((sin(sqrt(X.^2+Y.^2)).^2)-0.5)./(1+0.001.*(X.^2+Y.^2)).^2; surf(X,Y,Z); title('Schaffer Function'); xlabel('X-轴'); ylabel('Y-轴'); zlabel('Z-轴'); figure(2); contour(X, Y, Z, 8); title('Schaffer函数等高线'); xlabel('X-轴'); ylabel('Y-轴'); end if strcmp(mode, 'self_define') figure(1); x = -4:0.1:4; y = -4:0.1:4; [X,Y] = meshgrid(x,y); % Z = 100.*(Y-X.^2).^2+(1-X).^2; Z = (cos(X.^2+Y.^2)-0.1)./(1+0.3*(X.^2+Y.^2).^2)+3; surf(X,Y,Z); %title('Rosen Brock valley Function'); title('Self define Function'); xlabel('X-轴'); ylabel('Y-轴'); zlabel('Z-轴'); end % 种群初始化 x=zeros(NP,D); v=zeros(NP,D); u=zeros(NP,D); x=X_min + (X_max-X_min)*rand(NP,D); for gen=1:1:G for i=1:1:NP ob(i) = func(x(i,:), mode); end [fitness_max, index] = max(ob); lamb(gen) = exp(1-(G/(G+1-gen))); F = F0*2^lamb(gen); % 变异 if(DE_vector==0) for m=1:NP r1=randi([1,NP],1,1); while (r1==m) r1=randi([1,NP],1,1); end r2=randi([1,NP],1,1); while(r2==r1)||(r2==m) r2=randi([1,NP],1,1); end r3=randi([1,NP],1,1); while (r3==m)||(r3==r2)||(r3==r1) r3=randi([1,NP],1,1); end v(m,:)=x(r1,:)+F*(x(r2,:)-x(r3,:)); % DE/best/1bin end elseif(DE_vector==1) for m=1:NP r1=randi([1,NP],1,1); while (r1==m) r1=randi([1,NP],1,1); end r2=randi([1,NP],1,1); while(r2==r1)||(r2==m) r2=randi([1,NP],1,1); end v(m,:)=x(index,:)+x(r1,:)+F*(x(r1,:)-x(r2,:)); end elseif(DE_vector==2) lambda = 0.35; for m=1:NP r1=randi([1,NP],1,1); while (r1==m) r1=randi([1,NP],1,1); end r2=randi([1,NP],1,1); while(r2==r1)||(r2==m) r2=randi([1,NP],1,1); end v(m,:)=x(m,:)+lambda*(x(index,:)-x(m,:))+F*(x(r1,:)-x(r2,:)); end elseif(DE_vector==3) for m=1:NP r1=randi([1,NP],1,1); while (r1==m) r1=randi([1,NP],1,1); end r2=randi([1,NP],1,1); while(r2==r1)||(r2==m) r2=randi([1,NP],1,1); end r3=randi([1,NP],1,1); while (r3==m)||(r3==r2)||(r3==r1) r3=randi([1,NP],1,1); end r4=randi([1,NP],1,1); while (r4==m)||(r4==r3)||(r4==r2)||(r4==r1) r4=randi([1,NP],1,1); end v(m,:)=x(index,:)+F*(x(r1,:)-x(r2,:)+x(r3,:)-x(r4,:)); end else for m=1:NP r1=randi([1,NP],1,1); while (r1==m) r1=randi([1,NP],1,1); end r2=randi([1,NP],1,1); while(r2==r1)||(r2==m) r2=randi([1,NP],1,1); end r3=randi([1,NP],1,1); while (r3==m)||(r3==r2)||(r3==r1) r3=randi([1,NP],1,1); end r4=randi([1,NP],1,1); while (r4==m)||(r4==r3)||(r4==r2)||(r4==r1) r4=randi([1,NP],1,1); end r5=randi([1,NP],1,1); while (r5==m)||(r5==4)||(r5==r3)||(r5==r2)||(r5==r1) r5=randi([1,NP],1,1); end v(m,:)=x(r5,:)+F*(x(r1,:)-x(r2,:)+x(r3,:)-x(r4,:)); end end % 交叉操作 r=randi([1,D],1,1); for i=1:D cr=rand; if (cr<=CR)||(i==r) u(:,i)=v(:,i); else u(:,i)=x(:,i); end end % 边界条件处理 for m=1:NP for n=1:D if u(m,n)<X_min u(m,n)=X_min; end if u(m,n)>X_max u(m,n)=X_max; end end end % 自然选择 for i=1:NP ob_1(i)=func(u(i,:), mode); end for i=1:NP if ob_1(i)>ob(i) x(i,:)=u(i,:); else x(i,:)=x(i,:); end end trace(gen+1)=fitness_max; end figure(3); % plot(trace); title('差分进化算法'); xlabel('迭代次数'); ylabel('目标函数值'); plot(trace); function f=func(buf, md) if strcmp(md, 'Schaffer') f=0.5-((sin(sqrt(buf(1).^2+buf(2).^2)).^2)-0.5)./(1+0.001.*(buf(1).^2+buf(2).^2)).^2; end if strcmp(md,'self_define') % f = 100*(buf(2)-buf(1).^2).^2+(1-buf(1)).^2; f = (cos(buf(1).^2+buf(2).^2)-0.1)./(1+0.3*(buf(1).^2+buf(2).^2).^2)+3; end end
测试函数:
适应度进化曲线:
源代码中只是添加了典型的测试函数,参数只是粗略设置一下。对于其他的测试函数。可以在原代码中添加,并且修改源代码中的一些参数来得到算法最好的性能。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)