遗传算法及其matlab实现(工具箱及非工具箱)

本文将简单叙述遗传算法的原理及实现过程,并通过采用工具箱非工具箱两种方法解决一个在约束条件下求解函数最小值的问题。


前言

遗传算法是1962年Holland教授基于进化机制自然遗传学提出的一种启发式,并行,随机优化算法。它将待优化问题的求解过程表示成个体“适者生存”的进化过程。将问题的解表示成“染色体”(个体),由多个个体组成的群体经过数次选择交叉变异三个进化过程,最终得到最适应环境的个体,即待优化问题的最优解。


一、遗传算法实现过程

在遗传算法中,n维向量X = [x1,x2,…,xn]T可以看作由n个遗传基因组成的一个染色体。染色体X又叫做个体,对于每个个体,要按照一定规矩确定出其适应度。个体适应度与目标函数相关联,个体越接近于目标函数,其适应度越大。通过搜索染色体来解决问题的最优解。
进化过程是以集群为主体。由M个个体组成的群体作为遗传算法的运算对象。遗传算法的运算过程是一个反复迭代的过程。遗传算法包括选择,交叉,变异三个操作。
(1)选择:根据每一个个体的适应度,按照“进化”规则,从群体中选择优良的个体遗传到下一代。
(2)交叉:在群体中按照指定的交叉概率交换随机配对的个体的部分染色体。
(3)变异:在群体中按照指定的变异概率改变个体基因中的一个或者多个
在这里插入图片描述

二、matlab实现

1.工具箱实现

代码如下:

[x,fval]=ga(@fitnessfun,n,A,b,Aeq,beq,lb,ub,@nonlcon,options)

其中:
fitnessfun是求最小值的适应度函数;
n:问题待求变量的个数;
A,b分别是是不等式约束AX<=b的系数矩阵和常数项;
Aeq,beq分别是等式约束Aeq
X = beq的系数矩阵和常数项;
lb,ub分别是是X的下限和上限;
nonlcon是非线性约束函数。
x:待求最优值;
fval:适应度函数的最终值
options是一个包含遗传算法选项设置、属性参数的结构。具体格式如下:

options=gaoptimset('PropertyName1','PropertyValue1','PropertyName 2',' PropertyValue2','PropertyName3','PropertyValue3'......)

仿真例子:

在这里插入图片描述

求最小值的适应度函数:

function y=fun(x)
 y=3*x(1)-2*x(2)+x(3);
end

主程序:

clear all;
clc;
A=[-1 0 0;1 0 0;0 -1 0;0 1 0;0 0 -1;0 0 1];
b=[-10;10;-10;10;-10;10]; 
Aeq=[1 1 1]; 
beq=18;
[x,y]=ga(@fun,3,A,b,Aeq,beq); 
x
y

2.非工具箱实现

代码如下:

求最小值的适应度函数:

function y=fun(x)
y=3*x(1)-2*x(2)+(18-x(1)-x(2));  
end

选择操作:

function ret=select(individuals,sizepop)
% 该函数用于进行选择操作
% individuals input    种群信息
% sizepop     input    种群规模
% ret         output   选择后的新种群

%求适应度值倒数   
fitness1=1./individuals.fitness; %individuals.fitness为个体适应度值

%个体选择概率
sumfitness=sum(fitness1);
sumf=fitness1./sumfitness;

%采用轮盘赌法选择新个体
index=[]; 
for i=1:sizepop   %sizepop为种群数
    pick=rand;
    while pick==0    
        pick=rand;        
    end
    for i=1:sizepop    
        pick=pick-sumf(i);        
        if pick<0        
            index=[index i];            
            break;  
        end
    end
end

%新种群
individuals.chrom=individuals.chrom(index,:);   %individuals.chrom为种群中个体
individuals.fitness=individuals.fitness(index);
ret=individuals;

交叉操作:

function ret=Cross(pcross,lenchrom,chrom,sizepop,bound)
%本函数完成交叉操作
% pcorss                input  : 交叉概率
% lenchrom              input  : 染色体的长度
% chrom     input  : 染色体群
% sizepop               input  : 种群规模
% ret                   output : 交叉后的染色体
 for i=1:sizepop  %每一轮for循环中,可能会进行一次交叉操作,染色体是随机选择的,交叉位置也是随机选择的,%但该轮for循环中是否进行交叉操作则由交叉概率决定(continue控制)
     % 随机选择两个染色体进行交叉
     pick=rand(1,2);
     while prod(pick)==0
         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*v1+(1-pick)*v2; %交叉结束
         flag1=test(lenchrom,bound,chrom(index(1),:));  %检验染色体1的可行性
         flag2=test(lenchrom,bound,chrom(index(2),:));  %检验染色体2的可行性
         if   flag1*flag2==0
             flag=0;
         else flag=1;
         end    %如果两个染色体不是都可行,则重新交叉
     end
 end
ret=chrom;

变异操作:

function ret=Mutation(pmutation,lenchrom,chrom,sizepop,num,maxgen,bound)
% 本函数完成变异操作
% pcorss                input  : 变异概率
% lenchrom              input  : 染色体长度
% chrom     input  : 染色体群
% sizepop               input  : 种群规模
% opts                  input  : 变异方法的选择
% pop                   input  : 当前种群的进化代数和最大的进化代数信息
% bound                 input  : 每个个体的上届和下届
% maxgen                input  :最大迭代次数
% num                   input  : 当前迭代次数
% ret                   output : 变异后的染色体

for i=1:sizepop   %每一轮for循环中,可能会进行一次变异操作,染色体是随机选择的,变异位置也是随机选择的,
    %但该轮for循环中是否进行变异操作则由变异概率决定(continue控制)
    % 随机选择一个染色体进行变异
    pick=rand;
    while pick==0
        pick=rand;
    end
    index=ceil(pick*sizepop);
    % 变异概率决定该轮循环是否进行变异
    pick=rand;
    if pick>pmutation
        continue;
    end
    flag=0;
    num = 0;
    chrom1 = chrom(i,:);
    while flag==0&&num<=20
        % 变异位置
        pick=rand;
        while pick==0      
            pick=rand;
        end
        pos=ceil(pick*sum(lenchrom));  %随机选择了染色体变异的位置,即选择了第pos个变量进行变异
        
        pick=rand; %变异开始  
        fg=(rand*(1-num/maxgen))^2;
        if pick>0.5
            chrom(i,pos)=chrom(i,pos)+(bound(pos,2)-chrom(i,pos))*fg;
        else
            chrom(i,pos)=chrom(i,pos)+(chrom(i,pos)-bound(pos,1))*fg;
        end   %变异结束
        flag=test(lenchrom,bound,chrom(i,:));     %检验染色体的可行性
        num = num+1;  % 检验次数设置
    end
    if num>20         % 如果大于20次,则不变异
        chrom(i,:) = chrom1;
    end
end
ret=chrom;

编码:

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; %线性插值,编码结果以实数向量存入ret中
    flag=test(lenchrom,bound,ret);     %检验染色体的可行性
end

测试函数:

function flag=test(lenchrom,bound,code)
% lenchrom   input : 染色体长度
% bound      input : 变量的取值范围
% code       output: 染色体的编码值
t=code; %先解码
t3 =18-t(1)-t(2);
flag=1;
if (t(1)<bound(1,1))||(t(2)<bound(2,1))||(t(1)>bound(1,2))||(t(2)>bound(2,2))||t3<0||t3>10
    flag=0;
end     

主函数:

clc,clear,close all
% 遗传算法参数初始化
maxgen = 50;                      % 进化代数,即迭代次数
sizepop = 50;                     % 种群规模
pcross = [0.7];                    % 交叉概率选择,01之间
pmutation = [0.01];                 % 变异概率选择,01之间
%染色体设置
lenchrom=ones(1,2);    % t1、t2
bound=[-10,10;-10,10;];   % 数据范围
%---------------------------种群初始化------------------------------------
individuals=struct('fitness',zeros(1,sizepop), 'chrom',[]);  %将种群信息定义为一个结构体
avgfitness = [];                      %每一代种群的平均适应度
bestfitness = [];                     %每一代种群的最佳适应度
bestchrom = [];                       %适应度最好的染色体
% 初始化种群
for i=1:sizepop
    % 随机产生一个种群
    individuals.chrom(i,:)=Code(lenchrom,bound); % 编码(binary和grey的编码结果为一个实数,float的编码结果为一个实数向量)
    x=individuals.chrom(i,:);
    % 计算适应度
    individuals.fitness(i)=fun(x);   % 染色体的适应度 
end
% 找最好的染色体
[bestfitness bestindex] = min(individuals.fitness);
bestchrom = individuals.chrom(bestindex,:);    % 最好的染色体
% 记录每一代进化中最好的适应度和平均适应度
trace = [bestfitness]; 
% 迭代求解最佳初始阀值和权值
% 进化开始
for i=1:maxgen
    disp(['迭代次数:  ',num2str(i)])
    % 选择
    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; % 剔除最差个体
    trace=[trace;bestfitness]; %记录每一代进化中最好的适应度
end
x = [bestchrom, 20-sum(sum(bestchrom))];       % 最佳个体值
x
bestfitness

仿真结果:
在这里插入图片描述


总结

本文简述了遗传算法的原理及通过工具箱和非工具箱两种方法仿真实例。
遗传算法是一种自适应全局随机优化算法,是群体搜索策略和群体中个体之间的信息交换,搜索不依赖于梯度信息,搜索不依赖于初始点,基本上不用搜索空间的知识或其它辅助信息,不与求解空间有紧密关系。
关于算法的具体细节推荐:
MATLAB优化算法案例分析与应用
MATLAB优化算法案例分析与应用(进阶版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值