一、原理:
原理可转至:遗传算法原理
二、待解决问题:
搜索下列函数的最小值:
f
(
x
1
,
x
2
)
=
2
cos
(
x
1
x
2
)
+
4
x
1
+
x
2
2
x
1
,
x
2
∈
[
−
5
,
5
]
f(x_1,x_2) = 2\cos(x_1x_2)+4x_1+x_2^2\\x_1,x_2\in[-5,5]
f(x1,x2)=2cos(x1x2)+4x1+x22x1,x2∈[−5,5]
三、代码实现
clc
clear
close all
%% 采用浮点数编码形式搜索
N = 100; % 群体数量
ChromNum = 2; % 染色体数量
IterMax = 20; % 迭代次数
Pc = 0.7; % 交叉概率
Pm = 0.1; % 变异概率
UpLimit = [5,5]; % 染色体取值上限
DownLimit = [-5,-5]; % 染色体取值下限
WaitbarInter = IterMax / 100; % 一个和进度条有关的参数
FitnessBestProgress = zeros(1,IterMax); % 初始化群体最优适应度变化情况存储容器
AveFitnessProgress = zeros(1,IterMax); % 初始化群体平均适应度变化情况存储容器
Individual = InitIndividual(N,ChromNum,DownLimit,UpLimit); % 初始化群体染色体
fitness = CalcFitness(Individual); % 初始化适应度
[IndividualBest,FitnessBest] = FindBest(Individual,fitness); % 初始化最优个体
FitnessBestProgress(1,1) = FitnessBest; % 存储当前群体最优适应度
AveFitnessProgress(1,1) = CalcAveFitness(fitness); % 存储当前群体平均适应度
tic
h = waitbar(0, ['已完成:0% 运算中...用时:', num2str(toc)]); % 初始化进度条
for iter = 2:IterMax
Individual = MutIndividual(Individual,iter,IterMax,Pm,DownLimit,UpLimit); % 变异
Individual = CroIndividual(Individual,Pc); % 交叉
fitness = CalcFitness(Individual); % 计算当前群体适应度
[IndividualBesttemp,FitnessBesttemp] = FindBest(Individual,fitness); % 寻找当前群体最优个体
if FitnessBesttemp < FitnessBest % 最有个体存储迭代
FitnessBest = FitnessBesttemp;
IndividualBest = IndividualBesttemp;
end
[Individual,fitness] = NaturalSlection(Individual,fitness,IndividualBest,FitnessBest); % 自然选择
FitnessBestProgress(1,iter) = FitnessBest; % 存储当前群体最优适应度
AveFitnessProgress(1,iter) = CalcAveFitness(fitness); % 存储当前群体平均适应度
if mod(iter, WaitbarInter) == 0 % 处理并显示进度条
waitbar(iter / IterMax, h, ['已完成:' num2str(iter / IterMax * 100) ...
'% 运算中...用时:', num2str(toc),'/',num2str(toc/(iter / IterMax))])
end
end
close(h)
disp(["搜索完成,开始打印结果······"])
[ErgodicBestIndividual,ErgodicBestFitness] = PlotResult(ChromNum,IterMax,AveFitnessProgress,FitnessBestProgress); % 绘制GA搜索结果和遍历结果
PrintResult(IndividualBest,FitnessBest,ErgodicBestIndividual,ErgodicBestFitness); % 打印GA搜索结果和遍历结果
disp('打印完成!!!')
% 适应度计算
function fitness = CalcFitness(Individual)
fitness = 2*cos(Individual(:,1).*Individual(:,2))+4*Individual(:,1)+Individual(:,2).^2;
end
% 初始化群体
function Individual = InitIndividual(N,ChromNum,DownLimit,UpLimit)
Individual = zeros(N,ChromNum);
for i = 1:ChromNum
Individual(:,i) = rand(N,1)*(UpLimit(i)-DownLimit(i))+DownLimit(i);
end
end
% 寻找当前群体最优个体
function [IndividualBest,FitnessBest] = FindBest(Individual,fitness)
[FitnessBest,minCor] = min(fitness);
IndividualBest = Individual(minCor,:);
end
% 变异操作
function New_Individual = MutIndividual(Individual,iter,IterMax,Pm,DownLimit,UpLimit)
[N,ChromNum] = size(Individual);
% 遍历群体中的每一个个体
for i = 1:N
for j = 1:ChromNum
if rand <= Pm % 依照变异概率变异(可以实现自适应的变异概率,使该概率随着迭代次数越大变得越小,查文献找公式)
Mut_num = rand * (1-iter/IterMax)^2; % 概率性的变异数值
if rand<=0.5 % 按照50%概率决定变异方向
Individual(i, j) = Individual(i, j) * (1 - Mut_num);
else
Individual(i, j) = Individual(i, j) * (1 + Mut_num);
end
end
end
end
New_Individual = BoundaryLimit(Individual,DownLimit,UpLimit);
end
% 交叉操作
function New_Individual = CroIndividual(Individual,Pc)
[N,ChromNum] = size(Individual);
% 遍历群体中的每一个个体
for i = 1:N
if rand < Pc % 依照交叉概率交叉(可以实现自适应的交叉概率,使该概率随着迭代次数越大变得越小,查文献找公式)
Cro_Individual = floor((N-1)*rand+1); % 被交叉的个体
Cro_Node = floor((ChromNum-1)*rand+1); % 被交叉的染色体节点
% 交叉操作
temp = Individual(Cro_Individual,Cro_Node);
Individual(Cro_Individual,Cro_Node) = Individual(i,Cro_Node);
Individual(i,Cro_Node) = temp;
end
end
New_Individual = Individual;
end
% 自然选择
function [New_Individual,New_Fitness] = NaturalSlection(Individual,fitness,IndividualBest,FitnessBest)
[N,~] = size(Individual);
SumFitness = sum(fitness);
FitnessRate = fitness / SumFitness;
for i = 1:N
% 赌轮盘形式选择
if rand >= FitnessRate(i)
% 被选择的个体用概率当前最优个体替换
fitness(i) = FitnessBest;
Individual(i,:) = IndividualBest;
end
end
New_Individual = Individual;
New_Fitness = fitness;
end
% 计算群体平均适应度
function AveFitness = CalcAveFitness(fitness)
[N,~] = size(fitness);
AveFitness = sum(fitness) / N;
end
% 边界条件
function New_Individual = BoundaryLimit(Individual,DownLimit,UpLimit)
[N,ChromNum] = size(Individual);
for i = 1:N
for j = 1:ChromNum
if Individual(i,j) > UpLimit(j)
Individual(i,j) = UpLimit(j);
end
if Individual(i,j) < DownLimit(j)
Individual(i,j) = DownLimit(j);
end
end
end
New_Individual = Individual;
end
% 绘制GA搜索结果和遍历结果
function [ErgodicBestIndividual,ErgodicBestFitness] = PlotResult(ChromNum,IterMax,AveFitnessProgress,FitnessBestProgress)
ErgodicBestIndividual = zeros(1,ChromNum);
figure(1)
plot(1:IterMax,AveFitnessProgress,'r',1:IterMax,FitnessBestProgress,'b');
grid on
legend('平均适应度','最优适应度')
x = -5:0.01:5;
y = -5:0.01:5;
z = 2*cos(x.*y)+4*x+y.^2;
figure(2)
scatter3(x,y,z,'ko');
[X,Y] = meshgrid(x, y);
Z = 2*cos(X.*Y)+4*X+Y.^2;
mesh(X,Y,Z);
[a,b]=find(Z==min(min(Z)));
ErgodicBestFitness = Z(a(end),b(end));
ErgodicBestIndividual(1,1) = X(a(end),b(end));
ErgodicBestIndividual(1,2) = Y(a(end),b(end));
end
% 打印GA搜索结果和遍历结果
function PrintResult(IndividualBest,FitnessBest,ErgodicBestIndividual,ErgodicBestFitness)
disp(['GA搜索结果:']);
disp([' 自变量:x1 = ',num2str(IndividualBest(1)),' , x2 = ',num2str(IndividualBest(2))]);
disp([' 最小值:f = ',num2str(FitnessBest)]);
disp(['Ergodic搜索结果:']);
disp([' 自变量:x1 = ',num2str(ErgodicBestIndividual(1)),' , x2 = ',num2str(ErgodicBestIndividual(2))]);
disp([' 最小值:f = ',num2str(ErgodicBestFitness)]);
end