多峰值优化问题 (提供 DE 和 GA 两种解决思路)
多峰值优化问题,容易陷入局部最优,现提供两种方法解决该类问题。
1 实例
注:这种较简单的优化模型(除自变量本身外,不含其他等式或不等式约束),使用进化算法很好解决。
1.1 函数图像
1.2 提供图形绘制代码
% t=-3:0.1:15;
[x,y] =meshgrid(-3:0.1:12.1,4.1:0.01:5.8);%%表示区域网格控制,目地是为了让x,y形成格点矩阵%%
z=2.15+x.*sin(x.*4*pi)+y.*sin(y.*20*pi);
mesh(x,y,z);
%%设置三维曲面x轴,y轴,z轴,标题对应内容及三个坐标轴的取值范围%%
% axis([-3,12.1,4.1,5.8])
xlabel('X');
ylabel('Y');
zlabel('Z');
title('mesh三维曲面图');
axis([-3 12.1 4.1 5.8 -20 20]);
2 实现方法
2.1 DE(差分进化算法)
2.1.1 DE实现
实现代码同另一篇博客的差分进化算法部分
2.1.2 实验结果图
该算法收敛速度快,全局寻优能力也较强。
2.2 GA(遗传算法)
2.2.1 主函数
clear;clc;close all;
%%遗传参数设置
NUMPOP=200;%初始种群大小
irange_l=[-3,4.1]; %问题解区间
irange_r=[12.1,5.8];
LENGTH=12; %二进制编码长度
ITERATION = 100;%迭代次数
CROSSOVERRATE = 0.7;%杂交率
SELECTRATE = 0.5;%选择率
VARIATIONRATE = 0.01;%变异率
%初始化种群
pop=m_InitPop(NUMPOP,irange_l,irange_r);
pop_save=pop;
%开始迭代
for time=1:ITERATION
time
pop_save=pop;
%计算初始种群的适应度
fitness=m_Fitness(pop);
%选择
pop=m_Select(fitness,pop,SELECTRATE);
%编码
binpop=m_Coding(pop,LENGTH,irange_l);
%交叉
kidsPop = crossover(binpop,NUMPOP,CROSSOVERRATE);
%变异
kidsPop = Variation(kidsPop,VARIATIONRATE);
%解码
kidsPop=m_Incoding(kidsPop,irange_l,irange_r);
%更新种群
pop = [pop_save;pop; kidsPop];
%% 贪婪策略
[best_x,best_solution,pop] = save_best(pop);
best_X(time,:) = best_x;
best_Solution(time,1) = best_solution;
end
figure(1);
plot(best_Solution);
title(['min最优值 ',num2str(best_Solution(end))]);
xlabel(['best [x1,x2] = ',num2str(best_X(end,:))]);
ylabel("fitness");
disp(['最优个体:' 'x1 =' num2str(best_x(1)) ' ' 'x2 =' num2str(best_x(2))])
disp(['最优解:' num2str(best_solution)]);
2.2.2 种群初始化
function pop=m_InitPop(numpop,irange_l,irange_r)
%% 初始化种群
pop=zeros(numpop,2);
for i=1:numpop
pop(i,:)=irange_l+(irange_r-irange_l).*rand(1,2);
end
end
2.2.3 计算初始种群适应度
function fitness=m_Fitness(pop)
for i=1:size(pop,1)
fitness(i,1)=30-m_Fx(pop(i,:)); %%原函数值最大不超过30 ,由于是极小优化问题 ,适应度进行处理
end
end
2.3.4 选择(轮盘赌)
function parentPop=m_Select(matrixFitness,pop,SELECTRATE)
sumFitness=sum(matrixFitness(:));%计算所有种群的适应度
accP=cumsum(matrixFitness/sumFitness);%累积概率
%轮盘赌选择算法
for n=1:round(SELECTRATE*size(pop,1))
matrix=find(accP>rand); %找到比随机数大的累积概率
if isempty(matrix)
continue
end
parentPop(n,:)=pop(matrix(1),:);%将首个比随机数大的累积概率的位置的个体遗传下去
end
end
2.2.5 编码 (二进制)
编码长度的确定根据每个自变量取值范围区间长度,和考虑保留小数的个数 ,转二进制确定:
例如: -3 ~12.1 区间长度 15.1 ,保留2位小数 1510 转二进制 101 1110 0110 11位2进制数
保留更多的有小数有利于算法精度的提升!!!
function binPop=m_Coding(pop,pop_length,irange_l)
%% 二进制编码(生成染色体)
% 输入:pop--种群
% pop_length--编码长度
for i = 1:size(pop,1)
pop(i,:)=round((pop(i,:)-irange_l)*10^2);
end
for n=1:size(pop,1) %行循环
for k=1:size(pop,2) %列循环
dec2binpop{n,k}=dec2bin(pop(n,k));%dec2bin的输出为字符向量;
%dec2binpop是cell数组
lengthpop=length(dec2binpop{n,k});
for s=1:pop_length-lengthpop %补零
dec2binpop{n,k}=['0', dec2binpop{n,k}];
end
end
binPop{n,:}=dec2binpop{n,:}; %取dec2binpop的第k行
end
end
2.2.6 交叉
function kidsPop = crossover(parentsPop,NUMPOP,CROSSOVERRATE)
kidsPop = {[]};
n = 1;
while size(kidsPop,1)<NUMPOP-size(parentsPop,1) %让子代和父代的种群和为 预设种群数量
%选择出交叉的父代和母代
father = parentsPop{ceil((size(parentsPop,1)-1)*rand)+1,1};
mother = parentsPop{ceil((size(parentsPop,1)-1)*rand)+1,1};
%随机产生交叉位置
crossLocation = ceil((length(father)-1)*rand)+1;
%如果随即数比交叉率低,就杂交
if rand<CROSSOVERRATE
father(1,crossLocation:end) = mother(1,crossLocation:end);
kidsPop{n,:} = father;
n = n+1;
end
end
2.2.7 变异
function kidsPop = Variation(kidsPop,VARIATIONRATE)
for n=1:size(kidsPop,2)
if rand<VARIATIONRATE
temp = kidsPop{n};
%找到变异位置
location = ceil(length(temp)*rand);
temp = [temp(1:location-1) num2str(~temp(location))...
temp(location+1:end)];
kidsPop{n} = temp;
end
end
2.2.8 解码
function pop=m_Incoding(binPop,irange_l,irange_r)
%% 解码
% popNum=1;
popNum = 2;%染色体包含的参数数量
for n=1:size(binPop,1)
Matrix = binPop{n,1};
for num=1:popNum
pop(n,num) = bin2dec(Matrix)+irange_l(num); %%之前减去左界,现加上左界
if pop(n,num)<irange_l(num)||pop(n,num)>irange_r(num) %%边界判断,若超出边界,即做重新赋值处理
pop(n,num) = rand*(irange_r(num)-irange_l(num))+irange_l(num);
end
end
end
end
2.2.9 贪婪选择
同时还原出目标函数值
function [best_x,best_solution,pop] = save_best(pop)
fitness = m_Fitness(pop);
[~,index] =sort(fitness,'descend');
m = size(pop,1);
for i = 1 : m/2
temp(i,1:2) = pop(index(i),:);
temp(i,3) = fitness(index(i));
end
%%经过处理 适应度越大,函数值越小
pop = temp(:,1:2);
best_x = pop(1,:);
best_solution = m_Fx(best_x);
end
2.2.10实验结果图
需要注意的是:该算法可能实现上存在一定问题(笔者没做深入研究),导致算法可能出现早熟,或者不能达到全局最优问题~~
有相关问题探讨请私信或留言,谢谢!
创作不易:如果有帮助请点赞!