MATLAB智能算法—遗传算法

本文详细介绍了遗传算法的概念、特点和基本操作,包括种群初始化、适应度函数、选择、交叉和变异等步骤。重点讲解了MATLAB中遗传算法工具箱的使用,如谢菲尔德遗传算法工具箱的安装配置和功能。此外,还探讨了遗传算法在非线性规划、TSP问题、多目标优化及车间调度等领域的应用实例。

1.遗传算法的介绍

遗传算法(Genetic Algorithm,GA)关键是把问题参数编码成染色体,再利用迭代方式进行选择、交叉、变异等运算交换种群中的染色体信息,根据适应度的好坏选择一定数量优秀的染色体,经过若干代的进化后,最终收敛于最好的符合优化目标染色体。

特点:

  1. 全局搜索能力强,局部搜索能力弱
  2. 一般得到的是次优解,而非最优解(问题规模小可得最优解,问题规模大一般只能得近似解)

术语:

  1. 个体(individual)
  2. 适应度函数(fitness function)、适应度函数值(fitness value)
  3. 种群(population)、种群大小(population size)
  4. 代(generation)
  5. 父代(parents)、子代(children)
  6. 选择(select)、交叉(crossover)、变异(mutation)
  7. 精英数目(eliteCount)、交叉后代比例(crossover fraction)

步骤:

  1. 初始化种群:位串编码、Grey编码、实数编码、多级参数编码、有序串编码、结构式编码
  2. 适应度函数:由目标函数变换得到,函数值越大/小,个体越优
  3. 选择操作:个体适应度函数值越高,被选中概率越大,轮盘赌法、锦标赛法
  4. 交叉操作:随机抽取种群两个个体,通过染色体的交换组合,把父串的优秀特征传给子串,从而产生新的优秀个体
  5. 变异操作:维持种群多样性,随机抽取种群单个体,选择染色体的一点变异
  6. 收敛寻优:通过迭代产生的新种群为下次计算的初始值,经过众多次迭代,算法收敛于“最优解”
  7. 结果统计:多次测试,根据需求,取最优或平均

参数:

  1. 种群规模:100
  2. 进化次数:30
  3. 交叉概率:0.6
  4. 变异概率:0.1

改进:

  1. 精英策略:子代种群中的最优个体永远不会比父代最优的个体差,使得父代好的个体不至于交叉、变异而丢失
  2. 进化逆转:TSP解的关键在于码串的顺序,交叉一方面可以维持种群的多样性,避免陷入局部最优,另一方面它不利于子代继承亲代的较多信息,特别是进化到了后期,群体充斥大量高适应度个体,交叉对亲代的较优基因破坏很大,使子代难以继承到亲代的优良基因,从而使交叉算子的搜索能力大大降低;单向进化逆转,即只接受朝着好的方向的逆转,搜索最优解的能力强于交叉算子

 

2.遗传算法工具箱

2.1 GA工具箱

  1. 英国谢菲尔德大学的遗传算法工具箱
  2. 美国北卡罗来纳州立大学的遗传算法最优化工具箱
  3. MATLAB自带的遗传算法工具箱与直接搜索工具箱

2.2 谢菲尔德遗传算法工具箱

     2.2.1 安装配置到 Matlab

  1. 将 gatbx 文件夹复制粘贴到 Matlab 软件安装目录下的 toolbox 目录中
  2. 将所在文件夹添加到 Matlab 的搜索路径:str=[matlabroot,'\toolbox\gatbx'];    addpath(str)
  3. 测试是否安装成功:v = ver('gatbx')

    2.2.2  工具箱相关函数功能介绍

      

2.2 

2.3 MATLAB自带的遗传算法工具箱与直接搜索工具箱

     Genetic Algorithm and Direct Search Toolbox,GADST

     2.3.1 GADST GUI

命令行输入:

optimtool('ga')

注意:GADST是对目标函数去最小值进行优化,若要最大值优化,将适应度函数*-1

 

 

3 非线性规划的函数寻优

     

1.初始化种群:实数编码:不必进行数值转换,可以直接在解的表现型上进行遗传算法操作

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

2.适应度函数:求函数最小值,将函数值的倒数作为个体的适应度值,即函数值越小的个体越优

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;

3.选择操作:轮盘赌:基于适应度比例的选择策略

    

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;

4.交叉操作:实数交叉

   

function ret=Cross(pcross, lenchrom, chrom, sizepop, bound)
% pcorss                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);
    % 交叉概率决定是否进行交叉
    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;

5.变异操作

       

function ret=Mutation(pmutation, lenchrom, chrom, sizepop, pop, bound)
% pcorss                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个变量进行变异
        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,:));     % 检验染色体的可行性
    end
end

ret=chrom;

6.收敛寻优

基本GA寻优

%% 清空环境
clc
clear

%% 遗传算法参数
maxgen=30;              % 进化代数
sizepop=100;            % 种群规模
pcross=[0.6];           % 交叉概率
pmutation=[0.01];       % 变异概率
lenchrom=[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];  % 变量范围

%% 个体初始化
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);
    
    % 计算适应度 
    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 c]=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('各代平均值','各代最佳值');
disp('函数值                   变量');
ylim([1.5 8])
%xlim([1,size(trace,1)])
grid on
% 窗口显示
disp([bestfitness x]);

工具箱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.8274 2.8274 2.8274 2.8274 2.8274]);
    ret(i,:)=x';
end
%% 清空环境
clc
clear
warning off

%% 遗传算法参数
maxgen=30;                         % 进化代数
sizepop=100;                       % 种群规模
pcross=[0.6];                      % 交叉概率
pmutation=[0.01];                  % 变异概率
lenchrom=[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];  %变量范围

%% 个体初始化
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);
    
    if mod(i,10)==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);
    [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   % 进化结束

%% 结果显示
figure
[r c]=size(trace);
plot([1:r]',trace(:,1),'r-',[1:r]',trace(:,2),'b--');
title(['函数值曲线  ' '终止代数=' num2str(maxgen)],'fontsize',12);
xlabel('进化代数','fontsize',12);ylabel('函数值','fontsize',12);
legend('各代平均值','各代最佳值','fontsize',12);
ylim([1.5 8])
disp('函数值                   变量');
% 窗口显示
disp([bestfitness x]);
grid on

7.结果

基本GA优化迭代到第30次函数值收敛于2,工具箱优化迭代到第10次函数值收敛于2

 

 

 

4 基于遗传算法的TSP算法

TSP:从一个城市出发,访问每个城市且只去一次,最后回到出发城市,使路径最短(一条遍历n个城市的最短曼哈顿回路)

城市编号X坐标Y坐标城市编号X坐标Y坐标
116.4796.1817.296.29
216.4794.44916.397.38
320.0992.541014.0598.12
422.3993.371116.5397.38
525.2397.241221.5295.59
62296.051319.4197.13
720.4797.021420.0992.55

 

1.编码

          对14个城市的TSP问题:|1|14|2|4|8|5|6|12|9|7|11|13|3|10|  可作为一条合法染色体

2.初始化种群:依据城市规模而定 [50, 200]

function Chrom=InitPop(NIND, N)
% 输入:
%   NIND:种群大小
%   N:   个体染色体长度(这里为城市的个数)  
Chrom=zeros(NIND,N);  % 用于存储种群
for i=1:NIND
    Chrom(i,:)=randperm(N);  % 随机生成初始种群
end

3.适应度函数:适应度函数值越大,个体值越优

                       

function FitnV=Fitness(len)
% 输入:
%   个体的长度(TSP的距离)
% 输出:
%   个体的适应度值
FitnV=1./len;

4.选择

function SelCh=Select(Chrom,FitnV,GGAP)
% 输入
%   Chrom 种群
%   FitnV 适应度值
%   GGAP:选择概率
% 输出
%   SelCh  被选择的个体
NIND=size(Chrom,1);
NSel=max(floor(NIND*GGAP+.5),2);
ChrIx=Sus(FitnV,NSel);
SelCh=Chrom(ChrIx,:);

function NewChrIx = Sus(FitnV,Nsel)
% 输入:
%   FitnV  个体的适应度值
%   Nsel   被选择个体的数目
% 输出:
%   NewChrIx  被选择个体的索引号

% Identify the population size (Nind)
   [Nind,ans] = size(FitnV);

% Perform stochastic universal sampling
   cumfit = cumsum(FitnV);
   trials = cumfit(Nind) / Nsel * (rand + (0:Nsel-1)');
   Mf = cumfit(:, ones(1, Nsel));
   Mt = trials(:, ones(1, Nind))';
   [NewChrIx, ans] = find(Mt < Mf & [ zeros(1, Nsel); Mf(1:Nind-1, :) ] <= Mt);

% Shuffle new population
   [ans, shuf] = sort(rand(Nsel, 1));
   NewChrIx = NewChrIx(shuf);

% End of function

5.交叉:部分映射杂交,确定交叉操作的父代并将其两两分组,每组重复

          以10个城市为例演示交叉操作

        

function SelCh=Recombin(SelCh,Pc)
% 输入
%   SelCh  被选择的个体
%   Pc     交叉概率
% 输出:
%   SelCh 交叉后的个体

NSel=size(SelCh,1);
for i=1:2:NSel-mod(NSel,2)
    if Pc>=rand  % 交叉概率Pc
        [SelCh(i,:),SelCh(i+1,:)]=intercross(SelCh(i,:),SelCh(i+1,:));
    end
end

% 输入:
%   a和b为两个待交叉的个体
% 输出:
%   a和b为交叉后得到的两个个体

function [a,b]=intercross(a,b)
L=length(a);
r1=randsrc(1,1,[1:L]);
r2=randsrc(1,1,[1:L]);
if r1~=r2
    a0=a;b0=b;
    s=min([r1,r2]);
    e=max([r1,r2]);
    for i=s:e
        a1=a;b1=b;
        a(i)=b0(i);
        b(i)=a0(i);
        x=find(a==a(i));
        y=find(b==b(i));
        i1=x(x~=i);
        i2=y(y~=i);
        if ~isempty(i1)
            a(i1)=a1(i);
        end
        if ~isempty(i2)
            b(i2)=b1(i);
        end
    end
end



% %交叉算法采用部分匹配交叉%交叉算法采用部分匹配交叉
% function [a,b]=intercross(a,b)
% L=length(a);
% r1=ceil(rand*L);
% r2=ceil(rand*L);
% r1=4;r2=7;
% if r1~=r2
%     s=min([r1,r2]);
%     e=max([r1,r2]);
%     a1=a;b1=b;
%     a(s:e)=b1(s:e);
%     b(s:e)=a1(s:e);
%     for i=[setdiff(1:L,s:e)]
%         [tf, loc] = ismember(a(i),a(s:e));
%         if tf
%             a(i)=a1(loc+s-1);
%         end
%         [tf, loc]=ismember(b(i),b(s:e));
%         if tf
%             b(i)=b1(loc+s-1);
%         end
%     end
% end

6.变异:随机选两个点交换位置

          以10个城市为例演示交叉操作

        

function SelCh=Mutate(SelCh,Pm)
% 输入:
%   SelCh  被选择的个体
%   Pm     变异概率
% 输出:
%   SelCh 变异后的个体

[NSel,L]=size(SelCh);
for i=1:NSel
    if Pm>=rand
        R=randperm(L);
        SelCh(i,R(1:2))=SelCh(i,R(2:-1:1));
    end
end

7.进化逆转:逆转算子的单方向性,即只有经过逆转后,适应度值有提高的才保留,否则逆转无效

          以10个城市为例演示交叉操作

        

function SelCh=Reverse(SelCh,D)
% 输入
%   SelCh 被选择的个体
%   D     个城市的距离矩阵
% 输出
%   SelCh  进化逆转后的个体

[row,col]=size(SelCh);
ObjV=PathLength(D,SelCh);  % 计算路径长度
SelCh1=SelCh;
for i=1:row
    r1=randsrc(1,1,[1:col]);
    r2=randsrc(1,1,[1:col]);
    mininverse=min([r1 r2]);
    maxinverse=max([r1 r2]);
    SelCh1(i,mininverse:maxinverse)=SelCh1(i,maxinverse:-1:mininverse);
end
ObjV1=PathLength(D,SelCh1);  % 计算路径长度
index=ObjV1<ObjV;
SelCh(index,:)=SelCh1(index,:);

9.寻优

clear
clc
close all
X =[16.47,96.10
    16.47,94.44
    20.09,92.54
    22.39,93.37
    25.23,97.24
    22.00,96.05
    20.47,97.02
    17.20,96.29
    16.30,97.38
    14.05,98.12
    16.53,97.38
    21.52,95.59
    19.41,97.13
    20.09,92.55];  % 个城市坐标位置,可以换成load CityPosition1.mat
NIND=100;          % 种群大小
MAXGEN=200;
Pc=0.9;            % 交叉概率
Pm=0.05;           % 变异概率
GGAP=0.9;          % 代沟(Generation gap)
D=Distanse(X);     % 生成距离矩阵
N=size(D,1);       % (34*34)
%% 初始化种群
Chrom=InitPop(NIND,N);
%% 在二维图上画出所有坐标点
% figure
% plot(X(:,1),X(:,2),'o');
%% 画出随机解的路线图
DrawPath(Chrom(1,:),X)
pause(0.0001)
%% 输出随机解的路线和总距离
disp('初始种群中的一个随机值:')
OutputPath(Chrom(1,:));
Rlength=PathLength(D,Chrom(1,:));
disp(['总距离:',num2str(Rlength)]);
disp('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
%% 优化
gen=0;
figure;
hold on;box on
xlim([0,MAXGEN])
title('优化过程')
xlabel('代数')
ylabel('最优值')
ObjV=PathLength(D,Chrom);  %计算路线长度
preObjV=min(ObjV);
while gen<MAXGEN
    %% 计算适应度
    ObjV=PathLength(D,Chrom);  %计算路线长度
    % fprintf('%d   %1.10f\n',gen,min(ObjV))
    line([gen-1,gen],[preObjV,min(ObjV)]);pause(0.0001)
    preObjV=min(ObjV);
    FitnV=Fitness(ObjV);
    %% 选择
    SelCh=Select(Chrom,FitnV,GGAP);
    %% 交叉操作
    SelCh=Recombin(SelCh,Pc);
    %% 变异
    SelCh=Mutate(SelCh,Pm);
    %% 逆转操作
    SelCh=Reverse(SelCh,D);
    %% 重插入子代的新种群
    Chrom=Reins(Chrom,SelCh,ObjV);
    %% 更新迭代次数
    gen=gen+1 ;
end
%% 画出最优解的路线图
ObjV=PathLength(D,Chrom);  %计算路线长度
[minObjV,minInd]=min(ObjV);
DrawPath(Chrom(minInd(1),:),X)
%% 输出最优解的路线和总距离
disp('最优解:')
p=OutputPath(Chrom(minInd(1),:));
disp(['总距离:',num2str(ObjV(minInd(1)))]);
disp('-------------------------------------------------------------')
% 计算两两城市之间的距离
function D=Distanse(a)
% 输入 a  各城市的位置坐标
% 输出 D  两两城市之间的距离
row=size(a,1);
D=zeros(row,row);
for i=1:row
    for j=i+1:row
        D(i,j)=((a(i,1)-a(j,1))^2+(a(i,2)-a(j,2))^2)^0.5;
        D(j,i)=D(i,j);
    end
end
% 输出路径函数
function p=OutputPath(R)
% 输入:R 路径
R=[R,R(1)];
N=length(R);
p=num2str(R(1));
for i=2:N
    p=[p,'—>',num2str(R(i))];
end
disp(p)
% 计算各个体的路径长度
function len=PathLength(D,Chrom)
% 输入:
%   D     两两城市之间的距离
%   Chrom 个体的轨迹
[row,col]=size(D);
NIND=size(Chrom,1);
len=zeros(NIND,1);
for i=1:NIND
    p=[Chrom(i,:) Chrom(i,1)];
    i1=p(1:end-1);
    i2=p(2:end);
    len(i,1)=sum(D((i1-1)*col+i2));
end
%重插入子代的新种群
function Chrom=Reins(Chrom,SelCh,ObjV)
% 输入:
%   Chrom  父代的种群
%   SelCh  子代种群
%   ObjV   父代适应度
% 输出
%   Chrom  组合父代与子代后得到的新种群
NIND=size(Chrom,1);
NSel=size(SelCh,1);
[TobjV,index]=sort(ObjV);
Chrom=[Chrom(index(1:NIND-NSel),:);SelCh];
function varargout = dsxy2figxy(varargin)
if length(varargin{1}) == 1 && ishandle(varargin{1}) ...
                            && strcmp(get(varargin{1},'type'),'axes')   
    hAx = varargin{1};
    varargin = varargin(2:end);
else
    hAx = gca;
end;
if length(varargin) == 1
    pos = varargin{1};
else
    [x,y] = deal(varargin{:});
end
axun = get(hAx,'Units');
set(hAx,'Units','normalized'); 
axpos = get(hAx,'Position');
axlim = axis(hAx);
axwidth = diff(axlim(1:2));
axheight = diff(axlim(3:4));
if exist('x','var')
    varargout{1} = (x - axlim(1)) * axpos(3) / axwidth + axpos(1);
    varargout{2} = (y - axlim(3)) * axpos(4) / axheight + axpos(2);
else
    pos(1) = (pos(1) - axlim(1)) / axwidth * axpos(3) + axpos(1);
    pos(2) = (pos(2) - axlim(3)) / axheight * axpos(4) + axpos(2);
    pos(3) = pos(3) * axpos(3) / axwidth;
    pos(4) = pos(4) * axpos(4 )/ axheight;
    varargout{1} = pos;
end
set(hAx,'Units',axun)
function DrawPath(Chrom,X)
% 输入
%   Chrom  待画路径   
%   X      各城市坐标位置

R=[Chrom(1,:) Chrom(1,1)]; % 一个随机解(个体)
figure;
hold on
plot(X(:,1),X(:,2),'o','color',[0.5,0.5,0.5])
plot(X(Chrom(1,1),1),X(Chrom(1,1),2),'rv','MarkerSize',20)
for i=1:size(X,1)
    text(X(i,1)+0.05,X(i,2)+0.05,num2str(i),'color',[1,0,0]);
end
A=X(R,:);
row=size(A,1);
for i=2:row
    [arrowx,arrowy] = dsxy2figxy(gca,A(i-1:i,1),A(i-1:i,2));  % 坐标转换
    annotation('textarrow',arrowx,arrowy,'HeadWidth',8,'color',[0,0,1]);
end
hold off
xlabel('横坐标')
ylabel('纵坐标')
title('轨迹图')
box on

10.结果

初始种群中的一个随机值:
2—>8—>14—>1—>10—>12—>5—>6—>11—>3—>7—>13—>9—>4—>2
总距离:63.9542
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最优解:
14—>3—>4—>5—>6—>12—>7—>13—>8—>11—>9—>10—>1—>2—>14
总距离:29.3405
----------------------------------------------------------------

 

5 多种群遗传算法的函数优化

未成熟收敛:

      表现:群体中所有个体都趋于同一状态而停止进化,算法得不到令人满意的结果

      问题:传统GA通常采用轮盘赌选择、单点交叉、位点变异

  1. 当种群中存在个别超常个体(适应度函数值远远高于其他个体)时,该个体在选择算子作用下,将会被多次选中,下一代群体很快被该个体控制,群体失去竞争性,导致群体停滞不前,陷入局部最优
  2. 交叉和变异的概率变化:全局搜索能力和局部搜索能力的均衡
  3. 群体规模:群体规模小,多样性差,个体间竞争弱,随着进化的进行,群体很快出现单一化,群体更新只能靠变异操作;群体规模大,计算量增加,计算效率不高
  4. 终止依据:迭代次数。次数少,进化不充分

多种群遗传算(Multiple Population Genetic Algorithm,MPGA)

  1. 引入多个种群同时优化搜索,不同的种群以不同的控制参数,实现不同的搜索目的
  2. 多种群间通过移民算子联系,实现多种群的协同进化
  3. 通过人工选择算子保存各种群每代中的最优个体,并作为算法收敛的依据

二元函数求最值

                                       

移民算子

 变量名类型说明
输入参数ChromCell每个元胞单元为一个种群的编码
ObjVCell每个元胞为一个种群所有个体的目标值
输出参数ChromCell每个元胞单元为一个种群的编码
ObjVCell每个元胞为一个种群所有个体的目标值
%移民算子
function [Chrom,ObjV]=immigrant(Chrom,ObjV)
MP=length(Chrom);
for i=1:MP
    [MaxO,maxI]=max(ObjV{i});  % 找出第i种群中最优的个体
    next_i=i+1;                % 目标种群(移民操作中)
    if next_i>MP;next_i=mod(next_i,MP);end
    [MinO,minI]=min(ObjV{next_i});          %  找出目标种群中最劣的个体
    % 目标种群最劣个体替换为源种群最优个体
    Chrom{next_i}(minI,:)=Chrom{i}(maxI,:);
    ObjV{next_i}(minI)=ObjV{i}(maxI);
end

人工选择算子

 变量名类型说明
输入参数ChromCell每个元胞单元为一个种群的编码
ObjVCell每个元胞为一个种群所有个体的目标值
MaxObjVDouble各个种群当前最优个体的目标值
MaxChromDouble各个种群当前最优个体的编码
输出参数MaxObjVDouble各个种群当前最优个体的目标值
MaxChromDouble各个种群当前最优个体的编码
% 人工选择算子
function [MaxObjV,MaxChrom]=EliteInduvidual(Chrom,ObjV,MaxObjV,MaxChrom)
MP=length(Chrom);  % 种群数
for i=1:MP
    [MaxO,maxI]=max(ObjV{i});    % 找出第i种群中最优个体
    if MaxO>MaxObjV(i)
        MaxObjV(i)=MaxO;         % 记录各种群的精华个体
        MaxChrom(i,:)=Chrom{i}(maxI,:);  % 记录各种群精华个体的编码
    end
end

目标函数

function obj=ObjectFunction(X)
% X的每行为一个个体
col=size(X,1);
for i=1:col
    obj(i,1)=21.5+X(i,1)*sin(4*pi*X(i,1))+X(i,2)*sin(20*pi*X(i,2));
end

主函数

    多种群遗传:

clear;
clc
close all
NIND=40;               % 个体数目
NVAR=2;                % 变量的维数
PRECI=20;              % 变量的二进制位数
GGAP=0.9;              % 代沟
MP=10;                 % 种群数目
FieldD=[rep(PRECI,[1,NVAR]);[-3,4.1;12.1,5.8];rep([1;0;1;1],[1,NVAR])];  % 译码矩阵
for i=1:MP
    Chrom{i}=crtbp(NIND, NVAR*PRECI);                       % 创建初始种群
end
pc=0.7+(0.9-0.7)*rand(MP,1);       % 在【0.7,0.9】范围内随机产生交叉概率
pm=0.001+(0.05-0.001)*rand(MP,1);  % 在【0.001,0.05】范围内随机产生变异概率
gen=0;      % 初始遗传代数
gen0=0;     % 初始保持代数
MAXGEN=10;  % 最优个体最少保持代数
maxY=0;     % 最优值
for i=1:MP
    ObjV{i}=ObjectFunction(bs2rv(Chrom{i}, FieldD));  % 计算各初始种群个体的目标函数值
end
MaxObjV=zeros(MP,1);           % 记录精华种群
MaxChrom=zeros(MP,PRECI*NVAR); % 记录精华种群的编码
while gen0<=MAXGEN
    gen=gen+1;       % 遗传代数加1
    for i=1:MP
        FitnV{i}=ranking(-ObjV{i});                      % 各种群的适应度
        SelCh{i}=select('sus', Chrom{i}, FitnV{i},GGAP); % 选择操作
        SelCh{i}=recombin('xovsp',SelCh{i}, pc(i));      % 交叉操作
        SelCh{i}=mut(SelCh{i},pm(i));                    % 变异操作
        ObjVSel=ObjectFunction(bs2rv(SelCh{i}, FieldD)); % 计算子代目标函数值
        [Chrom{i},ObjV{i}]=reins(Chrom{i},SelCh{i},1,1,ObjV{i},ObjVSel); % 重插入操作
    end
    [Chrom,ObjV]=immigrant(Chrom,ObjV);     % 移民操作
    [MaxObjV,MaxChrom]=EliteInduvidual(Chrom,ObjV,MaxObjV,MaxChrom);     % 人工选择精华种群
    YY(gen)=max(MaxObjV);    % 找出精华种群中最优的个体
    if YY(gen)>maxY   % 判断当前优化值是否与前一次优化值相同
        maxY=YY(gen); % 更新最优值
        gen0=0;
    else
        gen0=gen0+1;  % 最优值保持次数加1
    end
end
%% 进化过程图
plot(1:gen,YY)
xlabel('进化代数')
ylabel('最优解变化')
title('进化过程')
xlim([1,gen])
%% 输出最优解
[Y,I]=max(MaxObjV);    %找出精华种群中最优的个体
X=(bs2rv(MaxChrom(I,:), FieldD));   %最优个体的解码解
disp(['最优值为:',num2str(Y)])
disp(['对应的自变量取值:',num2str(X)])

    标准遗传:

clear
clc
pc=0.7;
pm=0.05;
% 定义遗传算法参数
NIND=40;        % 个体数目
MAXGEN=500;     % 最大遗传代数
NVAR=2;         % 变量的维数
PRECI=20;       % 变量的二进制位数
GGAP=0.9;       % 代沟
trace=zeros(MAXGEN,1);
FieldD=[rep(PRECI,[1,NVAR]);[-3,4.1;12.1,5.8];rep([1;0;1;1],[1,NVAR])];  % 建立区域描述器
Chrom=crtbp(NIND, NVAR*PRECI);                       % 创建初始种群
gen=0;                                               % 代计数器   
maxY=0; % 最优值
ObjV=ObjectFunction(bs2rv(Chrom, FieldD));           % 计算初始种群个体的目标函数值
while gen<MAXGEN                                     % 迭代
    FitnV=ranking(-ObjV);                            % 分配适应度值(Assign fitness values)
    SelCh=select('sus', Chrom, FitnV, GGAP);         % 选择
    SelCh=recombin('xovsp', SelCh, pc);              % 重组
    SelCh=mut(SelCh,pm);                             % 变异
    ObjVSel=ObjectFunction(bs2rv(SelCh, FieldD));           % 计算子代目标函数值
    [Chrom ObjV]=reins(Chrom, SelCh, 1, 1, ObjV, ObjVSel);  % 重插入
    gen=gen+1;           % 代计数器增加
    if maxY<max(ObjV)
        maxY=max(ObjV);
    end
    trace(gen,1)=maxY;
end

%% 进化过程图
plot(1:gen,trace(:,1));

%% 输出最优解
[Y,I]=max(ObjV);
X=bs2rv(Chrom, FieldD);
disp(['最优值为:',num2str(Y)])
disp(['对应的自变量取值:',num2str(X(I,:))])

结果

 

 

6.基于遗传算法的多目标优化

Pareto最优解(Pareto optima):某一目标函数的提高需要以另一个目标函数的降低为代价

 

带精英策略的快速非支配排序遗传算法(Nondominated Sorting Genetic Algorithm II, NSGA-II)

概念:

  1. 支配(dominate)、非劣(non-inferior):若个体p至少有一个目标必个体q好,且个体p的所有目标都不必个体q的差,则个体p支配个体q,个体p非劣与个体q
  2. 序值(rank)、前端(front):如果个体p支配个体q,则个体p的序值比个体q的序值低;如果个体p和q互不支配,则p和q拥有相同序值。序值为1的个体属于第一前端,序值为2的个体属于第二前端,以此类推。显然,在当前种群中,第一前端是完全不受支配的,第二前端受第一前端中个体的支配。通过排序,可以将种群中的个体分到不同的前端
  3. 拥挤距离(Crowding Distance):计算某前端中的某个体与该前端中其他个体之间的距离,用以表征个体间的拥挤程度。显然拥挤距离的值越大,个体间就越不拥挤,种群的多样性就越好。需要注意,只有处于同一前端的个体间才需要计算拥挤距离,不同前端之间的个体计算拥挤距离是没有意义的
  4. 最优前端个体系数(ParetoFraction):最优前端中的个体在种群中所占的比例

通过GUI方式调用gamultiobj

optimtool('gamultiobj')

通过命令行方式调用gamultiobj

[x,fval] = gamultiobj(fitnessfcn, nvars, A, b, Aeq, beq, lb, ub, options)

 

选择:stepgamultiobj

function parents = selectiontournament(expectation,nParents,options,tournamentSize)
%SELECTIONTOURNAMENT Each parent is the best of a random set.
%   PARENTS = SELECTIONTOURNAMENT(EXPECTATION,NPARENTS,OPTIONS,TOURNAMENTSIZE)
%   chooses the PARENTS by selecting the best TOURNAMENTSIZE players out of
%   NPARENTS with EXPECTATION and then choosing the best individual
%   out of that set.
%
%   Example:
%   Create an options structure using SELECTIONTOURNAMENT as the selection
%   function and use the default TOURNAMENTSIZE of 4
%     options = optimoptions('ga','SelectionFcn',@selectiontournament);
%
%   Create an options structure using SELECTIONTOURNAMENT as the
%   selection function and specify TOURNAMENTSIZE to be 3.
%
%     tournamentSize = 3;
%     options = optimoptions('ga','SelectionFcn', ...
%               {@selectiontournament, tournamentSize});
%
%   (Note: If calling gamultiobj, replace 'ga' with 'gamultiobj')

%   Copyright 2003-2017 The MathWorks, Inc.

% How many players in each tournament?
if nargin < 4 || isempty(tournamentSize)
    tournamentSize = 4;
end

% Choose the players
playerlist = ceil(size(expectation,1) * rand(nParents,tournamentSize));
% Play tournament
parents = tournament(playerlist,expectation);

function champions = tournament(playerlist,expectation)
%tournament between players based on their expectation

playerSize = size(playerlist,1);
champions = zeros(1,playerSize);
% For each set of players
for i = 1:playerSize
    players = playerlist(i,:);
    % For each tournament
    winner = players(1); % Assume that the first player is the winner
    for j = 2:length(players) % Winner plays against each other consecutively
        score1 = expectation(winner,:);
        score2 = expectation(players(j),:);
        if score2(1) > score1(1)
            winner = players(j);
        elseif score2(1) == score1(1) && ... % score(1) is an integer rank
                (length(score1) > 1 && score2(2) > score1(2))
            % socre(2) may not be present for single objective problems
            winner = players(j);
        end
    end
    champions(i) = winner;
end
% 锦标赛选择函数
function parents = selectiontournament(expectation, nParents, options, tournamentSize)
% 输入
%   expectation 在函数 stepgamultiobj 中赋值,赋值为[-rank,Distance]

% 函数 gamultiobj 将 tournamentSize 默认赋值为2
if nargin<4 || isempty(tournamentSize)
    tournamentSize = 4;
end

playerlist = ceil(size(expectation,1)) * rand(nParents, tournamentSize);
% 产生 nParents 行 tournamentSize 矩阵,其元素为 [0,size(expectation,1)] 间的整数
% 选择操作是锦标赛,该矩阵可理解为运动员名单,该名单有 nParents 组,每组有 tournamentSize 个运动员
parents = tournament(playerlist, expectation);


function champions = tournament(playerlist,expectation)
playerSize = size(playerlist,1);
champions = zeros(1,playerSize);

for i=1:playerSize
    players = playerlist(i,:);
    winner = players(1);
    for j=2:length(players)
        score1 = expectation(winner,:);     % 第一个运动员成绩
        score2 = expectation(players(j),:); % 第 j 个运动员成绩
        if score2(1) > score1(1)
            winner = players(j);  % 序值小的获胜
        elseif score2(1) == score1(1)
            try
                if score2(2) > score1(2)  % 序值相同,拥挤距离大的获胜
                   winner = players(j);
                end
            catch
            end
        end
    end
    champions(i) = winner;
end

交叉、变异、产生子种群、父子种群合并

nextPopulation = [xoverKids,mutateKids]  % 生成子种群
nextPopulation = [eliteKids,xoverKids,mutateKids]  % 生成子种群

population = [population,nextPopulation]  %合并父子种群

计算序值和拥挤距离

% 非适配排序函数
function nondominatedRank = nonDominatedRank(score, nParent)
popSize = size(score,1);  % 计算需要排序的个体数目
if nargin < 2
    nParent = popSize;
end
rankedIndiv = false(popSize,1);    % 表征个体是否已经被赋予序值的矩阵,默认每个个体都没排序
nondominatedRank = inf(popSize,1); % 函数返回的序值矩阵,初始序值为inf
rankCounter = 1;                   % 序值从1开始,依次加1

while ~all(rankedIndiv) && nnz(isfinite(nondominatedRank))<=nParent
    front = false(popSize,1);
    for p=1:popSize  % 对每个个体排序
        if rankedIndiv(p)  % 已经排序的跳出循环
            continue;
        end
        dominates = true;  % 表征某个体是否被支配
        for q=1:popSize    % 个体p依次与个体q比较
            if rankedIndiv(q) || p==q  % 个体q已排序或p,q为同一体,跳出循环
                continue;
            end
            if any(score(q,:)<score(p,:)) && all(score(q,:)<=score(p,:))  % 检查个体q是否支配个体p
                dominates = false;  % 个体q支配个体p,标志dominates位false
                break;
            end
        end
        if dominates
            nondominatedRank(p) = rankCounter;  % 个体p序值为true,则将当前序值 rankCounter赋予个体p,个体p被排序
            front(p) = true;  % 个体p序值为默认的inf,要等到下一个rnakCounter再被赋予序值
        end
    end
    rankedIndiv(front) = true;   % 更新 rankCounter
    rankCounter = rankCounter+1;
end
function crowdingDistance = distancecrowding(pop,score,~,space)
%DISTANCECROWDING Assign local crowding distance to each individual
%   CROWDINGDISTANCE = DISTANCECROWDING(POP,SCORE,OPTIONS,SPACE) Calculates
%   crowding distance for each individuals on a non-dominated front. The
%   fourth argument SPACE can be 'phenotype' or 'genotype' for distance to
%   be in function space or decision variable space respectively.
%
%   Example:
%   Create an options structure using DISTANCECROWDING as the distance
%   function in decision variable space
%     options = optimoptions('gamultiobj','DistanceMeasureFcn',{@distancecrowding,'genotype'}); 

%   Reference: Kalyanmoy Deb, "Multi-Objective Optimization using
%   Evolutionary Algorithms", John Wiley & Sons ISBN 047187339, pg: 245 -
%   253

%   Copyright 2007-2015 The MathWorks, Inc.

if nargin < 4
    space = 'phenotype';
end

% Score should be finite to work with 'phenotype' distance 
if strcmpi(space,'phenotype') && nnz(~isfinite(score)) == 0
    y = score;
else % if strcmpi(space,'genotype')
    y = pop;
end

popSize = size(y,1);
numData = size(y,2);
crowdingDistance = zeros(popSize,1);

for m = 1:numData
    data = y(:,m);
    % Normalize obective before computing distance
    data = data./(1 + max(abs(data(isfinite(data)))));
    [sorteddata,index] = sort(data);
    % The best and worst individuals are at the end of Pareto front and
    % they are assigned Inf distance measure
    crowdingDistance([index(1),index(end)]) = Inf;
    % Distance measure of remaining individuals
    i = 2;
    while i < popSize
        crowdingDistance(index(i)) = crowdingDistance(index(i)) + ...
            min(Inf, (data(index(i+1)) - data(index(i-1))));
        i = i+1;
    end
end
function [pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas] = ...
    trimPopulation(pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas, ...
                   maxLinInfeas,popSize,nScore,nParents,ParetoFraction)
%trimPopulation Trim population to get nParents with specified distribution
%among all fronts

%   Copyright 2007-2014 The MathWorks, Inc.


if nScore > 1 % front diversity make sense for multi-objective
    [pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas,popSize] =  ...
        frontDiversity(pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas, ...
                       maxLinInfeas,popSize,nParents,ParetoFraction);
end
% trim individuals to nParents size based on distance
[pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas] = distanceDiversity( ...
    pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas,nParents,popSize);

%-------------------------------------------------------------
function [pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas] = distanceDiversity( ...
                pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas,nParents,popSize)
% Remove indivduals from last front if length(nonDomRank) is greater than nParents
to_remove = length(nonDomRank) - nParents;
if to_remove > 0
    [~,I] = sortrows([nonDomRank, crowdingDistance],[1,-2]);
    indiv_to_remove = I(popSize:-1:(popSize - to_remove + 1));
    pop(indiv_to_remove,:) = [];
    score(indiv_to_remove,:) = [];
    nonDomRank(indiv_to_remove) = [];
    crowdingDistance(indiv_to_remove) = [];
    c(indiv_to_remove,:) = [];
    ceq(indiv_to_remove,:) = [];
    isFeas(indiv_to_remove) = [];
    maxLinInfeas(indiv_to_remove) = [];
end

%-------------------------------------------------------------------------------
function [pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas,popSize] = ...
    frontDiversity(pop,score,nonDomRank,crowdingDistance,c,ceq,isFeas,maxLinInfeas, ...
                   popSize,nParents,ParetoFraction)
    
numRank = unique(nonDomRank); % numRank will be sorted
% Trim front size based on a pre-determined count
totalNumOfRank = length(numRank);
retainIndiv = zeros(totalNumOfRank,1); % Individuals to be retained in each front
availableIndiv = zeros(totalNumOfRank,1); % Available individuals in each front

% First rank is treated differently for number of desired individuals
availableIndiv(1) = nnz(nonDomRank == 1);
allowedIndiv = ceil(nParents*ParetoFraction);
if allowedIndiv <= availableIndiv(1)
    retainIndiv(1) = allowedIndiv;
else
    retainIndiv(1) =  availableIndiv(1);
end

% If there are more than one fronts then we calculate the maximum number of
% individuals we can retain
if totalNumOfRank > 1
    gpRatio = 0.8; % Geometric progression ratio
    carryover = 0;
    for i = numRank(2:end)'
        availableIndiv(i) = nnz(nonDomRank == i);
        % allowedIndiv redcuces as geometric progression
        allowedIndiv = ceil(nParents*gpRatio^(i-1)*((1-gpRatio)/(1-gpRatio^totalNumOfRank))) + carryover;
        if allowedIndiv <= availableIndiv(i)
            retainIndiv(i) = allowedIndiv;
        else
            retainIndiv(i) =  availableIndiv(i);
            carryover = allowedIndiv - availableIndiv(i);
        end
    end
end

% Adjust retainIndiv if required
front = totalNumOfRank; increase = 0.10;
while sum(retainIndiv) <= ceil(nParents)
    if retainIndiv(front) < availableIndiv(front)
        retainIndiv(front) = min(availableIndiv(front),ceil(retainIndiv(front)*(1+increase)));
        increase = increase*0.95;
    end
    if front == 1
        front = totalNumOfRank;
        increase = 0.10;
    else
        front = front - 1;
    end
end

for i = numRank'
   popIndices = 1:popSize;
   index = (nonDomRank == i);
   if retainIndiv(i) < nnz(index)   % We need to trim the front
       if retainIndiv(i) == 0
           continue;
       end
       % Select individuals after a tournament selection
       % Choose the players for each round
       playerlist = popIndices(index);
       losers = tournament(playerlist,crowdingDistance,retainIndiv(i)); 
       pop(losers,:) = [];
       score(losers,:) = [];
       nonDomRank(losers) = [];
       crowdingDistance(losers) = [];
       c(losers,:) = [];
       ceq(losers,:) = [];
       isFeas(losers) = [];
       maxLinInfeas(losers) = [];
       popSize = size(score,1);
   else
       % No need to modify the front; do nothing
   end
end

%-------------------------------------------------------------
function losers = tournament(playerlist,expectation,allowed)
%tournament between players based on their distance values

[~,sortedIndex] = sort(expectation(playerlist),'descend');
losers = playerlist(sortedIndex(allowed+1:end));

 

7. 基于多层编码遗传算法的车间调度

对于较为复杂的优化问题,染色体难以充分表达问题的解。多层编码把个体编码分为多层,每层含义不同,多层编码共同完整表达了问题的解,从而用一条染色体准确表达复杂问题的解。

车间调度是指根据产品制造的合理需求分配加工车间顺序,从而达到合理产生产品制造资源,提高企业经济效益的目的

1.个体编码

    染色体对应工件的加工顺序,染色体前半部分表示所有工件在机器上的加工顺序,后半部分表示工件每道工序的加工机器序号

2.适应度值:时间最短,适应度值越高

function P=calp(S,PNumber)
% 功能说明:          根据基因S,计算调度工序P
% 输入参数:
%        S           为基因  
%        PNumber     为工件个数 
% 输出参数: 
%        P           为输出的调度工序 
%                    比如数字1002表示工件10的工序03

WNumber=length(S);%工序总个数
WNumber=WNumber/2;

%取工序基因,取基因的一半
S=S(1,1:WNumber);

%初始化
temp=zeros(1,PNumber);
P=zeros(1,WNumber);

%解码生成调度工序
for i=1: WNumber 
    
   %工序加+1
  temp(S(i))=temp(S(i))+1; 
  
  P(i)=S(i)*100+temp(S(i));
  
end
function PVal=caltime(S,P,JmNumber,T,Jm)
% 功能说明:    根据调度工序,计算出调度工序时间
% 输入参数:
%        P     为调度工序  
%        JmNumber    为机器个数
%        T     为各工件各工序的加工时间 
%        Jm    为各工件各工序使用的机器 
% 输出参数:
%        PVal  为调度工序开始加工时间及完成时间


%  工件个数 工序个数 
[PNumber MNumber]=size(Jm);

%取机器基因,取基因的一半
 M=S(1,PNumber*MNumber+1:PNumber*MNumber*2); 
 
%工序总个数
WNumber=length(P);

%初始化
TM=zeros(1,JmNumber);
TP=zeros(1,PNumber);
PVal=zeros(2,WNumber);

%计算调度工序时间
for i=1: WNumber 
    
    % 取机器号
    val= P(1,i);
    a=(mod(val,100)); %工序
    b=((val-a)/100);  %工件
    Temp=Jm{b,a};
    m=Temp(M(1,i));
    
    %取加工时间
    Temp=T{b,a};
    t=Temp(M(1,i));
    
    %取机器加工本工序的开始时间和前面一道工序的完成时间
    TMval=TM(1,m);
    TPval=TP(1,b); 
    
    %机器加工本工序的开始时间 大于前面一道工序的完成时 ,取机器加工本工序的开始时间
    if TMval>TPval 
        val=TMval;
     %取前面一道工序的完成时间  
    else
        val=TPval;
    end
    
    %计算时间
    PVal(1,i)=val;
    PVal(2,i)=val+t;
    
    %记录本次工序的机器时间和工序时间
    TM(1,m)=PVal(2,i);
    TP(1,b)=PVal(2,i); 
end

 

3.选择操作:轮盘赌

  

% SELECT.M          (universal SELECTion)
%
% This function performs universal selection. The function handles
% multiple populations and calls the low level selection function
% for the actual selection process.

%
% Syntax:  SelCh = select(SEL_F, Chrom, FitnV, GGAP, SUBPOP)
%
% Input parameters:
%    SEL_F     - Name of the selection function
%    Chrom     - Matrix containing the individuals (parents) of the current
%                population. Each row corresponds to one individual.
%    FitnV     - Column vector containing the fitness values of the
%                individuals in the population.
%    GGAP      - (optional) Rate of individuals to be selected
%                if omitted 1.0 is assumed
%    SUBPOP    - (optional) Number of subpopulations
%                if omitted 1 subpopulation is assumed
%
% Output parameters:
%    SelCh     - Matrix containing the selected individuals.

% Author:     Hartmut Pohlheim
% History:    10.03.94     file created

function SelCh = select(SEL_F, Chrom, FitnV, GGAP, SUBPOP);

% Check parameter consistency
   if nargin < 3, error('Not enough input parameter'); end

   % Identify the population size (Nind)
   [NindCh,Nvar] = size(Chrom);
   [NindF,VarF] = size(FitnV);
   if NindCh ~= NindF, error('Chrom and FitnV disagree'); end
   if VarF ~= 1, error('FitnV must be a column vector'); end
  
   if nargin < 5, SUBPOP = 1; end
   if nargin > 4,
      if isempty(SUBPOP), SUBPOP = 1;
      elseif isnan(SUBPOP), SUBPOP = 1;
      elseif length(SUBPOP) ~= 1, error('SUBPOP must be a scalar'); end
   end

   if (NindCh/SUBPOP) ~= fix(NindCh/SUBPOP), error('Chrom and SUBPOP disagree'); end
   Nind = NindCh/SUBPOP;  % Compute number of individuals per subpopulation

   if nargin < 4, GGAP = 1; end
   if nargin > 3,
      if isempty(GGAP), GGAP = 1;
      elseif isnan(GGAP), GGAP = 1;
      elseif length(GGAP) ~= 1, error('GGAP must be a scalar');
      elseif (GGAP < 0), error('GGAP must be a scalar bigger than 0'); end
   end

% Compute number of new individuals (to select)
   NSel=max(floor(Nind*GGAP+.5),2);

% Select individuals from population
   SelCh = [];
   for irun = 1:SUBPOP,
      FitnVSub = FitnV((irun-1)*Nind+1:irun*Nind);
      ChrIx=feval(SEL_F, FitnVSub, NSel)+(irun-1)*Nind;
      SelCh=[SelCh; Chrom(ChrIx,:)];
   end
 

% End of function

selectJm

function SelS=selectJm(S,S_T)

Num=length(S_T);

MaxVal=0;
for i=1:Num
  if S_T(i)>MaxVal;
   MaxVal=S_T(i);
  end
end
MaxVal=2*MaxVal;

for i=1:Num
 S_T(i)=MaxVal-S_T(i);
end

eVal=0;
for i=1:Num
 eVal=eVal+S_T(i);
end

for i=1:Num
 P(i)=S_T(i)/eVal;
end

for i=2:Num
  P(i)=P(i)+P(i-1);
end

 num=rand;
 SelS=1;
 while(num>P(SelS))
     SelS=SelS+1;    
 end

 

4.交叉操作

    

function NewChrom=across(Chrom,XOVR,Jm,T)
% Chrom=[1 3 2 3 1 2 1 3 2; 
%     1 1 2 3 3 1 2 3 2;
%     1 3 2 3 2 2 1 3 1;
%     1 3 3 3 1 2 1 2 2;
% ]; 
%   XOVR=0.7;

[NIND,WNumber]=size(Chrom);
WNumber=WNumber/2;
NewChrom=Chrom;%初始化新种群

[PNumber MNumber]=size(Jm);
Number=zeros(1,PNumber);
for i=1:PNumber
  Number(i)=1;
end

%随机选择交叉个体(洗牌交叉)
SelNum=randperm(NIND);   

Num=floor(NIND/2);%交叉个体配对数
for i=1:2:Num
    if XOVR>rand; 
        Pos=unidrnd(WNumber);%交叉位置
        while Pos==1
            Pos=unidrnd(WNumber);
        end
        %取两交叉的个体
        S1=Chrom(SelNum(i),1:WNumber);
        S2=Chrom(SelNum(i+1),1:WNumber); 
        S11=S2;S22=S1; %初始化新的个体     
        %新个体中间片断的COPY      
        S11(1:Pos)=S1(1:Pos);      
        S22(1:Pos)=S2(1:Pos);        
        %比较S11相对S1,S22相对S2多余和缺失的基因
        S3=S11;S4=S1;
        S5=S22;S6=S2;
        for j=1:WNumber         
           Pos1=find(S4==S3(j),1);
           Pos2=find(S6==S5(j),1);
           if Pos1>0
               S3(j)=0;
               S4(Pos1)=0;
           end                         
           if Pos2>0
               S5(j)=0;
               S6(Pos2)=0;
           end
        end
        for j=1:WNumber          
          if S3(j)~=0 %多余的基因          
            Pos1=find(S11==S3(j),1);        
            Pos2=find(S4,1);%查找缺失的基因
            S11(Pos1)=S4(Pos2);%用缺失的基因修补多余的基因
            S4(Pos2)=0;       
          end 
          if S5(j)~=0              
            Pos1=find(S22==S5(j),1); 
            Pos2=find(S6,1);           
            S22(Pos1)=S6(Pos2);
            S6(Pos2)=0;          
          end  
        end                         

        % 保存交叉前的机器 基因
        S1=Chrom(SelNum(i),:);
        S2=Chrom(SelNum(i+1),:); 
       
        for k=1:WNumber            
            Pos1=Find(S11(k),S1);           
            S11(WNumber+k)=S1(WNumber+Pos1);
            S1(Pos1)=0;
            
            Pos1=Find(S22(k),S2);           
            S22(WNumber+k)=S2(WNumber+Pos1);
            S2(Pos1)=0;
        end
          
        %生成新的种群
        NewChrom(SelNum(i),:)=S11;
        NewChrom(SelNum(i+1),:)=S22;
    end
 end

5.变异操作

    

main

%% 清空环境
clc;clear

%% 下载数据
load scheduleData Jm T JmNumber
%工序 时间

%% 基本参数
NIND=40;        %个体数目
MAXGEN=50;      %最大遗传代数
GGAP=0.9;       %代沟
XOVR=0.8;       %交叉率
MUTR=0.6;       %变异率
gen=0;          %代计数器
%PNumber 工件个数 MNumber  工序个数
[PNumber MNumber]=size(Jm);  
trace=zeros(2, MAXGEN);      %寻优结果的初始值
WNumber=PNumber*MNumber;     %工序总个数

%% 初始化
Number=zeros(1,PNumber);     % PNumber 工件个数
for i=1:PNumber
    Number(i)=MNumber;         %MNumber工序个数
end

% 代码2层,第一层工序,第二层机器
Chrom=zeros(NIND,2*WNumber);
for j=1:NIND
    WPNumberTemp=Number;
    for i=1:WNumber
        
        %随机产成工序
        val=unidrnd(PNumber);
        while WPNumberTemp(val)==0
            val=unidrnd(PNumber);
        end
        
        %第一层代码表示工序
        Chrom(j,i)= val;
        WPNumberTemp(val)=WPNumberTemp(val)-1;
        
        %第2层代码表示机器
        Temp=Jm{val,MNumber-WPNumberTemp(val)};
        SizeTemp=length(Temp);
        %随机产成工序机器
        Chrom(j,i+WNumber)= unidrnd(SizeTemp);
        
    end
end
 
%计算目标函数值
[PVal ObjV P S]=cal(Chrom,JmNumber,T,Jm);  

%% 循环寻找
while gen<MAXGEN
    
    %分配适应度值
    FitnV=ranking(ObjV);  
    %选择操作
    SelCh=select('rws', Chrom, FitnV, GGAP);       
    %交叉操作
    SelCh=across(SelCh,XOVR,Jm,T);          
    %变异操作
    SelCh=aberranceJm(SelCh,MUTR,Jm,T);            
    
    %计算目标适应度值
    [PVal ObjVSel P S]=cal(SelCh,JmNumber,T,Jm);   
    %重新插入新种群
    [Chrom ObjV] =reins(Chrom, SelCh,1, 1, ObjV, ObjVSel);       
    %代计数器增加
    gen=gen+1;       
    
    %保存最优值
    trace(1, gen)=min(ObjV);       
    trace(2, gen)=mean(ObjV);  
    
    % 记录最佳值
    if gen==1
        Val1=PVal;
        Val2=P;
        MinVal=min(ObjV);%最小时间
        STemp=S;
    end
    %记录 最小的工序
    if MinVal> trace(1,gen)
        Val1=PVal;
        Val2=P;
        MinVal=trace(1,gen);
        STemp=S;
    end
    
end

% 当前最佳值
PVal=Val1; %工序时间
P=Val2;  %工序 
S=STemp; %调度基因含机器基因

%% 描绘解的变化
figure(1)
plot(trace(1,:));
hold on;
plot(trace(2,:),'-.');grid;
legend('解的变化','种群均值的变化');

%% 显示最优解
figure(2);
MP=S(1,PNumber*MNumber+1:PNumber*MNumber*2);
for i=1:WNumber  
    val= P(1,i);
    a=(mod(val,100)); %工序
    b=((val-a)/100); %工件
    Temp=Jm{b,a};
    mText=Temp(MP(1,i));
    
    x1=PVal(1,i);
    x2=PVal(2,i);
    
    y1=mText-1;
    y2=mText;
    plotRec(x1,x2,mText);
    
    plotRec(PVal(1,i),PVal(2,i),mText);
    hold on;
    
    fill([x1,x2,x2,x1],[y1,y1,y2,y2],[1-1/b,1/b,b/PNumber]);
    text((x1+x2)/2,mText-0.25,num2str(P(i)));
end

aberranceJm

function ChromNew=aberranceJm(Chrom,MUTR,Jm,T)

%初始化
[NIND,WNumber]=size(Chrom);
WNumber=WNumber/2;

ChromNew=Chrom;

[PNumber MNumber]=size(Jm);
Number=zeros(1,PNumber);
for i=1:PNumber
  Number(i)=1;
end

for i=1:NIND    
                
    %取一个个体
    S=Chrom(i,:);
            
       WPNumberTemp=Number; 
        
       for j=1:WNumber
           
          JMTemp=Jm{S(j), WPNumberTemp(S(j))};
          SizeTemp=length(JMTemp);
          
            %是否变异
          if MUTR>rand;
              
%               选择机器(随机选择)
%                S(j+WNumber)=unidrnd(SizeTemp); 
          
                %选择机器( 加工时间少的选择几率大)
                if SizeTemp==1      
                       S(j+WNumber)=1;
                else
                    S(j+WNumber)=selectJm(S(j++WNumber),T{S(j),WPNumberTemp(S(j))});
                end
          end
          
            WPNumberTemp(S(j))=WPNumberTemp(S(j))+1;
        end         
   
  
    %数据放入新群
    ChromNew(i,:)=S;
end

cal

function [PVal ObjV P S]=cal(Chrom,JmNumber,T,Jm)
% 功能说明:       根据基因群,计算出个群中每个个体的调度工序时间,
%                 保存最小时间的调度工序和调度工序时间
% 输入参数:
%       Chrom     为基因种群  
%       T         为各工件各工序使用的时间 
%       Jm        为各工件各工序使用的机器 

% 输出参数:
%       PVal      为最佳调度工序时间 
%       P         为最佳输出的调度工序 
%       ObjV      为群中每个个体的调度工序时间
%       S         为最佳输出的调度基因

%初始化
NIND=size(Chrom,1);
ObjV=zeros(NIND,1);

%  工件个数 工序个数 
[PNumber MNumber]=size(Jm);

for i=1:NIND  
    
    %取一个个体
    S=Chrom(i,:);
    
    %根据基因,计算调度工序
    P= calp(S,PNumber);
    
    %根据调度工序,计算出调度工序时间
    PVal=caltime(S,P,JmNumber,T,Jm); 
        
    %取完成时间
    MT=max(PVal);
    TVal=max(MT);  
    
    %保存时间
    ObjV(i,1)=TVal;
    
    %初始化
    if i==1
        Val1=PVal;
        Val2=P;
        MinVal=ObjV(i,1);
        STemp=S;
    end
    
    %记录 最小的调度工序时间、最佳调度工序时间 最佳输出的调度工序
    if MinVal> ObjV(i,1)
        Val1=PVal;
        Val2=P;
        MinVal=ObjV(i,1);
        STemp=S;
    end   
end 
 
%最佳调度工序时间 最佳输出的调度工序
 PVal=Val1;
 P=Val2;
 S=STemp;

Find

function  Pos=Find(FindVal,S)
% S=[1 3 2 3 1 2 1 3 2];
% FindVal=3;

[m n]=size(S);

Pos=-1;
for i=1:n 
    if FindVal==S(i)
      Pos=i;
      break;
    end
end

PlotRec

function PlotRec(mPoint1,mPoint2,mText)

%mPoint1=10;
%mPoint2=15;
%mText=1;

vPoint =zeros(4,2);
vPoint(1,:)=[mPoint1,mText-0.5];
vPoint(2,:)=[mPoint2,mText-0.5];
vPoint(3,:)=[mPoint1,mText];
vPoint(4,:)=[mPoint2,mText];

plot([vPoint(1,1),vPoint(2,1)],[vPoint(1,2),vPoint(2,2)])
hold on;
plot([vPoint(1,1),vPoint(3,1)],[vPoint(1,2),vPoint(3,2)])
plot([vPoint(2,1),vPoint(4,1)],[vPoint(2,2),vPoint(4,2)])
plot([vPoint(3,1),vPoint(4,1)],[vPoint(3,2),vPoint(4,2)])

end 

ranking

% RANKING.M      (RANK-based fitness assignment)
%
% This function performs ranking of individuals.
%
% Syntax:  FitnV = ranking(ObjV, RFun, SUBPOP)
%
% This function ranks individuals represented by their associated
% cost, to be *minimized*, and returns a column vector FitnV
% containing the corresponding individual fitnesses. For multiple
% subpopulations the ranking is performed separately for each
% subpopulation.
%
% Input parameters:
%    ObjV      - Column vector containing the objective values of the
%                individuals in the current population (cost values).
%    RFun      - (optional) If RFun is a scalar in [1, 2] linear ranking is
%                assumed and the scalar indicates the selective pressure.
%                If RFun is a 2 element vector:
%                RFun(1): SP - scalar indicating the selective pressure
%                RFun(2): RM - ranking method
%                         RM = 0: linear ranking
%                         RM = 1: non-linear ranking
%                If RFun is a vector with length(Rfun) > 2 it contains
%                the fitness to be assigned to each rank. It should have
%                the same length as ObjV. Usually RFun is monotonously
%                increasing.
%                If RFun is omitted or NaN, linear ranking
%                and a selective pressure of 2 are assumed.
%    SUBPOP    - (optional) Number of subpopulations
%                if omitted or NaN, 1 subpopulation is assumed
%
% Output parameters:
%    FitnV     - Column vector containing the fitness values of the
%                individuals in the current population.
%                

% Author:     Hartmut Pohlheim (Carlos Fonseca)
% History:    01.03.94     non-linear ranking
%             10.03.94     multiple populations

function FitnV = ranking(ObjV, RFun, SUBPOP)

% Identify the vector size (Nind)
   [Nind,ans] = size(ObjV);

   if nargin < 2, RFun = []; end
   if nargin > 1, if isnan(RFun), RFun = []; end, end
   if prod(size(RFun)) == 2,
      if RFun(2) == 1, NonLin = 1;
      elseif RFun(2) == 0, NonLin = 0;
      else error('Parameter for ranking method must be 0 or 1'); end
      RFun = RFun(1);
      if isnan(RFun), RFun = 2; end
   elseif prod(size(RFun)) > 2,
      if prod(size(RFun)) ~= Nind, error('ObjV and RFun disagree'); end
   end

   if nargin < 3, SUBPOP = 1; end
   if nargin > 2,
      if isempty(SUBPOP), SUBPOP = 1;
      elseif isnan(SUBPOP), SUBPOP = 1;
      elseif length(SUBPOP) ~= 1, error('SUBPOP must be a scalar'); end
   end

   if (Nind/SUBPOP) ~= fix(Nind/SUBPOP), error('ObjV and SUBPOP disagree'); end
   Nind = Nind/SUBPOP;  % Compute number of individuals per subpopulation
   
% Check ranking function and use default values if necessary
   if isempty(RFun),
      % linear ranking with selective pressure 2
         RFun = 2*[0:Nind-1]'/(Nind-1);
   elseif prod(size(RFun)) == 1
      if NonLin == 1,
         % non-linear ranking
         if RFun(1) < 1, error('Selective pressure must be greater than 1');
         elseif RFun(1) > Nind-2, error('Selective pressure too big'); end
         Root1 = roots([RFun(1)-Nind [RFun(1)*ones(1,Nind-1)]]);
         RFun = (abs(Root1(1)) * ones(Nind,1)) .^ [(0:Nind-1)'];
         RFun = RFun / sum(RFun) * Nind;
      else
         % linear ranking with SP between 1 and 2
         if (RFun(1) < 1 | RFun(1) > 2),
            error('Selective pressure for linear ranking must be between 1 and 2');
         end
         RFun = 2-RFun + 2*(RFun-1)*[0:Nind-1]'/(Nind-1);
      end
   end;

   FitnV = [];

% loop over all subpopulations
for irun = 1:SUBPOP,
   % Copy objective values of actual subpopulation
      ObjVSub = ObjV((irun-1)*Nind+1:irun*Nind);
   % Sort does not handle NaN values as required. So, find those...
      NaNix = isnan(ObjVSub);
      Validix = find(~NaNix);
   % ... and sort only numeric values (smaller is better).
      [ans,ix] = sort(-ObjVSub(Validix));

   % Now build indexing vector assuming NaN are worse than numbers,
   % (including Inf!)...
      ix = [find(NaNix) ; Validix(ix)];
   % ... and obtain a sorted version of ObjV
      Sorted = ObjVSub(ix);

   % Assign fitness according to RFun.
      i = 1;
      FitnVSub = zeros(Nind,1);
      for j = [find(Sorted(1:Nind-1) ~= Sorted(2:Nind)); Nind]',
         FitnVSub(i:j) = sum(RFun(i:j)) * ones(j-i+1,1) / (j-i+1);
         i =j+1;
      end

   % Finally, return unsorted vector.
      [ans,uix] = sort(ix);
      FitnVSub = FitnVSub(uix);

   % Add FitnVSub to FitnV
      FitnV = [FitnV; FitnVSub];
end


% End of function

REINS

% REINS.M        (RE-INSertion of offspring in population replacing parents)
%
% This function reinserts offspring in the population.
%
% Syntax: [Chrom, ObjVCh] = reins(Chrom, SelCh, SUBPOP, InsOpt, ObjVCh, ObjVSel)
%
% Input parameters:
%    Chrom     - Matrix containing the individuals (parents) of the current
%                population. Each row corresponds to one individual.
%    SelCh     - Matrix containing the offspring of the current
%                population. Each row corresponds to one individual.
%    SUBPOP    - (optional) Number of subpopulations
%                if omitted or NaN, 1 subpopulation is assumed
%    InsOpt    - (optional) Vector containing the insertion method parameters
%                ExOpt(1): Select - number indicating kind of insertion
%                          0 - uniform insertion
%                          1 - fitness-based insertion
%                          if omitted or NaN, 0 is assumed
%                ExOpt(2): INSR - Rate of offspring to be inserted per
%                          subpopulation (% of subpopulation)
%                          if omitted or NaN, 1.0 (100%) is assumed
%    ObjVCh    - (optional) Column vector containing the objective values
%                of the individuals (parents - Chrom) in the current 
%                population, needed for fitness-based insertion
%                saves recalculation of objective values for population
%    ObjVSel   - (optional) Column vector containing the objective values
%                of the offspring (SelCh) in the current population, needed for
%                partial insertion of offspring,
%                saves recalculation of objective values for population
%
% Output parameters:
%    Chrom     - Matrix containing the individuals of the current
%                population after reinsertion.
%    ObjVCh    - if ObjVCh and ObjVSel are input parameter, than column 
%                vector containing the objective values of the individuals
%                of the current generation after reinsertion.
           
% Author:     Hartmut Pohlheim
% History:    10.03.94     file created
%             19.03.94     parameter checking improved

function [Chrom, ObjVCh] = reins(Chrom, SelCh, SUBPOP, InsOpt, ObjVCh, ObjVSel);


% Check parameter consistency
   if nargin < 2, error('Not enough input parameter'); end
   if (nargout == 2 & nargin < 6), error('Input parameter missing: ObjVCh and/or ObjVSel'); end

   [NindP, NvarP] = size(Chrom);
   [NindO, NvarO] = size(SelCh);

   if nargin == 2, SUBPOP = 1; end
   if nargin > 2,
      if isempty(SUBPOP), SUBPOP = 1;
      elseif isnan(SUBPOP), SUBPOP = 1;
      elseif length(SUBPOP) ~= 1, error('SUBPOP must be a scalar'); end
   end

   if (NindP/SUBPOP) ~= fix(NindP/SUBPOP), error('Chrom and SUBPOP disagree'); end
   if (NindO/SUBPOP) ~= fix(NindO/SUBPOP), error('SelCh and SUBPOP disagree'); end
   NIND = NindP/SUBPOP;  % Compute number of individuals per subpopulation
   NSEL = NindO/SUBPOP;  % Compute number of offspring per subpopulation

   IsObjVCh = 0; IsObjVSel = 0;
   if nargin > 4, 
      [mO, nO] = size(ObjVCh);
      if nO ~= 1, error('ObjVCh must be a column vector'); end
      if NindP ~= mO, error('Chrom and ObjVCh disagree'); end
      IsObjVCh = 1;
   end
   if nargin > 5, 
      [mO, nO] = size(ObjVSel);
      if nO ~= 1, error('ObjVSel must be a column vector'); end
      if NindO ~= mO, error('SelCh and ObjVSel disagree'); end
      IsObjVSel = 1;
   end
       
   if nargin < 4, INSR = 1.0; Select = 0; end   
   if nargin >= 4,
      if isempty(InsOpt), INSR = 1.0; Select = 0;   
      elseif isnan(InsOpt), INSR = 1.0; Select = 0;   
      else
         INSR = NaN; Select = NaN;
         if (length(InsOpt) > 2), error('Parameter InsOpt too long'); end
         if (length(InsOpt) >= 1), Select = InsOpt(1); end
         if (length(InsOpt) >= 2), INSR = InsOpt(2); end
         if isnan(Select), Select = 0; end
         if isnan(INSR), INSR =1.0; end
      end
   end
   
   if (INSR < 0 | INSR > 1), error('Parameter for insertion rate must be a scalar in [0, 1]'); end
   if (INSR < 1 & IsObjVSel ~= 1), error('For selection of offspring ObjVSel is needed'); end 
   if (Select ~= 0 & Select ~= 1), error('Parameter for selection method must be 0 or 1'); end
   if (Select == 1 & IsObjVCh == 0), error('ObjVCh for fitness-based exchange needed'); end

   if INSR == 0, return; end
   NIns = min(max(floor(INSR*NSEL+.5),1),NIND);   % Number of offspring to insert   

% perform insertion for each subpopulation
   for irun = 1:SUBPOP,
      % Calculate positions in old subpopulation, where offspring are inserted
         if Select == 1,    % fitness-based reinsertion
            [Dummy, ChIx] = sort(-ObjVCh((irun-1)*NIND+1:irun*NIND));
         else               % uniform reinsertion
            [Dummy, ChIx] = sort(rand(NIND,1));
         end
         PopIx = ChIx((1:NIns)')+ (irun-1)*NIND;
      % Calculate position of Nins-% best offspring
         if (NIns < NSEL),  % select best offspring
            [Dummy,OffIx] = sort(ObjVSel((irun-1)*NSEL+1:irun*NSEL));
         else              
            OffIx = (1:NIns)';
         end
         SelIx = OffIx((1:NIns)')+(irun-1)*NSEL;
      % Insert offspring in subpopulation -> new subpopulation
         Chrom(PopIx,:) = SelCh(SelIx,:);
         if (IsObjVCh == 1 & IsObjVSel == 1), ObjVCh(PopIx) = ObjVSel(SelIx); end
   end


% End of function

RWS

% RWS.m - Roulette Wheel Selection
%
%       Syntax:
%               NewChrIx = rws(FitnV, Nsel)
%
%       This function selects a given number of individuals Nsel from a
%       population. FitnV is a column vector containing the fitness
%       values of the individuals in the population.
%
%       The function returns another column vector containing the
%       indexes of the new generation of chromosomes relative to the
%       original population matrix, shuffled. The new population, ready
%       for mating, can be obtained by calculating
%       OldChrom(NewChrIx, :).

% Author: Carlos Fonseca, 	Updated: Andrew Chipperfield
% Date: 04/10/93,		Date: 27-Jan-94

function NewChrIx = rws(FitnV,Nsel);

% Identify the population size (Nind)
[Nind,ans] = size(FitnV);

% Perform Stochastic Sampling with Replacement
cumfit  = cumsum(FitnV);
trials = cumfit(Nind) .* rand(Nsel, 1);
Mf = cumfit(:, ones(1, Nsel));
Mt = trials(:, ones(1, Nind))';
[NewChrIx, ans] = find(Mt < Mf & ...
                        [ zeros(1, Nsel); Mf(1:Nind-1, :) ] <= Mt);

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值