基于遗传算法和非线性规划的函数寻优算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


问题描述

采用遗传算法和非线性规划的方法求解如下函数的极小值
y=-5*sin(x(1))*sin(x(2))*sin(x(3))*sin(x(4))sin(x(5))-sin(5x(1))sin(5x(2))sin(5x(3))sin(5x(4))sin(5x(5))+8;

算法流程

在这里插入图片描述

函数

function y=my_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;
end

选择操作

function ret=my_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; %寻找落入区间的染色体,此次选择为j
            end
        end
    end
    individuals.chrom=individuals.chrom(index,:);%获取chrom中行索引在index中的chrom数据
    individuals.fitness=individuals.fitness(index);
    ret=individuals;

交叉操作

function ret=my_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
        pick=rand(1,2);
    end
    index=ceil(pick.*sizepop);%取整的意思 取的整数>=1;
    %交叉概率决定是否进行交叉
    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*v1+(1-pick)*v2;%交叉结束

        flag1=test(lenchrom,bound,chrom(index(1),:));
        flag2=test(lenchrom,bound,chrom(index(2),:));
        if flag2*flag1==0
            flag=0;
        else
            flag=1;
        end  %如果两个染色体不是都可行,则重新交叉    
    end
end
ret=chrom;
end

变异操作

function ret=my_Mutation(pmutation,lenchrom,chrom,sizepop,pop,bound)
% 本函数完成变异操作
% pmutation 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=rand;
    end
    pos=ceil(pick.*sum(lenchrom)); %获取变异的位置
    chrom_max=max(chrom(index));%基因的上界
    chrom_min=max(chrom(index));%基因的下界
    r2=rand;
    f_g=r2*(1-pop(1)/pop(2))^2;%pop(1):表示当前迭代次数,pop(2)表示最大迭代次数
    %变异开始 
    r=rand; 
    if r>=0.5
    chrom(index,pos)=chrom(index,pos)+(chrom(index,pos)-chrom_max)*f_g;
    else
    chrom(index,pos)=chrom(index,pos)+(chrom_min-chrom(index,pos))*f_g;%变异结束
    end
    flag=test(lenchrom,bound,chrom(i,:));
    end   
end
ret=chrom;
end

编码

将变量编码成染色体

function ret=Code(lenchrom,bound)
% 本函数将变量编码成染色体,用于随机初始化一个种群
% lenchrom   input:染色体长度
% bound      input:变量的取值范围
% ret        output:染色体的编码值
flag=0;
while flag==0
    pick=rand(1,length(lenchrom));
    ret=bound(:,1)'+(bound(:,2)-bound(:,1))'.*pick; %线性插值
    flag=test(lenchrom,bound,ret);
end
end

检测

function flag=test(lenchrom,bound,code)
% 用于交叉、变异过程中会产生超过取值范围的变量,所以定义了flag来检测变量是否在约束区间里
% lenchrom input:染色体长度
% bound    input:变量的取值范围
% code     output:染色体的编码值
flag=1;
[n,m]=size(code);% n行m列
for i=1:n
    if code(i)<bound(i,1)||code(i)>bound(i,2)
        flag=0;
    end
end
end

main 主函数

%% 清除环境变量
clc
clear
%% 遗传算法参数
maxgen=200;%进化代数,即迭代次数
sizepop=20;%种群规模
pcross=0.6;%交叉概率
pmutation=0.01;%变异概率
lenchrom=[1 1 1 1 1];%每个变量的字串长度,如果是浮点变量,则长度都为1
bound=[0 0.9*pi;0 0.9*pi;0 0.9*pi;0 0.9*pi;0 0.9*pi];

%% 个体初始化
% fitness 即为zeros(1,sizepop);chrom 即为[]
individuals=struct('fitness',zeros(1,sizepop),'chrom',[]);%种群结构体
avgfitness=[];%种群的平均适应度
bestfitness=[];%种群的最佳适应度
bestchrom=[];%适应度最好的染色体
%初始化种群
for i=1:sizepop
    individuals.chrom(i,:)=Code(lenchrom,bound);%随机产生染色体
    %individuals.chrom(i,:)=rand(1,5)*0.9*pi;%随机产生染色体
    x=individuals.chrom(i,:);
    individuals.fitness(i)=my_fun(x);
end
% 找最好的染色体
[bestfitness,bestindex]=min(individuals.fitness);
bestchrom=individuals.chrom(bestindex,:);%最好的染色体
avgfitness=sum(individuals.fitness)/sizepop;%染色体的平均适应度
% 记录每一代进化中最好的适应度和平均适应度
trace=[];
%% 进化开始
for i=1:maxgen
    %选择
    individuals=my_select(individuals,sizepop);
    avgfitness=sum(individuals.fitness)./sizepop;
    %交叉
    individuals.chrom=my_Cross(pcross,lenchrom,individuals.chrom,sizepop,bound);
    %变异
    individuals.chrom=my_Mutation(pmutation,lenchrom,individuals.chrom,sizepop,[i maxgen],bound);
    % 每进化10代,以所得值为初始值进行非线性优化
    if mod(i,10)==0
        individuals.chrom=my_nonlinear(individuals.chrom,sizepop);
    end
    %计算适应度
    for j=1:sizepop
        x=individuals.chrom(j,:);
        individuals.fitness(j)=my_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];%trace(:,1)第一列代表平均适应度值,trace(:,2)第二列代表各代最佳值
end %进化结束
%% 绘制图
figure(1);
[r,c]=size(trace);
plot([1:r],trace(:,1),'r-',[1:r],trace(:,2),'b-');

结果

红色为平均适应度;蓝色为最小的适应度值
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JiAngTxone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值