基于遗传算法的柔性车间调度问题的求解(Flexible Job-shop scheduling problem based on genetic algorithm)

1、前言

距离上次研究传统车间调度问题(Job-shop scheduling problem,JSP ),大约有一个月左右了,这期间研究了一下柔性作业车间调度(Flexible Job-shop scheduling problem,FJSP),并利用MATLAB实现了基于遗传算法的FJSP问题求解。在此与大家分享一下,有问题欢迎评论留言,共同交流学习,完整代码见基于遗传算法的FJSP问题求解(备注:该源码在原来的作业车间调度算法基础上修改,部分命名未及时修改,不影响代码质量)。

2、柔性车间调度问题描述

柔性作业车间调度问题是传统Job-Shop 调度问题的扩展。在传统的 Job-Shop 调度问题中,工件的每道工序只能在一台确定的机床上加工。而在柔性作业车间调度问题中,每道工序可以在多台机床上加工,并且在不同的机床上加工所需时间不同。柔性作业车间调度问题减少了机器约束,扩大了可行解的搜索范围,增加了问题的复杂性。
柔性作业车间调度问题的描述如下:一个加工系统有 m 台机器,要加工 n种工件。每个工件包含一道或多道工序,工件的工序顺序是预先确定的;每道工序可以在多台不同的机床上加工,工序的加工时间随机床的性能不同而变化。调度目标是为每道工序选择最合适的机器、确定每台机器上各工件工序的最佳加工顺序及开工时间,使系统的某些性能指标达到最优。此外,在加工过程中还需满足以下约束条件:

  1. 同一时刻同一台机器只能加工一个零件;
  2. 每个工件在某一时刻只能在一台机器上加工,不能中途中断每一个操作;
  3. 同一工件的工序之间有先后约束,不同工件的工序之间没有先后约束;
  4. 不同工件具有相同的优先级;

例如, 一个包括 3 个工件、5 台机器的柔性作业车间调度加工时间表如表 5.1 所示。柔性作业车间调度问题的求解过程包括两部分:选择各工序的加工机器和确定每台机器上工件的先后顺序。
在这里插入图片描述调度的目标就是确定每个机器上工序的加工顺序和每个工序的开工时间,使得最大完工时间 C m a x C_{max} Cmax (makspan)最小或者其他指标达到最优。

3、利用遗传算法求解柔性车间调度问题

3.1、遗传算法编码和解码

编码与解码是指染色体和调度解之间进行相互转换,是遗传算法成功实施优化的首要和关键问题。对于传统的作业车间调度问题,大多数研究采用基于工序的编码。但是柔性作业车间调度问题不仅要确定工序的加工顺序,还需为每道工序选择一台合适的机器,仅采用基于工序的编码方法不能得到问题的解。因此,对于柔性作业车间调度问题,遗传算法的编码由两部分组成,第一部分为基于工序的编码,用来确定工序的加工先后顺序;第二部分为基于机器分配的编码,用来选择每道工序的加工机器。融合这两种编码方法,即可得到柔性作业车间调度问题的一个可行解。结合两种编码方式的染色体如下图所示。
在这里插入图片描述其中基于工序编码的基因串确定工序加工的先后顺序,基于机器编码的基因串确定每个工件所有工序的加工机器。图中所示的染色体表示的工序和机器序列为( O 11 , M 1 O_{11},M_1 O11,M1),( O 21 , M 1 O_{21},M_1 O21,M1),( O 12 , M 3 O_{12},M_3 O12,M3),( O 22 , M 4 O_{22},M_4 O22,M4),( O 13 , M 4 O_{13},M_4 O13,M4),( O 31 , M 3 O_{31},M_3 O31,M3),( O 23 , M 5 O_{23},M_5 O23,M5),( O 32 , M 2 O_{32},M_2 O32,M2),( O 33 , M 2 O_{33},M_2 O33,M2)。
解码过程和编码过程相反,解码分为一般解码或者称为半主动解码、主动解码和全主动解码。本文使用半主动解码方式进行染色体解码。

编码代码如下:

function [Population] = Coding(T,PopSize)
%% INPUT:
% T--input matrix:
%  For example: 
%  A partial flexible scheduling problem in which 8 jobs are processed 
%  on 8 machines, in which the number of available machining machines per
%  step of job is less than or equal to the total number of machines
% J1 ={[5 3 5 3 3 0 10 9];[10 0 5 8 3 9 9 6];[0 10 0 5 6 2 4 5]};
% J2 ={[5 7 3 9 8 0 9 0];[0 8 5 2 6 7 10 9];[0 10 0 5 6 4 1 7];[10 8 9 6 4 7 0 0]};
% J3 ={[10 0 0 7 6 5 2 4];[0 10 6 4 8 9 10 0];[1 4 5 6 0 10 0 7]};
% J4 ={[3 1 6 5 9 7 8 4];[12 11 7 8 10 5 6 9];[4 6 2 10 3 9 5 7]}; 
% J5 ={[3 6 7 8 9 0 10 0];[10 0 7 4 9 8 6 0];[0 9 8 7 4 2 7 0];[11 9 0 6 7 5 3 6]};
% J6 ={[6 7 1 4 6 9 0 10];[11 0 9 9 9 7 6 4];[10 5 9 10 11 0 10 0]};
% J7 ={[5 4 2 6 7 0 10 0];[0 9 0 9 11 9 10 5];[0 8 9 3 8 6 0 10]};
% J8 ={[2 8 5 9 0 4 0 10];[7 4 7 8 9 0 10 0];[9 9 0 8 5 6 7 1];[9 0 3 7 1 5 8 0]};
% T={J1;J2;J3;J4;J5;J6;J7;J8}; 8*1 cell
% Popsize- Population size in genetic algorithms,2*PopSize+1
%% OUTPUT:
% Population-Popsize*1 cell
% chromosome-2*1 cell
%% variable declaration
num_of_jobs = length(T);                                                   %number of jobs
num_of_machines = length(T{1}{1});                                         %number of machines
steps_of_job =[];
machine_of_job=cell(num_of_jobs,1);

% calculate the length of chromosome
for i = 1:num_of_jobs
    steps_of_job=[steps_of_job;length(T{i})];
end
len_of_chromosome = sum(steps_of_job);

% calculate the machine set for each steps of each job
for i=1:num_of_jobs
    steps=cell(steps_of_job(i),1);
    for j = 1:steps_of_job(i)
        machineset=[];
        for k=1:length(T{i}{j})
            if T{i}{j}(k)~=0
               machineset=[machineset k]; 
            end
        end
        steps{j}=machineset;
    end
    machine_of_job{i}=steps;
end


%steps chromosome
%Coding is based on the step of the job
step_chromsome=[];
for i = 1:num_of_jobs
    for j = 1:steps_of_job(i)
        step_chromsome=[step_chromsome i];
    end
end
step_population =[];
%Generate population with chromosome containing random genes 
for i = 1:PopSize
    step_population(i,:)=step_chromsome(randperm(length(step_chromsome(:))));
end
%
%machine chromosome
%In each steps, the machine is randomly selected for two machines,
%and the machine that selects the short processing time is the gene with
%propability
machine_population =[];
for index = 1:PopSize
    machine_chromsome=[];
    for i=1:num_of_jobs
        for j=1:steps_of_job(i)
            pos= randperm(length(machine_of_job{i}{j}),2);
            machine1=machine_of_job{i}{j}(pos(1));
            machine2=machine_of_job{i}{j}(pos(2));
            if (rand(1)<0.8) && (T{i}{j}(machine1)>T{i}{j}(machine2))
                machine = machine2;
            else
                machine = machine1;
            end
            machine_chromsome=[machine_chromsome machine];   
        end
    end
    machine_population(index,:) = machine_chromsome;
end

Population=cell(PopSize,1);
for i=1:PopSize
    Population{i} =[step_population(i,:);machine_population(i,:)]; 
end
end

解码代码如下

%% Flexible Job-shop scheduling problem based on genetic algorithm with POX selection
% Author:Eric.Wan
% Date:2019-12-8
% Add.:ShenYang,China
% Email:970301442@qq.com
% Version: v1.0
function [Jobs,Cmax,MachineList,ST,PT] = SemiActiveDecoding(T,Chromosome)
%% INPUT:
 % T--input matrix:
    %  For example: 
    %  A partial flexible scheduling problem in which 8 jobs are processed 
    %  on 8 machines, in which the number of available machining machines per
    %  step of job is less than or equal to the total number of machines
    % J1 ={[5 3 5 3 3 0 10 9];[10 0 5 8 3 9 9 6];[0 10 0 5 6 2 4 5]};
    % J2 ={[5 7 3 9 8 0 9 0];[0 8 5 2 6 7 10 9];[0 10 0 5 6 4 1 7];[10 8 9 6 4 7 0 0]};
    % J3 ={[10 0 0 7 6 5 2 4];[0 10 6 4 8 9 10 0];[1 4 5 6 0 10 0 7]};
    % J4 ={[3 1 6 5 9 7 8 4];[12 11 7 8 10 5 6 9];[4 6 2 10 3 9 5 7]}; 
    % J5 ={[3 6 7 8 9 0 10 0];[10 0 7 4 9 8 6 0];[0 9 8 7 4 2 7 0];[11 9 0 6 7 5 3 6]};
    % J6 ={[6 7 1 4 6 9 0 10];[11 0 9 9 9 7 6 4];[10 5 9 10 11 0 10 0]};
    % J7 ={[5 4 2 6 7 0 10 0];[0 9 0 9 11 9 10 5];[0 8 9 3 8 6 0 10]};
    % J8 ={[2 8 5 9 0 4 0 10];[7 4 7 8 9 0 10 0];[9 9 0 8 5 6 7 1];[9 0 3 7 1 5 8 0]};
    % T={J1;J2;J3;J4;J5;J6;J7;J8}; 8*1 cell
  %Chromosome -- A chromosome to be decoded
%% OUTPUT:
    %JobList-- job sequences
    %Cmax --the max makespan
    %MachineList--The machine sequences corresponding to chromosome
    %ST --the start time for each job step in chromosome
    %PT --The operation time for each job step in chromome
%% start
num_of_jobs = length(T);                                                   %number of jobs
num_of_machines = length(T{1}{1});                                         %number of machines
len_of_chromosome = length(Chromosome);


StepList = [];                                                             %steps for all genes
MachineList = zeros(1,len_of_chromosome);
ST = zeros(1,len_of_chromosome);
PT = zeros(1,len_of_chromosome);
DecodedGenes =[];


steps_of_job =[];                                                       
for i = 1:num_of_jobs
    steps_of_job=[steps_of_job;length(T{i})];
end
               
%% Caculate MachineList and PT
for index = 1:len_of_chromosome
    DecodedGenes=[DecodedGenes Chromosome(1,index)];
    postion = length(find(DecodedGenes==Chromosome(1,index))); 
    StepList = [StepList postion];
    MachineList(index)=Chromosome(2,sum(steps_of_job(1:(Chromosome(1,index)-1)))+postion);
    PT(index)=T{Chromosome(1,index)}{postion}(MachineList(index));
end

%% Caculate ST
Machines = unique(MachineList);
Jobs = unique(Chromosome(1,:));

job_start_time = cell(num_of_jobs,1);
job_end_time = cell(num_of_jobs,1);
machine_start_time = cell(num_of_machines,1);
machine_end_time   = cell(num_of_machines,1);
machine_state = zeros(1,num_of_machines);                                %0--FirstWork;1--NotFirst 


for index = 1:len_of_chromosome
    job = Chromosome(1,index);
    machine = MachineList(index);
    pt = PT(index);
    step = StepList(index);
    pos_m = find(Machines==machine);
    pos_j = find(Jobs==job);
    if step==1                                                             %first step without considering the constrains between steps of same job
        if machine_state(pos_m)==0                                         % The machine is first used
            job_start_time{pos_j}=[0,pos_m];
            job_end_time{pos_j}=[job_start_time{pos_j}(1)+pt,pos_m];
            
        else
            job_start_time{pos_j}=[machine_end_time{pos_m}(1),pos_m];
            job_end_time{pos_j}=[job_start_time{pos_j}(1)+pt,pos_m];
        end
    else
         if machine_state(pos_m)==0                                         % The machine is first used
            job_start_time{pos_j}=[job_end_time{pos_j}(1),pos_m];
            job_end_time{pos_j}=[job_start_time{pos_j}(1)+pt,pos_m];
           
        else
            job_start_time{pos_j}=[max(machine_end_time{pos_m}(1),job_end_time{pos_j}(1)),pos_m];
            job_end_time{pos_j}=[job_start_time{pos_j}(1)+pt,pos_m];
        end       
        
    end
    machine_start_time{pos_m}= job_start_time{pos_j}(1);
    machine_end_time{pos_m} = job_end_time{pos_j}(1); 
    machine_state(pos_m)=1;
    ST(index)=job_start_time{pos_j}(1); 
end

%% Caculate Cmax
end_time=cell2mat(job_end_time);
Cmax = max(end_time(:,1));
end

3.2、选择操作

在遗传算法中,适应度是个体对生存环境的适应程度,适应度高的个体将获得更多的生存机会。选择算子根据适应度的值选择个体遗传到下一代群体中。选择操作采用最佳个体保存(Elitist model)和锦标选择(Tournament selection)两种方法。在本章的改进遗传算法中,最佳个体保存方法是将父代群体中最优的 一个个体直接复制到下一代中。锦标选择是从种群中随机选择两个个体,如果随机值(在 0~1 之间随机产生)小于给定概率值 r(概率值 r是一个参数,一般设置为 0.8),则选择优的一个,否则就选择另一个。被选择的个体放回到种群,可以重新作为一个父染色体参与选择。

选择代码如下

BestFitness=min(FITNESS);                                              % find the best chromosome
    position=find(FITNESS==BestFitness);                                   % and the position,may be more than one
    BestChromosome=Population{position(1)};                                % choose one chromosome from population
  
    
    %% Selection :Elitism and 2-tournament selection are used
    Parent = cell(PopSize,1);
    Pr =0.8;
    for index =1:PopSize-1
        pos = randperm(PopSize,2);
        chromosome1 = Population{pos(1)};
        chromosome2 = Population{pos(2)};
        if (rand(1)<Pr) && FITNESS(pos(1))>FITNESS(pos(2))
                chromosome = chromosome1;
        else
                chromosome = chromosome2;
        end
        Parent{index} = chromosome;
    end
        Parent{PopSize}=BestChromosome;    

3.3 交叉操作

交叉操作是将种群中两个个体随机地交换某些基因,产生新的基因组合,期望将有益的基因组合在一起。染色体中两部分基因串的交叉分别进行,其中第一部分基于工序编码基因串的交叉操作采用IPOX 交叉算子,第二部分基于机器分配编码基因串的交叉采用多点交叉MPX的方法。

3.3.1 IPOX交叉因子

IPOX操作是在POX操作基础上经改进而形成的(POX不了解的可以参考博文基于遗传算法的传统作业车间调度的问题求解),它仅仅交叉父代染色体中工序的加工序列,保留工件中工序分配的机器到子代。IPOX的具体操作过程如下图所示,其中 P 1 P_1 P1 P 2 P_2 P2为调度问题的两个父代染色体,交叉产生子代 C 1 C_1 C1 C 2 C_2 C2.IPOX交叉操作过程为:
1)把所有的工件随机分成两个集合 G 1 G_1 G1 G 2 G_2 G2;
2) 复制 P 1 P_1 P1包含在 G 1 G_1 G1中的工件到 C 1 C_1 C1,复制 P 2 P_2 P2包含在 G 2 G_2 G2中的工件到 C 2 C_2 C2,保留它们的位置;
3)复制 P 1 P_1 P1包含在 G 1 G_1 G1中的工件到 C 2 C_2 C2,复制 P 2 P_2 P2包含在 G 2 G_2 G2中的工件到 C 1 C_1 C1,保留它们的顺序。
在这里插入图片描述

3.3.2 MPX交叉因子

MPX交叉父代染色体中工序选定的机器,工序的加工顺序保留到子代。多点交叉操作的过程如下图所示。对于某调度问题, P 1 P_1 P1 P 2 P_2 P2为调度问题的两个父代染色体,交叉产生子代 C 1 C_1 C1 C 2 C_2 C2.MPX交叉操作过程为:
1)首先随机产生一个有整数0、1组成的与染色体长度相等的rand[0,1]集;
2)依次在 P 2 P_2 P2中选出 P 1 P_1 P1与rand[0,1]集中1的位置对应相同的工序,交换他们分配的机器, P 1 P_1 P1 P 2 P_2 P2 中其他机器的加工顺序保留到子代,这样分别产生子代 C 1 C_1 C1 C 2 C_2 C2。因为是同一工序的加工机器交换,生成的子代染色体必为可行解。
在这里插入图片描述

交叉操作的代码如下

   %% Crossover: IPOX for steps, MPX for machine 
   
    Children_group1=cell(PopSize,1);
    for i=1:(PopSize-1)
        %Parent individuals are selected for crossover operation:
        %Parent1 is selected sequentially and Parent2 is selected randomly.
        index_parent2 = randi([1,(PopSize-1)]);
        Parent1=Parent{i};
        Parent2=Parent{index_parent2};
       
        Children1=zeros(2,len_of_chromosome);
        Children2=zeros(2,len_of_chromosome);
        if rand(1)<=Pc %Use the probability to determine if crossover is required
           %% Part1: IPX for step
            %Randomly divide the set of jobs {1,2,3...,n} into two non-empty sub-sets J1 and J2.
            num_J1 = randi([1,num_of_jobs]);   
            if num_J1==num_of_jobs
                num_J1 = fix(num_of_jobs/2);  
            end
            J = randperm(num_of_jobs);          
            J1 =J(1:num_J1);
            J2 =J(num_J1+1:num_of_jobs); 
            % Copy the jobs that Parent1 contains in J1 to Children1, 
            % and Parent2 contains in J2 to Children2, and keep them in place.
            for index = 1:num_J1                                            % look for jobs that Parent1 are included in J1
                job = J1(index);
                for j = 1:len_of_chromosome
                    if job == Parent1(1,j)
                        Children1(1,j)=Parent1(1,j);
                    end 
                end   
            end
            for index = 1:num_of_jobs-num_J1                                % look for jobs that Parent2 are included in J2
                job = J2(index);
                for j = 1:len_of_chromosome
                    if job == Parent2(1,j)
                        Children2(1,j)=Parent2(1,j);
                    end 
                end   
            end           
            %Copy the jobs that Parent1 contains in J1 to Children2, 
            %and Parent2 contains in J2 to Children1 in their order.
           for index = 1:len_of_chromosome                                            % look for jobs that Parent1 are included in J1
                job = Parent1(1,index);
                if ~isempty(find(J1==job, 1))
                     for gene = 1:len_of_chromosome
                         if Children2(1,gene)==0
                            Children2(1,gene)=job;
                            break;
                         end
                     end
                end
                
            end
           for index = 1:len_of_chromosome                                            % look for jobs that Parent1 are included in J1
                job = Parent2(1,index);
                if ~isempty(find(J2==job, 1))
                     for gene = 1:len_of_chromosome
                         if Children1(1,gene)==0
                            Children1(1,gene)=job;
                            break;
                         end
                     end
                end
                
            end
            %%IPOX cross operation completed
           %% Part 2 MPX for machine 
            %The process of crossover operation is as follows: firstly, a set rand0_1 
            %composed of 0 and 1 that is equal to the length of chromosome is randomly 
            %generated, and then the genes at the same position of 1 in the set of rand0_1
            %in the two parental generations are interchanged, and two offspring are
            %obtained after the crossover
            rand0_1 = zeros(1,len_of_chromosome);
            for gene = 1:len_of_chromosome
                if rand(1)>0.5
                    rand0_1(gene)=1;
                end
            end

            for gene = 1:len_of_chromosome
                if rand0_1(gene)==1
                   Children1(2,gene) = Parent2(2,gene);
                   Children2(2,gene) = Parent1(2,gene);
                else
                   Children1(2,gene) = Parent1(2,gene);
                   Children2(2,gene) = Parent2(2,gene);                   
                end
            end    
            %MOX cross operation completed
        else  
        Children1 = Parent1;
        Children2 = Parent2;  
        end
        %% Select the Fitness value best retained to the next generation
        [Parent1_FitnessValue] = FitnessCalculator(T,Parent1);
        [Parent2_FitnessValue] = FitnessCalculator(T,Parent2);
        [Children1_FitnessValue] = FitnessCalculator(T,Children1);
        [Children2_FitnessValue] = FitnessCalculator(T,Children2);
        [~, pos] = max([Parent1_FitnessValue Parent2_FitnessValue Children1_FitnessValue Children2_FitnessValue]);
        temp_group ={Parent1 Parent2 Children1 Children2};

           
    end
    Children_group1{PopSize}= BestChromosome;

3.4 变异操作

变异操作的目的是改善算法的局部搜索能力和维持群体多样性,同时防止出现早
熟现象。基于工序编码和基于机器分配编码的变异分别设计如下:

  1. 基于工序编码的变异
    对于这部分基因实施插入变异,即从染色体中随机选择一个基因,然后将之插入到一个随机的位置。
  2. 基于机器分配编码的变异
    由于每道工序都可以由多台机器完成,所以随机选择两道工序,然后在执行这两道工序的机器集合中选择一台机器(采用比例选择策略,加工时间短的优先选择),并将选择的机器号置入对应的基于机器分配编码的基因串中,这样得出的解能确保是可行解。

交叉操作的代码如下

 %% Mutation 

    Children_group2=cell(PopSize,1);
    for i=1:(PopSize-1)
       temp_chromsome = Children_group1{i};
       %% Mutation for steps
        if rand(1)<Pm
            for j=1:4
                pos1=randi([1,len_of_chromosome]); % Choose the sequence number of a gene to be mutated
                pos2=randi([1,len_of_chromosome]); %  Choose another the sequence number of a gene to be mutated
                Gene=temp_chromsome(1,pos1); 
                temp_chromsome(1,pos1)=temp_chromsome(1,pos2);
                temp_chromsome(1,pos2)=Gene;
            end
        end
       %% Mutation for machine
       if rand(1)<Pm
           for k=1:4
               job = randi([1,num_of_jobs]) ;                                  %random choose job
               tempstep = randi([1,steps_of_job(job)]);                            %random choose step
               newmachine = machine_of_job{job}{tempstep}(randi([1,length(machine_of_job{job}{tempstep})]));%random choose machine
               temp_chromsome(2,sum(steps_of_job(1:job-1))+1)= newmachine;     %replace the old one
           end
       end
       Children_group2{i} = temp_chromsome;    
     end
   
    Children_group2{PopSize}= BestChromosome;
    % complete mutation

3.5 绘制甘特图

这部分就是将最优的染色体绘制出来,代码同基于遗传算法的作业车间调度问题求解

3.6 实验验证

这里使用两个基准实例,即部分柔性实例 T 8 ∗ 8 T_{8*8} T88和完全柔性实例 T 10 ∗ 10 T_{10*10} T1010.

%% T8x8 
% A partial flexible scheduling problem in which 8 jobs are processed 
% on 8 machines, in which the number of available machining machines per
% step of job is less than or equal to the total number of machines
J1 ={[5 3 5 3 3 0 10 9];[10 0 5 8 3 9 9 6];[0 10 0 5 6 2 4 5]};
J2 ={[5 7 3 9 8 0 9 0];[0 8 5 2 6 7 10 9];[0 10 0 5 6 4 1 7];[10 8 9 6 4 7 0 0]};
J3 ={[10 0 0 7 6 5 2 4];[0 10 6 4 8 9 10 0];[1 4 5 6 0 10 0 7]};
J4 ={[3 1 6 5 9 7 8 4];[12 11 7 8 10 5 6 9];[4 6 2 10 3 9 5 7]}; 
J5 ={[3 6 7 8 9 0 10 0];[10 0 7 4 9 8 6 0];[0 9 8 7 4 2 7 0];[11 9 0 6 7 5 3 6]};
J6 ={[6 7 1 4 6 9 0 10];[11 0 9 9 9 7 6 4];[10 5 9 10 11 0 10 0]};
J7 ={[5 4 2 6 7 0 10 0];[0 9 0 9 11 9 10 5];[0 8 9 3 8 6 0 10]};
J8 ={[2 8 5 9 0 4 0 10];[7 4 7 8 9 0 10 0];[9 9 0 8 5 6 7 1];[9 0 3 7 1 5 8 0]};

T8x8={J1;J2;J3;J4;J5;J6;J7;J8};
%% T10x10
% For all flexible scheduling problems of 10 jobs and 10 machines,
% the number of available processing machines in each step of job is equal to 
% the total number of machines
G1={[1 4 6 9 3 5 2 8 9 5];[4 1 1 3 4 8 10 4 11 4];[3 2 5 1 5 6 9 5 10 3]};
G2={[2 10 4 5 9 8 4 15 8 4];[4 8 7 1 9 6 1 10 7 1];[6 11 2 7 5 3 5 14 9 2]};
G3={[8 5 8 9 4 3 5 3 8 1];[9 3 6 1 2 6 4 1 7 2];[7 1 8 5 4 9 1 2 3 4]};
G4={[5 10 6 4 9 5 1 7 1 6];[4 2 3 8 7 4 6 9 8 4];[7 3 12 1 6 5 8 3 5 2]};
G5={[7 10 4 5 6 3 5 15 2 6];[5 6 3 9 8 2 8 6 1 7];[6 1 4 1 10 4 3 11 13 9]};
G6={[8 9 10 8 4 2 7 8 3 10];[7 3 12 5 4 3 6 9 2 15];[4 7 3 6 3 4 1 5 1 11]};
G7={[1 7 8 3 4 9 4 13 10 7];[3 8 1 2 3 6 11 2 13 3];[5 4 2 1 2 1 8 14 5 7]};
G8={[5 7 11 3 2 9 8 5 12 8];[8 3 10 7 5 13 4 6 8 4];[6 2 13 5 4 3 5 7 9 5]};
G9={[3 9 1 3 8 1 6 7 5 4];[4 6 2 5 7 3 1 9 6 7];[8 5 4 8 6 1 2 3 10 12]};
G10={[4 3 1 6 7 1 2 6 20 6];[3 1 8 1 9 4 1 4 17 15];[9 2 4 2 3 5 2 4 10 23]};
T10x10 = {G1;G2;G3;G4;G5;G6;G7;G8;G9;G10};

这里贴上运行8*8实例的运行脚本程序入如下:

clear;
clc;
T = Tmatrix('8x8');
Iterations=100;
PopSize=50;
Pc=0.8;
Pm=0.5;
result=cell(1000,1);

[Chromosome] = POX_GA(T,Iterations,PopSize,Pc,Pm);
[Jobs,Cmax,MachineList,ST,PT] = SemiActiveDecoding(T,Chromosome);
GanntGraf(Jobs,Chromosome(1,:),MachineList,ST,PT,Cmax,'FJSP') ;

实验结果如下:
在这里插入图片描述

4、 小结

通过对柔性作业车间调度的研究,一方面加深了对遗传算法解决NP难问题的有效性的体会,利用遗传算法解决这里问题难点在于使用比较好的编码和解码方式,其次是如何避免早熟,解决这两个问题是关键。本文中使用的源代码,存在早熟问题,有待进一步解决,也欢迎各位不吝赐教留言指导;另一方面对制造系统的调度过程有了更深一层次的认识,希望能对今后的学习和工作有所帮助。 以上便是近期对调度问题的入门级探索,不足之处欢迎留言批评指正!

Note:转发请注明出处。
  • 41
    点赞
  • 258
    收藏
    觉得还不错? 一键收藏
  • 54
    评论
遗传算法可以用来求解车间调度问题。下面是一个使用Python实现的简单示例代码: ```python import random # 初始化种群 def init_population(population_size, gene_size): population = [] for _ in range(population_size): chromosome = [i+1 for i in range(gene_size)] random.shuffle(chromosome) population.append(chromosome) return population # 计算染色体适应度 def calculate_fitness(chromosome): fitness = 0 for i in range(len(chromosome)-1): if chromosome[i] != chromosome[i+1]: fitness += 1 return fitness # 选择操作 def selection(population): fitness_values = [calculate_fitness(chromosome) for chromosome in population] total_fitness = sum(fitness_values) probabilities = [fitness/total_fitness for fitness in fitness_values] selected_chromosomes = random.choices(population, probabilities, k=len(population)) return selected_chromosomes # 交叉操作 def crossover(parent1, parent2): point = random.randint(0, len(parent1)-1) child1 = parent1[:point] + parent2[point:] child2 = parent2[:point] + parent1[point:] return child1, child2 # 变异操作 def mutation(chromosome): point1, point2 = random.sample(range(len(chromosome)), 2) chromosome[point1], chromosome[point2] = chromosome[point2], chromosome[point1] return chromosome # 遗传算法求解车间调度问题 def solve_job_shop_scheduling(population_size, gene_size, max_generations): population = init_population(population_size, gene_size) best_fitness = float('inf') best_chromosome = None for generation in range(max_generations): selected_chromosomes = selection(population) new_population = [] while len(new_population) < population_size: parent1, parent2 = random.sample(selected_chromosomes, 2) child1, child2 = crossover(parent1, parent2) child1 = mutation(child1) child2 = mutation(child2) new_population.extend([child1, child2]) population = new_population for chromosome in population: fitness = calculate_fitness(chromosome) if fitness < best_fitness: best_fitness = fitness best_chromosome = chromosome print(f"Generation {generation+1}: Best Fitness = {best_fitness}") return best_chromosome # 示例使用 population_size = 100 gene_size = 10 max_generations = 100 best_chromosome = solve_job_shop_scheduling(population_size, gene_size, max_generations) print("Best Chromosome:", best_chromosome) ``` 这是一个简单的遗传算法示例,用于求解车间调度问题。其中,种群的大小、基因的大小以及最大迭代次数可以根据具体问题进行调整。代码中的适应度函数根据车间调度问题的实际需求进行定义和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值