赞
踩
最近刚学完遗传算法,觉得遗传算法比较重要,因此我就手动编写对其进行实现,在此记录一下。编写遗传算法是为了解决下面的问题:
min
f
(
x
1
,
x
2
)
=
20
+
x
1
2
+
x
2
2
−
10
(
cos
2
π
x
1
+
cos
2
π
x
2
)
s
.
t
.
−
5
<
x
1
,
x
2
<
5
\min f\left( x_1,x_2 \right) =20+{x_1}^2+{x_2}^2-10\left( \cos 2\pi x_1+\cos 2\pi x_2 \right) \\ s.t. -5<x_1,x_2<5
minf(x1,x2)=20+x12+x22−10(cos2πx1+cos2πx2)s.t.−5<x1,x2<5
遗传算法是模拟生物种群进化的原理而设计出来的算法,是一种随机全局搜索优化方法,它模拟了自然选择和遗传中发生的复制、交叉(crossover)和变异(mutation)等现象,从任一初始种群(Population)出发,通过随机选择、交叉和变异操作,产生一群更适合环境的个体,使群体进化到搜索空间中越来越好的区域,这样一代一代不断繁衍进化,最后收敛到一群最适应环境的个体(Individual),从而求得问题的优质解。值得说明的是,遗传算法相对较好的解决了由神经网络中梯度法带来的陷入局部极小值的问题,是一个很好的算法。
% 时间:2023.5.31 % 开发者:落霞孤鹜,秋水长天 % 代码涉及算法:基本遗传算法(SGA) % 代码功能:使用SGA解决以下问题: % min f(x1,x2)=20+x1^2+x2^2-10(cos(2*pi*x1)+cos(2*pi*x2)) s.t. -5<x1,x2<5 %% 主函数 clc; clear all; close all; global population1 popSize populationAll crossProbality mutationProbality generationTimes generationNow global maxFitness fitnessValue1 stringLength trueValue averageFitness trueValueForMaxFitness popSize = 100; %种群规模 stringLength = 20; %编码长度,小数点后五位精度,最少需要20位 population1 = ones(popSize,stringLength,2); %种群1 trueValue = zeros(popSize,2); populationAll = ones(popSize,stringLength,2,popSize); %迭代过程种群汇总 fitnessValue1 = zeros(popSize,1); %每代种群适应度 crossProbality = 0.6; %交叉概率 mutationProbality = 0.03; %变异概率 generationTimes = 500; %迭代代数 generationNow = 1; maxFitness = zeros(generationTimes,1); averageFitness = zeros(generationTimes,1); trueValueForMaxFitness = zeros(generationTimes,2); randn('seed',sum(100*clock)) initPopulation; fitnessCalculate; select; while generationNow<generationTimes+1 generation; %遗传操作 generationNow = generationNow+1; end showResult; %% 初始化种群 function initPopulation() global population1 popSize populationAll stringLength for i1 = 1:popSize for i2 = 1:stringLength population1(i1,i2,1) = int8(rand()>0.5); %随机生成数据 population1(i1,i2,2) = int8(rand()>0.5); end end populationAll(:,:,:,1) = population1; end %% 遗传函数 function generation() fitnessCalculate; %计算适应度值及排序 select; %选择操作 crossover; %交叉 mutation; %变异 end %% 适应度计算 function fitnessCalculate() global popSize fitnessValue1 population1 stringLength trueValue averageFitness global generationNow maxFitness trueValueForMaxFitness format long x = zeros(popSize,2); dataNeedDecoding = zeros(2,stringLength); averageFitness(generationNow) = 0; maxFitness(generationNow) = 0; for i = 1:popSize dataNeedDecoding(1,:) = population1(i,:,1)'; dataNeedDecoding(2,:) = population1(i,:,2)'; x(i,:) = decoding(dataNeedDecoding)'; if x(i,1)>5||x(i,1)<-5||x(i,2)>5||x(i,2)<-5 fitnessValue1(i) =0; trueValue(i,:) = x(i,:); else trueValue(i,:) = x(i,:); fitnessValue1(i) = 90-(20 + x(i,1)^2 + x(i,2)^2 - 10*(cos(2*3.14*x(i,1))+cos(2*3.14*x(i,2)))); end averageFitness(generationNow) = averageFitness(generationNow) + fitnessValue1(i); if i == 1 maxFitness(generationNow) = fitnessValue1(i); trueValueForMaxFitness(generationNow,:) = trueValue(i,:); else if maxFitness(generationNow)<fitnessValue1(i) maxFitness(generationNow) = fitnessValue1(i); trueValueForMaxFitness(generationNow,:) = trueValue(i,:); end end end averageFitness(generationNow) = averageFitness(generationNow) / 1.0 / popSize; end %% 选择算子 function select() format long global popSize fitnessValue1 population1 stringLength wheelForAll = zeros(popSize,1); fitnessValueAll = 0; population_temp = ones(popSize,stringLength,2); for i1 = 1:popSize fitnessValueAll = fitnessValueAll + fitnessValue1(i1); end for i2 = 1:popSize temp = fitnessValue1(i2)*1.0/fitnessValueAll; if i2 == 1 wheelForAll(i2) = temp; else wheelForAll(i2) = wheelForAll(i2-1) + temp; end end for i3 = 1:popSize %轮盘赌法进行选择 a = rand(); for i4 = 1:popSize if a<wheelForAll(i4) population_temp(i3,:,:) = population1(i4,:,:); break; end end end population1 = population_temp; end %% 交叉算子 function crossover() global popSize population1 stringLength crossProbality for i1 = 1:2:popSize a = rand(); if a<crossProbality crossPosition = randi([1 stringLength]); tempBlock = population1(i1,1:crossPosition,:); population1(i1,1:crossPosition,:) = population1(i1+1,1:crossPosition,:); % 单点交叉 population1(i1+1,1:crossPosition,:) = tempBlock; end end end %% 变异算子 function mutation() global popSize mutationProbality population1 stringLength for i1 = 1:popSize a = rand(); if a<mutationProbality mutationPosition = randi([1 stringLength]); population1(i1,mutationPosition,:) = int8((population1(i1,mutationPosition,:)+1)/2); end end end %% 解码 function [decimalismData1,decimalismData2] = decoding(binaryData) binaryData1 = num2str(binaryData(1,:)); binaryData2 = num2str(binaryData(2,:)); decimalismData1 = bin2dec(binaryData1); decimalismData2 = bin2dec(binaryData2); decimalismData1 = decimalismData1 /100000.0 - 5; decimalismData2 = decimalismData2 /100000.0 - 5; end %% 显示数据 function showResult() global averageFitness maxFitness trueValueForMaxFitness generationTimes figure(1) i = 1:generationTimes; plot(i,averageFitness,'b') hold on plot(i,maxFitness,'r') hold off legend('平均适应度变化','最大适应度变化') title('遗传算法迭代相关参数变化') figure(2) v = -5:0.01:5; a = length(v); x1 = zeros(a,a); x2 = zeros(a,a); y = zeros(a,a); for i1 = 1:a for i2 = 1:a x1(i1,i2) = v(i1); x2(i1,i2) = v(i2); y(i1,i2) = 20 + x1(i1,i2)^2 + x2(i1,i2).^2 - 10*(cos(2*3.14*x1(i1,i2))+cos(2*3.14*x2(i1,i2))); end end surf(x1,x2,y,'EdgeColor', 'none'); hold on a1 = trueValueForMaxFitness(generationTimes,1) a2 = trueValueForMaxFitness(generationTimes,2) y1 = 20 + a1^2 + a2^2 - 10*(cos(2*3.14*a1)+cos(2*3.14*a2)) plot3(a1,a2,y1,'r*'); hold off end
这里研究的函数图像为:
通过遗传算法,其平均适应度和最大适应度变化为:
最终优化结果在函数图像上的位置:
不得不说明的是,遗传算法有一定的概率性,因此,得到的不一定是最优解,只能说是相对较优的解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。