• 智能优化之遗传算法


    概念

    是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型。
    本质:物竞天择,适者生存。
    下面我们从生物学的角度来分析一下:
    在这里插入图片描述
    假如有一只猫和一种花有两种性状,一种是深色的,一种是浅色的,而猫只喜欢吃深色的花。
    在这里插入图片描述
    那么在经过很多代后,深色的花由于经常被猫吃,则花会更多的变为浅色。
    在这里插入图片描述
    <1>在遗传算法中,染色体对应的是数据或数组。
    <2>串上各个位置对应基因的取值。
    <3>基因组成的串就是染色体,或者称为基因型个体
    <4>一定数量的个体组成了群体
    <5>个体对环境的适应程度叫适应度

    算法步骤

    在这里插入图片描述
    核心操作:
    <1>选择操作:从旧个体中以一定概率选择优良个体组成新的种群,以繁殖得到下一代。
    在这里插入图片描述
    通过图可以看出适应度越大,占的扇面就越大,遗传到下一代的概率也就越大。
    <2>交叉操作:从种群中随机选择两个个体,通过两个染色体的交换组合,把父串的优秀特征遗传给子串,从而产生新的优秀个体。
    在这里插入图片描述
    <3>变异操作:从种群中随机选择一个个体,选择个体中的一点进行变异以产生更优秀的个体。
    在这里插入图片描述

    代码

    主函数

    %% 清空环境
    clc
    clear
    
    %% 遗传算法参数
    maxgen=50;                         %进化代数
    sizepop=100;                       %种群规模
    pcross=0.6;                      %交叉概率
    pmutation=0.01;                  %变异概率
    lenchrom=5;              %变量字串长度
    bound=[0 0.9*pi;0 0.9*pi;0 0.9*pi;0 0.9*pi;0 0.9*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); 
         % 交叉操作
         individuals.chrom=Cross(pcross,lenchrom,individuals.chrom,sizepop,bound);
         % 变异操作
         individuals.chrom=Mutation(pmutation,lenchrom,individuals.chrom,sizepop,[i maxgen],bound);
        
        % 计算适应度 
        for j=1:sizepop
            x=individuals.chrom(j,:);
            individuals.fitness(j)=fun(x);   
        end
        
      %找到最小和最大适应度的染色体及它们在种群中的位置
        [newbestfitness,newbestindex]=min(individuals.fitness);
        [worestfitness,worestindex]=max(individuals.fitness);
        % 代替上一次进化中最好的染色体
        if bestfitness>newbestfitness
            bestfitness=newbestfitness;
            bestchrom=individuals.chrom(newbestindex,:);
        end
        individuals.chrom(worestindex,:)=bestchrom;
        individuals.fitness(worestindex)=bestfitness;
        
        avgfitness=sum(individuals.fitness)/sizepop;
        
        trace=[trace;avgfitness bestfitness]; %记录每一代进化中最好的适应度和平均适应度
    end
    %进化结束
    
    %% 结果显示
    [r,~]=size(trace);
    figure
    plot(1:r,trace(:,1),'r-',1:r,trace(:,2),'b--');
    title(['函数值曲线  ' '终止代数=' num2str(maxgen)],'fontsize',12);
    xlabel('进化代数','fontsize',12);ylabel('函数值','fontsize',12);
    legend('各代平均值','各代最佳值');
    grid on
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    Code函数(用来将变量编码成染色体)

    function ret=Code(lenchrom,bound)
    %本函数将变量编码成染色体,用于随机初始化一个种群
    % lenchrom   input : 染色体长度
    % bound      input : 变量的取值范围
    % ret        output: 染色体的编码值
    
    flag=0;
    while flag==0
        pick=rand(1,lenchrom);
        ret=bound(:,1)'+(bound(:,2)-bound(:,1))'.*pick; %线性插值
        flag=test(bound,ret);             %检验染色体的可行性
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    fun函数(所求问题的表达式)

    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
    • 2

    test函数(测试范围)

    function flag=test(bound,code)
    % lenchrom   input : 染色体长度
    % bound      input : 变量的取值范围
    % code       output: 染色体的编码值
    
    flag=1;
    [n,m]=size(code);
    
    for i=1:n
        if code(i)<bound(i,1) || code(i)>bound(i,2)
            flag=0;
        end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Select函数(选择操作)

    function ret=Select(individuals,sizepop)
    % 本函数对每一代种群中的染色体进行选择,以进行后面的交叉和变异
    % individuals input  : 种群信息
    % sizepop     input  : 种群规模
    % opts        input  : 选择方法的选择
    % ret         output : 经过选择后的种群
    
    individuals.fitness= 1./(individuals.fitness);
    sumfitness=sum(individuals.fitness);
    sumf=individuals.fitness./sumfitness;
    index=[];
    for i=1:sizepop   %转sizepop次轮盘
        pick=rand;
        while pick==0
            pick=rand;
        end
        for j=1:sizepop
            pick=pick-sumf(j);
            if pick<0
                index=[index j];
                break;  %寻找落入的区间,此次转轮盘选中了染色体i,注意:在转sizepop次轮盘的过程中,有可能会重复选择某些染色体
            end
        end
    end
    individuals.chrom=individuals.chrom(index,:);
    individuals.fitness=individuals.fitness(index);
    ret=individuals;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    Cross函数(交叉操作)

    function ret=Cross(pcross,lenchrom,chrom,sizepop,bound)
    %本函数完成交叉操作
    % pcorss                input  : 交叉概率
    % lenchrom              input  : 染色体的长度
    % chrom                 input  : 染色体群
    % sizepop               input  : 种群规模
    % ret                   output : 交叉后的染色体
    
    for i=1:sizepop
        
        % 随机选择两个染色体进行交叉
        index=randi(sizepop,2,1);
        % 交叉概率决定是否进行交叉
        pick=rand;
        while pick==0
            pick=rand;
        end
        if pick>pcross
            flag=0;
            while flag==0
                % 随机选择交叉位置
                pos=randi(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*v1+(1-pick)*v2; %交叉结束
                flag1=test(bound,chrom(index(1),:));  %检验染色体1的可行性
                flag2=test(bound,chrom(index(2),:));  %检验染色体2的可行性
                if   flag1*flag2==0
                    flag=0;
                else flag=1;
                end    %如果两个染色体不是都可行,则重新交叉
            end
        end
    end
    ret=chrom;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    Mutation(变异操作)

    function ret=Mutation(pmutation,lenchrom,chrom,sizepop,pop,bound)
    % 本函数完成变异操作
    % pmutation             input  : 变异概率
    % lenchrom              input  : 染色体长度
    % chrom                 input  : 染色体群
    % sizepop               input  : 种群规模
    % pop                   input  : 当前种群的进化代数和最大的进化代数信息
    % ret                   output : 变异后的染色体
    
    for i=1:sizepop
        % 随机选择一个染色体进行变异
        index=randi(sizepop);
        % 变异概率决定该轮循环是否进行变异
        pick=rand;
        if pick>pmutation
            flag=0;
            while flag==0
                % 变异位置
                pos=randi(lenchrom);  %随机选择了染色体变异的位置,即选择了第pos个变量进行变异
                v=chrom(index,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(index,pos)=v+delta;
                else
                    delta=v1*(1-pick^((1-pop(1)/pop(2))^2));
                    chrom(index,pos)=v-delta;
                end   %变异结束
                flag=test(bound,chrom(index,:));     %检验染色体的可行性
            end
        end
    end
    ret=chrom;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
  • 相关阅读:
    天童美语育儿书籍推荐《愿你慢慢长大》
    Transformer的最简洁pytorch实现
    Oracle性能调优实践中的几点心得
    【Go电商实战03】如何使用ORM链式操作?如何优雅的实现软删除?
    “蔚来杯“2022牛客暑期多校训练营(补题合集)
    基于 51 的点阵屏显示·16*16 点阵仿真实验(静态显示,左移显示)
    RK3588 实现温控风扇之pwm驱动调试(二)
    阿里云服务器租用价格,不同实例云服务器日常价、活动价与券后价格
    带你深入了解屏幕刷新机制
    中国石油大学(北京)-《 完井工程》第三阶段在线作业
  • 原文地址:https://blog.csdn.net/weixin_51711289/article/details/125999231