经典遗传算法编写总结

文末附有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);


猜你喜欢

转载自blog.csdn.net/qq_39068200/article/details/100596727