学习目标:
上两篇内容写了遗传算法求解FJSP算法的编码和初始化以及解码方式,今天把完整的算法代码放上来,与大家一块学习。
完整研究可参考:基于遗传算法求解柔性作业车间调度问题代码实现(包括标准算例准换、编码、解码的详细讲述)_crazy_girl_me的博客-CSDN博客
算法的基本步骤:
代码:
import numpy as np
import matplotlib.pyplot as plt
import random
import itertools
#全局初始化
def Global_initial(T0,O,GS,MS,n,M,OS_list,OS):
Machine_time = np.zeros(M,dtype=int) # 机器时间初始化
for i in range(GS):
random.shuffle(OS_list) # 生成工序排序部分
OS[i] = np.array(OS_list)
GJ_list=[]
for GJ_Num in range(n): #工件集
GJ_list.append(GJ_Num)
random.shuffle(GJ_list)
for g in GJ_list: # 随机选择工件集的第一个工件,从工件集中剔除这个工件
h = np.array(O[g]) # 第一个工件含有的工序
for j in range(len(h)): # 从工件的第一个工序开始选择机器
D = np.array(h[j])
List_Machine_weizhi = []
for k in range(len(D)): # 每道工序可使用的机器以及机器的加工时间
Useing_Machine = D[k]
if Useing_Machine == 9999: # 确定可加工该工序的机器
continue
else:
List_Machine_weizhi.append(k)
Machine_Select = []
for Machine_add in List_Machine_weizhi: # 将这道工序的可用机器时间和以前积累的机器时间相加
Machine_time[Machine_add] = Machine_time[Machine_add] + D[
Machine_add] # 比较可用机器的时间加上以前累计的机器时间的时间值,并选出时间最小
Machine_Select.append(Machine_time[Machine_add])
Min_time=min(Machine_Select)
Machine_Index_add = Machine_Select.index(Min_time)
MS[i][g*3+j] =Machine_Index_add + 1
CHS1=np.hstack((MS,OS))
return CHS1
#局部选择
def Local_initial(T0,O,LS,MS,n,M,OS_list,OS):
for i in range(LS):
random.shuffle(OS_list) # 生成工序排序部分
OS_gongxu = OS_list
OS[i] = np.array(OS_gongxu)
GJ_list=[]
for GJ_Num in range(n): #工件集
GJ_list.append(GJ_Num)
A=0
for gon in GJ_list:
Machine_time = np.zeros(M) # 机器时间初始化
g = gon # 随机选择工件集的第一个工件 #从工件集中剔除这个工件
h = np.array(O[g]) # 第一个工件及其对应工序的加工时间
for j in range(len(h)): # 从工件的第一个工序开始选择机器
D = np.array(h[j])
List_Machine_weizhi = []
for k in range(len(D)): # 每道工序可使用的机器以及机器的加工时间
Useing_Machine = D[k]
if Useing_Machine == 9999: # 确定可加工该工序的机器
continue
else:
List_Machine_weizhi.append(k)
Machine_Select = []
for Machine_add in List_Machine_weizhi: # 将这道工序的可用机器时间和以前积累的机器时间相加
Machine_time[Machine_add] = Machine_time[Machine_add] + D[Machine_add] # 比较可用机器的时间加上以前累计的机器时间的时间值,并选出时间最小
Machine_Select.append(Machine_time[Machine_add])
Machine_Index_add = Machine_Select.index(min(Machine_Select))
MS[i][g*3+j] = MS[i][g*3+j] + Machine_Index_add + 1
A+=1
CHS1=np.hstack((MS,OS))
return CHS1
#随机选择
def Random_initial(T0,O,RS,MS,n,M,OS_list,OS):
for i in range(RS):
random.shuffle(OS_list) # 生成工序排序部分
OS_gongxu = OS_list
OS[i] = np.array(OS_gongxu)
GJ_list=[]
for GJ_Num in range(n): #工件集
GJ_list.append(GJ_Num)
A=0
for gon in GJ_list:
Machine_time = np.zeros(M) # 机器时间初始化
g = gon # 随机选择工件集的第一个工件 #从工件集中剔除这个工件
h = np.array(O[g]) # 第一个工件及其对应工序的加工时间
for j in range(len(h)): # 从工件的第一个工序开始选择机器
D = np.array(h[j])
List_Machine_weizhi = []
for k in range(len(D)): # 每道工序可使用的机器以及机器的加工时间
Useing_Machine = D[k]
if Useing_Machine == 9999: # 确定可加工该工序的机器
continue
else:
List_Machine_weizhi.append(k)
Machine_Select = []
for Machine_add in List_Machine_weizhi: # 将这道工序的可用机器时间和以前积累的机器时间相加
Machine_time[Machine_add] = Machine_time[Machine_add] + D[
Machine_add] # 比较可用机器的时间加上以前累计的机器时间的时间值,并选出时间最小
Machine_Select.append(Machine_time[Machine_add])
Machine_Index_add = Machine_Select.index(random.choice(Machine_Select))
MS[i][A] = MS[i][A] + Machine_Index_add + 1
A+=1
CHS1=np.hstack((MS,OS))
return CHS1
#染色体解码
#JM与T的关系是一一对应的
def Chromosome_decoding(CHS,O,T0,n):
JM = np.zeros((4, 3), dtype=int) # JM(j,h)表示工件Ji的工序Oh的机器号
T = np.zeros((4, 3), dtype=int) # T(j,h)表示工件Jj的工序Oh的加工时间
# 步骤1:对机器选择部分进行解码,从左到右依次读取并转换成机器顺序矩阵JM和时间顺序矩阵T
MS = CHS[0:12]
OS = CHS[12:24]
GX_num = 0
for J_j in MS: # 将机器选择部分转换成机器顺序矩阵和时间顺序矩阵
GX_num += 1
JM_j = int((GX_num-1) / 3) #机器顺序矩阵的横坐标
JM_h = int((GX_num-1) % 3) #机器顺序矩阵的纵坐标
O_j =np.array(O[JM_j][JM_h])
Mac_using = []
Mac_time = []
for Mac_num in range(len(O_j)): # 寻找MS对应部分的机器时间和机器顺序
if O_j[Mac_num] != 9999:
Mac_using.append(Mac_num)
Mac_time.append(O_j[Mac_num])
else:
continue
JM[JM_j][JM_h] += Mac_using[J_j-1] # 机器顺序矩阵
T[JM_j][JM_h] += Mac_time[J_j-1] # 时间顺序矩阵
# 步骤2:按照步骤1对应的T和JM依次得到每个工件工序对应的加工机器和加工时间
Start_time=np.zeros((6,12),dtype=int) #机器开始加工的时间
End_time=np.zeros((6,12),dtype=int) #机器结束加工的时间
Opearation = np.zeros((6, 12), dtype=int)
Counter_List=[]
T_count=0
for OS_j in OS: # 通过机器顺序矩阵和时间顺序矩阵的到工序的加工机器和加工时间
T_count+=1
Counter_List.append(OS_j)
M_i_h=Counter_List.count(OS_j) #该工件的第几道工序
M_i = JM[OS_j-1][M_i_h-1] #这道工序使用的机器
P_ij=T[OS_j-1][M_i_h-1] #这道工序的加工时间
M_n_list=[]
for M_n in End_time[M_i]: #确定工序为机器M_i的第几道加工工序
if M_n!=0:
M_n_list.append(M_n)
# 工件O_jh是机器M_i的第一道加工工序,直接从机器M_i的零时刻进行加工
if M_i_h==1 and len(M_n_list)==0 :
Start_time[M_i][T_count-1]=0
End_time[M_i][T_count-1]+=P_ij
Opearation[M_i][T_count-1]=OS_j
# 工序O_jh是机器M_i的第一道工序
elif len(M_n_list)==0 and M_i_h>1:
#寻找该工件上一道工序的完工时间:
SD_Machine=JM[OS_j-1][M_i_h-2]
SD_count=0
SD_c=0
for SD_i in OS:
SD_count+=1
if SD_i==OS_j:
SD_c+=1
if SD_c==M_i_h-1:
break
S=End_time[SD_Machine][SD_count-1]
Start_time[M_i][T_count - 1] =S
End_time[M_i][T_count - 1] = S+ P_ij
Opearation[M_i][T_count - 1] = OS_j
elif len(M_n_list)!=0 and M_i_h==1:
List_start_0=[]
List_end_0=[]
List_index_0=[]
for L_i in range(len(End_time[M_i])):
if End_time[M_i][L_i]!=0:
List_start_0.append(Start_time[M_i][L_i])
List_end_0.append(End_time[M_i][L_i])
List_index_0.append(L_i)
disp = zip(List_index_0,List_end_0)
disp_1=zip(List_index_0,List_start_0)
Disp_1 = dict(disp)
Disp_2 = dict(disp_1)
A = sorted(Disp_1.items(), key=lambda item: item[1])
B = sorted(Disp_2.items(), key=lambda item: item[1])
D_1= dict(A)
D_2=dict(B)
List_start=[]
List_end=[]
List_index=[]
for k in D_1:
List_end.append(D_1[k])
List_index.append(k)
for k_1 in D_2:
List_start.append(D_2[k_1])
Lst=[]
Lst_index=[]
for L_j in range(len(List_end)-1):
if List_start[L_j+1]-List_end[L_j]>=P_ij:
Lst.append(List_start[L_j+1]-List_end[L_j])
Lst_index.append(List_index[L_j])
if len(Lst)!=0:
L_m_list = []
for L_m in Lst:
L_m_list.append(L_m)
if L_m>=P_ij:
L_P=Lst_index[Lst.index(L_m)]
Start_time[M_i][T_count - 1]=End_time[M_i][L_P]
break
while len(L_m_list)==len(Lst):
Start_time[M_i][T_count - 1] = max(End_time[M_i])
break
else:
Start_time[M_i][T_count - 1] = max(End_time[M_i])
End_time[M_i][T_count-1]=Start_time[M_i][T_count-1]+P_ij
Opearation[M_i][T_count - 1] = OS_j
#加工工序不是机器和工件的第一道工序
else:
SC_Machine = JM[OS_j - 1][M_i_h - 2] # 这个工件上一道工序的使用机器
CO_er = 0
CON_er = 0
for Max_i in OS:
CO_er += 1
if Max_i == OS_j:
CON_er += 1
if CON_er == M_i_h - 1:
break
SC_endtime = End_time[SC_Machine][CO_er - 1] # 这个工件的上一道工序的结束时间
SD_S=[]
SD_E=[]
SD_index=[]
for SD_i in range(len(End_time[M_i])):
if End_time[M_i][SD_i]!=0:
SD_E.append(End_time[M_i][SD_i])
SD_S.append(Start_time[M_i][SD_i])
SD_index.append(SD_i)
disp_2 = zip(SD_index, SD_E)
disp_3 = zip(SD_index, SD_S)
Disp_3 = dict(disp_2)
Disp_4 = dict(disp_3)
C_1 = sorted(Disp_3.items(), key=lambda item: item[1])
D_4 = sorted(Disp_4.items(), key=lambda item: item[1])
D_5 = dict(C_1)
D_6 = dict(D_4)
List_start_1 = []
List_end_1 = []
List_index_1 = []
for k_2 in D_5:
List_end_1.append(D_5[k_2])
List_index_1.append(k_2)
for k_3 in D_6:
List_start_1.append(D_6[k_3])
Lst_1 = []
Lst_index_1=[]
for L_j_1 in range(len(List_end_1) - 1):
if List_start_1[L_j_1 + 1] - List_end_1[L_j_1]>=P_ij:
Lst_1.append(List_start_1[L_j_1 + 1] - List_end_1[L_j_1])
Lst_index_1.append(List_index_1[L_j_1])
if len(Lst_1)!=0:
L_M_1_list=[]
for L_M_1 in Lst_1:
L_M_1_list.append(L_M_1)
if L_M_1 >= P_ij:
List_Count_1 = Lst_index_1[Lst_1.index(L_M_1)]
L_M= List_index_1[List_index_1.index(List_Count_1)+1]
if End_time[M_i][List_Count_1]>=SC_endtime or Start_time[M_i][L_M]-SC_endtime>=P_ij:
Start_time[M_i][T_count-1]=End_time[M_i][List_Count_1]
break
while len(L_M_1_list)==len(Lst_1):
if max(End_time[M_i]) >= SC_endtime:
Start_time[M_i][T_count - 1] = max(End_time[M_i])
else:
Start_time[M_i][T_count - 1] = SC_endtime
break
else:
if max(End_time[M_i])>=SC_endtime:
Start_time[M_i][T_count - 1] = max(End_time[M_i])
else:
Start_time[M_i][T_count - 1]=SC_endtime
End_time[M_i][T_count-1]=Start_time[M_i][T_count-1]+P_ij
Opearation[M_i][T_count - 1] = OS_j
return Start_time,End_time,Opearation
#交叉操作
#机器选择部分
def Crossover_Machine(T0,T_r,CHS1,CHS2):
r=random.randint(0,T0) #在区间[1,T0]内产生一个整数r
random.shuffle(T_r)
R=T_r[0:r] #按照随机数r产生r个互不相等的整数
#将父代的染色体复制到子代中去,保持他们的顺序和位置
C_1=CHS2
C_2=CHS1
for i in R:
K=CHS1[i]
K_2=CHS2[i]
C_1[i]=K
C_2[i]=K_2
return C_1,C_2
#工序排序部分
def Crossover_Operation(O_set,CHS1,CHS2):
r=2
random.shuffle(O_set)
O_1=O_set[0:r] #将工件集划分为Jobset1和Jobset2
O_2=O_set[r:4]
C_1=np.zeros(12,dtype=int)
C_2=np.zeros(12,dtype=int)
Count_i=0
Count=0
C_index1=[]
C_index2=[]
for j in CHS1: #复制父代染色体P1、P2中包含工件集Jobset1/Jobset2中的工件复制到C1/C2中,保持他们的顺序
Count_i+=1
for i in O_1:
if j==i:
C_1[Count_i-1]=j
for j_1 in CHS2:
Count+=1
for i_1 in O_2:
if j_1==i_1:
C_2[Count-1]=j_1
Count_2=0
for j_2 in CHS1:
Count_2+=1
for i_2 in O_2:
if j_2==i_2:
C_index1.append(Count_2-1)
Count_3=0
for j_3 in CHS2:
Count_3+=1
for i_3 in O_1:
if j_3==i_3:
C_index2.append(Count_3-1)
new_CHS1 = np.delete(CHS1, C_index1)
new_CHS2 = np.delete(CHS2, C_index2)
Count_4=0
for k in range(len(CHS1)):
if C_1[k]==0:
C_1[k]=new_CHS2[Count_4]
Count_4+=1
Count_5=0
for k_1 in range(len(CHS2)):
if C_2[k_1]==0:
C_2[k_1]=new_CHS1[Count_5]
Count_5+=1
return C_1,C_2
#变异操作
#机器变异部分
def Variation_Machine(Tr,O,MS):
#机器选择部分
r=random.randint(1,11) #在变异染色体中选择r个位置
random.shuffle(Tr)
T_r=Tr[0:r]
for i in T_r:
O_i=int(i/3)
O_j=i%3
Machine_using=O[O_i][O_j]
Machine_index=[]
for j in Machine_using:
if j!=9999:
Machine_index.append(j)
Min=Machine_index[0]
Min_index=0
for j_1 in range(len(Machine_index)):
if Machine_index[j_1]0: #设定结束的约束条件
Max_Itertions-=1
S=Select(Fit,POP_SIZE)
C_I=[]
for j in S:
C_I.append(C[j])
C_J=np.array(C_I)
P_c=random.uniform(0.6,0.8) #确定交叉概率
P_m=random.uniform(0.005,0.006) #确定变异概率
P_C=int(P_c*(len(S)))
P_M=int(P_m*(len(S)))
S_list=np.random.permutation(range(len(S)))
PC=S_list[0:P_C]
for k in range(0,len(PC),2):
CHS_1=C_J[PC[k]]
if k+1