【车间调度】基于matlab免疫遗传算法求解多目标生产调度问题【含Matlab源码 710期】

247 阅读4分钟

一、简介

1 免疫算法
1.1免疫算法的基本步骤:
(1)抗原识别。输入目标函数和各种约束作为免疫算法的抗原。
(2)初始抗体生成。随机生成初始抗体种群。
(3)亲和力计算。计算抗体的适应值。对解群体中的各个解个体进行综合评价,包括解(抗体)与问题(抗原)的适应值(亲和力)以及解与解之间的相似度(亲和力)
(4)免疫处理。免疫处理包括免疫选择、克隆、变异和抑制。
(5)免疫选择:根据抗体的亲和力选出亲和度较高的抗体。
(6)克隆:对选出的亲和力较高的抗体进行复制。
(7)变异:对克隆得到的个体进行交叉、变异操作,使其亲和力发生改变。
(8)抑制:对变异的抗体进行选择,保留亲和度较高的抗体。
(9)群体刷新。将免疫选择的抗体和免疫抑制后的抗体组成一个集合,保留其中亲和度较高的抗体,使这些抗体进入新的种群。新的种群中不足的部分随机生成,以增加多样性。
在这里插入图片描述

2 免疫算法与遗传算法的区别
在这里插入图片描述
免疫算法是模拟免疫系统对病菌的多样性识别能力(即免疫系统几乎可以识别无穷多种类的病菌)而设计出来的多峰值搜索算法,其具体步骤如下
在这里插入图片描述
在这里插入图片描述

二、源代码

%% 清空环境
clc;clear

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

%% 基本参数
NIND=40;        %个体数目
MAXGEN=80;      %最大遗传代数
GGAP=0.9;       %代沟
XOVR=0.8;       %交叉率
MUTR=0.1;       %变异率
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;
    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

三、运行结果

在这里插入图片描述
在这里插入图片描述

四、备注

版本:2014a