文末附有MATLAB代码
参数
1、目标函数,即需要求解的函数,适应度函数。格式fx=@(x)(xsin(10pi*x)+2.0 );
2、定义域上下限。用于确定区间长度,从而编码。上限xMax;下限xMin。
3、 种群规模 popSize。即种群的大小。
4、选中概率selPrb。根据选概确定每次留下多少比例的个体。
5、交叉概率croPrb。根据交概确定两个个体间是否交叉。
6、变异概率varPrb。根据变概确定个体是否需要变异。
7、循环代数generNum。根据代数确定循环次数。
8、精度accuracy。根据精度和区间长度编码。
编码
1、确定编码长度。例如目函区间长度为3,精度为6。则
3*10^6小于等于2的22次方,但大于等于2的21次方,那么编码长度为21.
2、确定映射函数。映射函数的作用是从0到2的22次方的数能够对应目函区间里的数。
产生初始种群
例如种群规模是50。
根据种群规模生成50个二进制随机数存储到种群pop中。
这些随机数是22位
根据代数开始循环
计算适应度
1、将pop中的二进制数转换成十进制数。
2、利用映射函数将这些十进制数转换成区间内的数。
3、将这些数带入目函,求出的结果是个体适应度,存储在popFitness。
4利用Max函数求出popFitness中的局部最优解(在这个例子中即最大值)以及对应得x。存储在view中。
轮盘赌算法选择
1、计算选择概率。例如:
个体1适应度=1;
个体2适应度=2;
个体3适应度=3;
个体4适应度=4;
则个体1的选择概率:1/(1+2+3+4)
个体1的选择概率:2/(1+2+3+4)
个体1的选择概率:3/(1+2+3+4)
个体1的选择概率:4/(1+2+3+4)
2、计算累计概率。个体1的累概=个体1的选概,
此后,个体n的累概=个体n的选概+个体n-1的累概。
3、根据selPrb生成popSize*selPrb(四舍五入)个0-1之间的随机数。
4、如第一个随机数为0.55,个体2的累概为0.400,个体3的累概为0.588。则选中个体3。依次类推。
5、更新种群与种群规模,淘汰未选中个体。
单点交叉
对每两个个体进行如下操作:
1、生成0-1之间随机数,如果这个数小于交叉概率,则个体n(从1开始)与个体n+1的交叉。
2、生成1-编码长度之间的随机数,当做交叉位置。
3、交叉操作。如 n:1111000
n+1:1100111
交叉位置为3,交叉后新个体
n_new:1100111
n+1_new:1111000
4、将产生的新个体加入种群,更新种群大小。
注:交叉完成后产生新个体,种群规模增加。
变异
对每个个体进行如下操作:
1、生成0-1之间随机数,如果这个数小于变异概率,则个体可以变异。
2、生成1-编码长度之间的随机数,当做变异位置。
3、对个体的变异位置进行反转。即原来是1变成0;
4、更新个体。
注:变异不产生新个体,只是对个体进行更新,变异完成后种群规模不变。
循环完成
输出结果
view变量每次循环都会存储一个局部最优解,则max(view)即全局最优解gBest。
在这里插入代码片
clear
fx=@(x)(x*sin(10*pi*x)+2.0 ); %适应度函数
%fx=@(x)(sin (x));
accuracy=6; %精确度
xMax=2; %定义域最大值
xMin=-1; %定义域最小值
popSize=50; %种群规模
selPrb=0.8; %选中概率
croPrb=0.25; %交叉概率
varPrb=0.01 %变异概率
generNum=89; %循环代数
view=[];
% 1、编码
intervalLength=xMax-xMin; %确定区间长度
codingLength=1;
while 2^codingLength<(intervalLength*(10^accuracy))
codingLength=codingLength+1;
end %确定编码长度
mappingx=@(xc)(-1.0+xc*(intervalLength/(2^codingLength-1)))
%十进制数映射到区间的函数
% 2、产生初始种群
pop=string(dec2bin(randi(2^codingLength,popSize,1)-1,22));
%生成随机种群 有问题
%pop=["1000101110110101000111","0000001110000000010000","1110000000111111000101"];
%用特定的种群验证
for g=1:generNum %代数循环
% 3、计算适应度
mapFin=mappingx(bin2dec(pop));
popFitness=[];
for i=1:popSize
popFitness(i)=fx(mapFin(i));
end %种群适应度存储在一维数组popFItness中
[lbest,lx]=max(popFitness);
view(end+1,1)=mapFin(lx); %用于作图
view(end,2)=lbest;
% 4、选择
%轮盘赌算法
selChance=popFitness/sum(popFitness);%计算选择概率
accChance=[];
accChance(1)=selChance(1);
for i=2:popSize
accChance(i)=selChance(i)+accChance(i-1);
end %计算累计概率
randnumber=rand(1,round(popSize*selPrb)); %生成随机数
selNum=size(randnumber); %确定选择个数
selUnit=strings(selNum(1,end),1); %选择后的个体将存在这里
for j=1:selNum(1,end) %轮盘赌开始
for i=1:popSize
if((i==1)&&randnumber(j)<accChance(i))
selUnit(j)=pop(i);
elseif (randnumber(j)<accChance(i))&&(randnumber(j)>accChance(i-1))
selUnit(j)=pop(i);
end
end
end
%轮盘赌结束。问题:选择重复
pop=selUnit; %更新种群
te=size(selUnit);
temSize=te(1,1);
% 5、交叉 未处理越界问题
for i=1:2:temSize-1
temPro=rand; %生成随机数,与交叉概率比较
if temPro<croPrb
croPos=randi([1,codingLength]); %生成交叉随机位置
unit1=char(selUnit(i));
unit2=char(selUnit(i+1));
if croPos==1 %交叉位置为1的情况
ex1u=unit1(1:1);
ex1d=unit1(croPos+1:end);
ex2u=unit2(1:1);
ex2d=unit2(croPos+1:end);
else
ex1u=unit1(1:croPos-1);
ex1d=unit1(croPos:end);
ex2u=unit2(1:croPos-1);
ex2d=unit2(croPos:end);
end
unit1=strcat(ex1u,ex2d);
unit2=strcat(ex2u,ex1d);
%一次交叉完成
pop(end+1,1)=string(unit1);
pop(end+1,1)=string(unit2); %将交叉生成的子代加入种群
end
end
%交叉完成
popSizeTem=size(pop);
popSize=popSizeTem(end,1); %更新种群大小
% 6、变异
for i=1:popSize
if rand<varPrb
varPos=randi([1,codingLength]);
varTem=char(pop(i));
if varTem(varPos)=='1'
varTem(varPos)='0';
pop(i)=string(varTem);
else
varTem(varPos)='1';
pop(i)=string(varTem);
end
end
end
%变异完成
end %代数循环完成
plot(view(:,1),view(:,2),'r--');
%选出最佳个体
[gBesty,xFinMax]=max(view(:,2));
gBestx=view(xFinMax,1);