目录
一、理论基础
随着制造业的快速发展,市场需求的不断扩大,对生产设备效率的需求也越来越高。因此,生产设备的调度优化问题已经成为核心问题。传统的基于遗传的优化算法中,存在各种缺陷,遗传优化过程陷入局部优化,优化速度较慢和优化结论不稳定等缺陷。针对这些问题,本文所提出的算法充分考虑了遗传算法和退火算法的诸多优势,如隐含的计算并行性、数值计算的稳定性、全局搜索与局部快速收敛搜索。充分结合了遗传算法的全局搜索能力与模拟退火算法的局部搜索能力同时可使模拟退火算法能够充分利用遗传算法所得的全局信息。
传统的生产设备通过简单重复的生产作业在同一生产设备上完成某个特定产品的生产,各个生产设备之间无法进行合理的工序组合和调整。因此,生产设备的优化调度问题可以定义为产品按照按照生产设备的生产节拍以及不同种类产品的生产周期将所有的工序进行组合,充分利用不同产品之间的生产间隙进行组合生产,使得每个生产设备的负荷量尽量充足和均衡,各工作站的空闲时间最少。用数学模型来描述生产设备调度优化问题,生产品整个过程的生产时间可以用如下的公式表示:
上述三个约束条件的含义分别为同一时刻任意一个机器只能同时生产一个产品;产品的生产周期、生产设备的初始化时间以及生产设备的清洗时间三个时间和小于当前产品的交付周期;产品的生产周期、生产设备的初始化时间,下一时刻产品切换到其他生产设备上进行生产而产生的操作延迟时间以及生产设备的清洗时间四个时间和小于当前产品的交付周期。
遗传优化算法具有较强的把握搜索过程总体的能力,但是在交叉过程中会导致最优解的错失,其全局最优解的搜索能力较弱,会出现早熟现象。将模拟退火算法融合到遗传算法中,同时集合遗传算法的全局性和并行性等优势,模拟退火算法的遍历性和局部搜索能力等优势。
改进之后的融合算法其主要步骤如下:
第一、随机化产生N个初始化群体P,分别设为P1 ,P2,...,PN。初始化种群首先要确定种群的规模N,此外还需要确定如下几组参数:种群规模 POPSIZE,染色体长度CHRLENGTH,交叉率PCROSS,变异率PMUTATION,初始温度T0,冷却温度T'以及降温方式。
第二、代入到优化目标函数,获得N个初始的适应度值,根据式子1可以获得T(P1),T(P2)...,T(PN)。在优化迭代过程中,需要考虑约束条件的限制。
第三、按照3.1章节所介绍的改进遗传算法的流程进行选择,变异和交叉等操作,通过这些操作保留一部分最优个体直接复制给下一代。被选择的个体所构成的新的群体为,而未被选择的个体所构成的新的群体为。将未被选择的个体进行交叉和变异,分别设置为和。
第四、然后对交叉和变异后的个体进行改进模拟退火的操作,所得结果设置为。在模拟退火操作阶段,通过以公式9所给出的概率来接受是否降温的指令。
第五、然后对模拟退火后的群体的所有个体进行计算适应度值;
第六、将改进遗传算法中最优个体(未进行变异交叉的部分个体)和改进模拟退火后的个体进行融合,构成新的种群,作为新一代的种群;
第七、重复上述的步骤直接优化迭代次数结束。
整个算法的流程如下图所示:
二、核心程序
clc;
clear;
close all;
warning off;
pack;
addpath 'func\'
addpath 'func\toolbox\'
s = RandStream('mt19937ar','Seed',0)
RandStream.setGlobalStream(s);
%一下是系统的一些参数
%一下是系统的一些参数
%订单个数
Num = 100;
%机器个数
Num_machine = 3;
global ProduceA;
global ProduceB;
global ProduceC;
global Time_OverA;
global Time_OverB;
global Time_OverC;
global isover;%这个变量用来说明是否超期
global Time_iniA;
global Time_iniB;
global Time_iniC;
global A_delays_diff;
global B_delays_diff;
global C_delays_diff;
global A_delays_same;
global B_delays_same;
global C_delays_same;
%生产周期
ProduceA = 15*24;
ProduceB = 20*24;
ProduceC = 30*24;
%三种商品的交货期限
Time_OverA = 20;
Time_OverB = 30;
Time_OverC = 40;
%定义初始化时间
Time_iniA = 24;
Time_iniB = 48;
Time_iniC = 72;
%更换机器产生的延迟
Time_delay = 12;
%清洗时间
Time_wash = [2,3,5];
%机器容量
Cap = [20,30,50];
%设置三种产品的随机值得随机数种子
Seek_A = 1;
Seek_B = 2;
Seek_C = 3;
%%%%%%%%%%%%%%此处在Simulink等效替换%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
RandStream.setDefaultStream(RandStream('mt19937ar','seed',Seek_A));
A_source = floor(30*rand(1,Num))+1;
RandStream.setDefaultStream(RandStream('mt19937ar','seed',Seek_B));
B_source = floor(20*rand(1,Num))+1;
RandStream.setDefaultStream(RandStream('mt19937ar','seed',Seek_C));
C_source = floor(10*rand(1,Num))+1;
%计算优化前的需要的时间
%计算优化前的需要的时间
TimeA = func_product_time(A_source,Time_iniC,ProduceC,Num,Cap,3)
TimeB = func_product_time(B_source,Time_iniB,ProduceB,Num,Cap,2)
TimeC = func_product_time(C_source,Time_iniA,ProduceA,Num,Cap,1)
MAX_Time = max([TimeA,TimeB,TimeC]);
TASKer = [A_source',B_source',C_source'];
%生产完一批,下一批换产品导致的延迟
A_1 = Time_iniA + Time_wash(1) + Time_delay;
A_2 = Time_iniA + Time_wash(2) + Time_delay;
A_3 = Time_iniA + Time_wash(3) + Time_delay;
A_delays_diff = [A_1,A_2,A_3];
B_1 = Time_iniB + Time_wash(1) + Time_delay;
B_2 = Time_iniB + Time_wash(2) + Time_delay;
B_3 = Time_iniB + Time_wash(3) + Time_delay;
B_delays_diff = [B_1,B_2,B_3];
C_1 = Time_iniC + Time_wash(1) + Time_delay;
C_2 = Time_iniC + Time_wash(2) + Time_delay;
C_3 = Time_iniC + Time_wash(3) + Time_delay;
C_delays_diff = [C_1,C_2,C_3];
%生产完一批,下一批还是生产同样的产品(根据修改后的要求可知,只要是同一批产品,则可以连续生产)
A_1 = 0;
A_2 = 0;
A_3 = 0;
A_delays_same = [A_1,A_2,A_3];
B_1 = 0;
B_2 = 0;
B_3 = 0;
B_delays_same = [B_1,B_2,B_3];
C_1 = 0;
C_2 = 0;
C_3 = 0;
C_delays_same = [C_1,C_2,C_3];
for i = 1:Num
Machine_sel{i,1} = [3,3,3];
Machine_sel{i,2} = [2,2,2];
Machine_sel{i,3} = [1,1,1];
end
%根据每个机器的容量,来等效出每个单个订单的生产时间,但在后面计算过程中,当期满足判决条件的时候,时间则为72,96或者120
for i = 1:Num
Machine_time{i,1} = [C_source(i)/Cap(1)*ProduceC,B_source(i)/Cap(1)*ProduceB,A_source(i)/Cap(1)*ProduceA];
Machine_time{i,2} = [C_source(i)/Cap(2)*ProduceC,B_source(i)/Cap(2)*ProduceB,A_source(i)/Cap(2)*ProduceA];
Machine_time{i,3} = [C_source(i)/Cap(3)*ProduceC,B_source(i)/Cap(3)*ProduceB,A_source(i)/Cap(3)*ProduceA];
end
%一下是遗传算法的一些参数
%个体
Num_gene = 20;
%遗传次数
Iteration = 1000;
%代沟
DG = 0.9;
%交叉率
cross_rate= 0.8;
%变异率
by_rate = 0.2;
%计数器
Cnter = 0;
[Nums_time,Num_ABC] = size(Machine_sel);
Best_save = zeros(2, Iteration);
All_Number = Nums_time*Num_ABC;
Number = zeros(1,Nums_time);
for i=1:Nums_time
Number(i)=Num_ABC;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%01)种群的初始化
Random_save_machine = zeros(Num_gene,2*All_Number);
for j=1:Num_gene
Number2=Number;
for i=1:All_Number
%产品编号ABC - > 123
val = unidrnd(Nums_time);
while Number2(val)==0
val = unidrnd(Nums_time);
end
%产品编号
Random_save_machine(j,i) = val;
Number2(val) = Number2(val)-1;
%机器编号
Temp = Machine_sel{val,Num_ABC-Number2(val)};
SizeTemp = length(Temp);
%随机产品机器
Random_save_machine(j,i+All_Number) = unidrnd(SizeTemp);
end
end
%定义fitness
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%02)定义优化目标函数
[Value_Product,ObjV,Product,Genes] = func_fitness(Random_save_machine,Num_machine,Machine_time,Machine_sel);
s = RandStream('mt19937ar','Seed',0);
RandStream.setGlobalStream(s);
%开始优化迭代
%设置模拟退火算法参数
%初始温度
T = 1000;
%温度降低参数
a = 0.99;
%记录模拟退火次数
kkk = 1;
while Cnter <= Iteration
Cnter
isover = 0;
if Cnter == 0
%交叉率
cross_rate0 = 0.8;
%变异率
by_rate0 = 1 - cross_rate0;
cross_rate = cross_rate0;
by_rate = by_rate0;
else
%交叉率
cross_rate = cross_rate0*(1-exp(1/(1+Cnter))/8);
%变异率
by_rate = 1 - cross_rate;
end
%适应度值
Value_fit = ranking(ObjV);
%选择
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%03)保留一部分最优的个体直接复制到新一代,这些群体定义为:
GA_Oper = select('rws', Random_save_machine, Value_fit, DG);
%04)没有被保留的部分进行交叉和变异操作
%交叉
GA_Oper = func_Gene_cross(GA_Oper,cross_rate,Machine_sel,Machine_time);
%变异
GA_Oper = func_aberrance(GA_Oper,by_rate,Machine_sel,Machine_time);
%适应度值
[Value_Product,Obj_Product,Product,Genes,TYPE] = func_fitness(GA_Oper,Num_machine,Machine_time,Machine_sel);
%新种群
[Random_save_machine,ObjV] = reins(Random_save_machine, GA_Oper,1, 1, ObjV, Obj_Product);
Cnter = Cnter + 1;
%保存最值
Best_save(1,Cnter) = min(ObjV);
Best_save(2,Cnter) = mean(ObjV);
%05)模拟退火过程
[newbestfitness,newbestindex]=min(ObjV);
[worestfitness,worestindex] =max(ObjV);
if Cnter == 1
[bestfitness,bestindex]=min(ObjV);
bestchrom = Random_save_machine(bestindex,:);
else
%代替上一次进化中最好的染色体
if bestfitness>= newbestfitness
bestfitness = newbestfitness;
bestchrom = Random_save_machine(newbestindex,:);
else
bh = bestfitness-newbestfitness;
cc(kkk) = bh/T;
aa(kkk) = exp(bh/T);
if exp(1000*bh/T) > rand/5
kkk = kkk+1;
bestfitness = newbestfitness;
bestchrom = Random_save_machine(newbestindex,:);
end
end
end
T=T*a; %温度降低
Random_save_machine(worestindex,:) = bestchrom;
ObjV(worestindex) = bestfitness;
%延期判决
if isover == 1
Cnter = Cnter-1;%重新开始本次迭代
else
Cnter =Cnter;
end
Best_V(Cnter) = mean(ObjV);
if Cnter <= 64
Best_V2(Cnter) = mean(Best_V(1:Cnter));
else
Best_V2(Cnter) = mean(Best_V(Cnter-64:Cnter));
end
end
%描绘解的变化
figure;
plot(Best_V2,'Linewidth',2);
grid on
xlabel('Iteration Number');
ylabel('GA & SA values');
%统计各个产品的生产情况
AD = TYPE(1:3:end);
BD = TYPE(2:3:end);
CD = TYPE(3:3:end);
[ANums,PCA] = func_output(AD,A_source,Cap,3);
[BNums,PCB] = func_output(BD,B_source,Cap,2);
[CNums,PCC] = func_output(CD,C_source,Cap,1);
save results.mat Best_V2 MAX_Time ANums BNums CNums
A06-25
三、仿真结论
通过优化之后,三种产品在不同的机器中的生产次序如下表所示:
表1 不同产品的生产次序
生产机器序列 | |
产品1 | 1,1,1,1,2,1,1,1,1,1,3,1,1,1,1,2,2,1,1,1,1,1...... |
产品2 | 2,2,2,2,1,2,2,2,2,2,1,2,2,2,2,1,1,2,2,2,2,2...... |
产品3 | 3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3...... |
从表1的结论可知,对于第1种产品,其首先进入到机器1生产,然后进入到机器2生产,然后进入到机器1生产。对于第2种产品,其首先进入到机器2生产,然后进入到机器1生产,然后进入到机器2生产。对于第3种产品,其首先进入到机器3生产,然后进入到机器3生产,然后进入到机器2生产。由于机器三的容量最大,所以当前两个第三种产品生产完之后,机器2产生了空档期,则将容量较小的后一批次的第三种产品直接送入到2号机器加工,依次类推。