填坑:遗传算法代码(MATLAB)

上一篇博文写了遗传算法的主要思路,然后摸索了一下工具箱什么的,今天就把代码这个坑先填上。

顺序就按照上一篇博文里面写的步骤来:

问题描述:采用遗传算法和非线性规划的方法求解如下函数的极小值:

f(x) = -5sinx_{1}sinx_{2}sinx_{3}sinx_{4}sinx_{5}-sin5x_{1}5x_{2}5x_{3}5x_{4}5x_{5}+8

其中的变量都在0~0.9π之间。

该函数的最小值为-2,最小值位置为(π/2,π/2,π/2,π/2,π/2)。

1. 先是写适应度函数

个体的适应度是适应度函数值的倒数,上一篇博文中已经用红色字标注出来了,函数值越小的个体,适应度值越大,个体越优。

所以,代码如下:

function y = fun(x)
y = -5 * sin(x(1))*sin(x(2))*sin(x(3))*sin(x(4))*sin(x(5))-
sin(5*x(1))*sin(5*x(2))*sin(5*x(3))*sin(5*x(4))*sin(5*x(5))+8;

其实所谓的适应度函数就是题目所要求的函数,适应度的话,就在下面的程序中取1/y。

2. 选择操作

方法选用的是轮盘赌(一个for循环,取随机),然后组成新的种群。

function ret = select(individuals,sizepop)
%individuals input :种群信息
%sizepop     input :种群规模
%opts        input :选择方法
%ret         input :重组的种群
individuals.fitness =  1./(individuals.fitness);
sunmfitness = sum (individuals.fitness);    %求适应度的总和
sumf = individuals.fitness./sumfitness;    %求每个函数值适应度的占比
index = [];    %建立一个序列

for i = 1:sizepop;    %开始轮盘赌
    pick = rand;        %这里把rand(0-1的随机数)理解成百分比比较好,作为一个概率的比较标准
    while pick == 0
        pick = rand;
    end
    for j = 1:sizepop
        pick = pick - sumf(j);
        if pick<0
            index = [index j];    %这里其实就是进行pick和sumf的对比,
                                  %如果pick比sumf小,就放入序列
            break;
        end
    end
end

individuals.chrom = individuals.chrom(index,:);
individuals.fitness = individuals.fitness(index);
ret = individuals;

轮盘赌的想法就是模拟自然选择,把值的大小换算成面积,用随机值来模拟指针,值越大,选中的概率也就越大。

这里可能不是很好理解,在知乎上有很多大佬解读过轮盘赌的方法,比我这个更详细,可以去观摩。毕竟我这个算法只针对这道题。

3. 交叉操作

函数就不解释了,贴个链接:https://blog.csdn.net/zhangqimo/article/details/105292845

function ret = Cross(pcross,lenchrom,chrom,sizepop,bound)

%pcross input :交叉概率
%lenchrom input :%染色体长度
%chrom input :%染色体群
%sizepop input :种群规模
%ret output :交叉后的染色体

for i = 1 : sizepop
    pick = rand(1,2);
    
    while prod(pick) == 0    %prod函数是求矩阵元素的积
        pick = rand(1,2);
    end
   
    index = ceil(pick.*sizepop);
    pick = rand;
    while pick = 0;
        pick = rand;
    end
    
    if pick > pcross    %如果大于交叉互换的概率就继续进行操作
        continue;
    end
    
    flag = 0;
    while flag == 0
        pick = rand;
        while pick == 0
            pick = rand;   
        end

        pos = ceil(pick.*sum(lenchrom));     %随机选择交叉位置(选择第几个变量进行互换)
        pick = rand;    %交叉开始
        v1 = chrom(index(1),pos);
        v2 = chrom(index(2),pos);
        chrom(index(1),pos) = pick * v2 + (1-pick) *v1;
        chrom(index(2),pos) = pick * v2 + (i-pick) *v2;    %交叉结束

        flag1 = test(lenchrom,bound,chrom(index(1),:),fcode);    %bound为自变量取值的约                              
                                                                 %束,该函数检验可行性
        flag2 = test(lenchrom,bound,chrom(index(2),:),fcode);

        if flag1 * flag2 ==0
            flag = 0;
        else flag = 1;
            end            %如果都不行,则重新交叉
        end
    end
    ret = chrom;

4. 变异操作

是从种群中随机选择一个个体,按一定概率变异得到新个体。

function ret = Mutation(pmutation,lenchrom,chrom,sizepoppop,bound)

%pcross        input    :变异概率
%lenchrom      input    :染色体长度
%chrom         input    :染色体群
%sizepop       input    :种群规模
%pop           input    :当前种群的进化代数和最大的进化代数信息
%ret           output   :变异后的染色体

for i = 1 : sizepop
    pick = rand;    %随机选
    while pick == 0
        pick = rand;
    end
    index = ceil(pick * sizepop)
    
    pick = rand;
    if pick > pmutation
        continue;
    end
    flag = 0;
    while flag == 0;
        pick = rand;
        while pick == 0;
            pick == 0;
        end
        pos = ceil(pick * sum(lenchrom));
        v = chrom(i,pos);
        v1 = v - bound(pos,1)
        v2 = bound(pos,2) - v;
        pick = rand;
%从这里开始变异
        if pick>0.5
            delta = v2*(1-pick^((1-pop(1)/pop(2))^2);
            chrom(i,pos) = v + delta;
        else
            delta = v1*(1 - pick^((1-pop(1)/pop(2))^2));
            chrom(i,pos) = v-delta;
        end
            flag = test(lenchrom,bound,chrom(i,:),fcode);
        end
    end
end
ret = chrom;

5. 主程序

遗传算法基本上就是:随机初始化——计算种群适应度,找最优——选择——交叉——变异——寻优——判断结束条件。

具体代码为:

心态有点炸,码的代码被猫一脚踹没了。心情好了更。

更新:主程序

clc
clear

maxgen = 100;    %迭代次数
sizepop = 10;    %种群规模
pcross = [0.5];    %交叉概率
pmutation = [0.05];    %变异概率
lenchrom = [1 1 1 1 1];    %变量长度
bound = [0 0.5*pi;0 0.5*pi;0 0.5*pi;0 0.5*pi;0 0.5*pi];

%初始化(个体)
individuals = struct('fitness',zeros(1,sizepop),'chrom',[]);
avgfitness = [];    %平均适应度
bestfitness = [];    %最佳适应度
bestchrom = [];    %最佳染色体

%初始化(种群)
for i = 1 : sizepop
    individuals.chrom(i,:) = Code(lenchrom,bound);
    x = individuals.chrom(i,:);
    individuals.fitness(i) = fun(x);
end

%找最优
[bestfitness bestindex] = min(individuals.fitness);
bestchrom = individuals.chrom(bestindex,:);
avgfitness = sum(individuals.fitness)/sizepop;
trace=[];    %记录每一代数值

%进化
for i = 1 :maxgen
%选择
individuals = Select(individuals,sizepop);
avgfitness = sum(individuals.fitness)/sizepop;
%交叉
individuals.chrom = Cross(pcross,lenchrom,individuals.chrom,sizepop,bound);
%变异
individuals.chrom = Mutation(pmutation,lenchrom,individuals.chrom,sizepop,[i maxgen],bound);

%以5代为界限,用求得数值作为初始值进行非线性寻优
if mod(i,5) == 0
    individuals.chrom = nonlinear(individuals.chrom,sizepop);
end

%计算适应度
for j = 1:sizepop
    x = individuals.chrom(j,:)
    individuals.fitness(j) = fun(x);
end

%求最优值所在位置
[newbestfitness,newbestindex] = min(individuals.fitness);

%与上一轮进化求得最优值对比,若更优,则替换
if bestfitness > newbestfitness
    bestfitness = newbestfitness;
    bestchrom = individuals.chrom(newbestindex,:);
end

avgfitness = sum(individuals.fitness)/sizepop;
trace = [trace;avgfitness bestfitness];    %每一代数据记录
end

6. 非线性寻优

这里得调用工具箱里的fmincon

function ret = nonlinear(chrom,sizepop)
for i = 1 : sizepop
    x = fmincon(inline('-5 * sin(x(1))*sin(x(2))*sin(x(3))*sin(x(4))*sin(x(5))-
    sin(5*x(1))*sin(5*x(2))*sin(5*x(3))*sin(5*x(4))*sin(5*x(5))'),
    chrom(i,:)',[],[],[],[],[0 0 0 0 0].[2.874 2.874 2.874 2.874 2.874]);
    ret(i,:)=x';
end

以上就是代码的全部了。

鬼知道我保存了几遍,不得不感叹一句,猫主子的脚是厉害,每次刚好踩到Alt+F4.

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值