2 篇文章 13 订阅

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

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

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

## 3.1、遗传算法编码和解码

### 编码代码如下：

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
% 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、选择操作

### 选择代码如下

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 交叉操作

### 3.3.1 IPOX交叉因子

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

### 3.3.2 MPX交叉因子

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

### 交叉操作的代码如下

   %% 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.6 实验验证

%% 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};


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、 小结

###### Note：转发请注明出处。

05-28 323
02-08
12-21
03-19
03-30 47
05-26 30
01-15

One.Wan

¥2 ¥4 ¥6 ¥10 ¥20

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