之前的解码可能会出现解码不正确的现象导致甘特图出来有些问题,现在给出改进版本:
就直接上代码了:
Job类代码
class Job:
def __init__(self,Job_index,Operation_num):
self.Job_index=Job_index
self.Operation_num = Operation_num
self.Processed=[]
self.Last_Processing_end_time=0
self.J_start=[]
self.J_end=[]
self.J_machine=[]
self.J_worker=[]
self.Last_Processing_Machine=None
def Current_Processed(self):
return len(self.Processed)
def _Input(self,W_Eailiest,End_time,Machine):
self.Processed.append(1)
self.Last_Processing_Machine=Machine
self.Last_Processing_end_time=End_time
self.J_start.append(W_Eailiest)
self.J_end.append(End_time)
self.J_machine.append(Machine)
Machines类代码
class Machine_Time_window:
def __init__(self,Machine_index):
self.Machine_index=Machine_index
self.assigned_task = []
self.worker_for_task=[]
self.O_start = []
self.O_end = []
self.End_time=0
#机器的哪些时间窗是空的,此处只考虑内部封闭的时间窗
def Empty_time_window(self):
time_window_start = []
time_window_end = []
len_time_window=[]
if self.O_end is None:
pass
elif len(self.O_end)==1:
if self.O_start[0]!=0:
time_window_start=[0]
time_window_end=[self.O_start[0]]
elif len(self.O_end)>1:
if self.O_start[0] !=0:
time_window_start.append(0)
time_window_end.append(self.O_start[0])
time_window_start.extend(self.O_end[:-1]) #因为使用时间窗的结束点就是空时间窗的开始点
time_window_end.extend(self.O_start[1:])
if time_window_end is not None:
len_time_window=[time_window_end[i]-time_window_start[i] for i in range(len(time_window_end))]
return time_window_start,time_window_end,len_time_window
def Machine_Burden(self):
if len(self.O_start)==0:
burden=0
else:
processing_time=[self.O_end[i]-self.O_start[i] for i in range(len(self.O_start))]
burden=sum(processing_time)
return burden
def _Input(self,Job,M_Ealiest,P_t,O_num):
if self.O_end!=[]:
if self.O_start[-1]>M_Ealiest:
for i in range(len(self.O_end)):
if self.O_start[i]>=M_Ealiest:
self.assigned_task.insert(i,[Job + 1, O_num + 1])
break
else:
self.assigned_task.append([Job+1,O_num+1])
else:
self.assigned_task.append([Job+1,O_num+1])
self.O_start.append(M_Ealiest)
self.O_start.sort()
self.O_end.append(M_Ealiest+P_t)
self.O_end.sort()
self.End_time=self.O_end[-1]
Encode类
import numpy as np
import random
class Encode:
def __init__(self,Matrix,Pop_size,J,J_num,M_num):
self.Matrix=Matrix #工件各工序对应各机器加工时间矩阵
self.GS_num=int(0.6*Pop_size) #全局选择初始化
self.LS_num=int(0.2*Pop_size) #局部选择初始化
self.RS_num=int(0.2*Pop_size) #随机选择初始化
self.J=J #各工件对应的工序数
self.J_num=J_num #工件数
self.M_num=M_num #机器数
self.CHS=[]
self.Len_Chromo=0
for i in J.values():
self.Len_Chromo+=i
#生成工序准备的部分
def OS_List(self):
OS_list=[]
for k,v in self.J.items():
OS_add=[k-1 for j in range(v)]
OS_list.extend(OS_add)
return OS_list
#生成初始化矩阵
def CHS_Matrix(self, C_num): # C_num:所需列数
return np.zeros([C_num, self.Len_Chromo], dtype=int)
def Site(self,Job,Operation):
O_num = 0
for i in range(len(self.J)):
if i == Job:
return O_num + Operation
else:
O_num = O_num + self.J[i + 1]
return O_num
#全局选择初始化
def Global_initial(self):
MS=self.CHS_Matrix(self.GS_num)
OS_list= self.OS_List()
OS=self.CHS_Matrix(self.GS_num)
for i in range(self.GS_num):
Machine_time = np.zeros(self.M_num, dtype=float) # 机器时间初始化
random.shuffle(OS_list) # 生成工序排序部分
OS[i] = np.array(OS_list)
GJ_list = [i_1 for i_1 in range(self.J_num)]
random.shuffle(GJ_list)
for g in GJ_list: # 随机选择工件集的第一个工件,从工件集中剔除这个工件
h = self.Matrix[g] # 第一个工件含有的工序
for j in range(len(h)): # 从工件的第一个工序开始选择机器
D = h[j]
List_Machine_weizhi = []
for k in range(len(D)): # 每道工序可使用的机器以及机器的加工时间
Useing_Machine = D[k]
if Useing_Machine != 9999: # 确定可加工该工序的机器
List_Machine_weizhi.append(k)
Machine_Select = []
for Machine_add in List_Machine_weizhi: # 将这道工序的可用机器时间和以前积累的机器时间相加
# 比较可用机器的时间加上以前累计的机器时间的时间值,并选出时间最小
Machine_Select.append(Machine_time[Machine_add] + D[
Machine_add])
Min_time = min(Machine_Select)
K = Machine_Select.index(Min_time)
I = List_Machine_weizhi[K]
Machine_time[I] += Min_time
site=self.Site(g,j)
MS[i][site] = K
CHS1 = np.hstack((MS, OS))
return CHS1
#局部选择初始化
def Local_initial(self):
MS = self.CHS_Matrix(self.LS_num)
OS_list = self.OS_List()
OS = self.CHS_Matrix(self.LS_num)
for i in range(self.LS_num):
random.shuffle(OS_list) # 生成工序排序部分
OS_gongxu = OS_list
OS[i] = np.array(OS_gongxu)
GJ_list = [i_1 for i_1 in range(self.J_num)]
for g in GJ_list:
Machine_time = np.zeros(self.M_num) # 机器时间初始化
h =self.Matrix[g] # 第一个工件及其对应工序的加工时间
for j in range(len(h)): # 从工件的第一个工序开始选择机器
D = 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))
site = self.Site(g, j)
MS[i][site] = MS[i][site] + Machine_Index_add
CHS1 = np.hstack((MS, OS))
return CHS1
def Random_initial(self):
MS = self.CHS_Matrix(self.RS_num)
OS_list = self.OS_List()
OS = self.CHS_Matrix(self.RS_num)
for i in range(self.RS_num):
random.shuffle(OS_list) # 生成工序排序部分
OS_gongxu = OS_list
OS[i] = np.array(OS_gongxu)
GJ_list = [i_1 for i_1 in range(self.J_num)]
A = 0
for gon in GJ_list:
Machine_time = np.zeros(self.M_num) # 机器时间初始化
g = gon # 随机选择工件集的第一个工件 #从工件集中剔除这个工件
h = np.array(self.Matrix[g]) # 第一个工件及其对应工序的加工时间
for j in range(len(h)): # 从工件的第一个工序开始选择机器
D = np.array(h[j])
List_Machine_weizhi = []
Site=0
for k in range(len(D)): # 每道工序可使用的机器以及机器的加工时间
if D[k] == 9999: # 确定可加工该工序的机器
continue
else:
List_Machine_weizhi.append(Site)
Site+=1
Machine_Index_add = random.choice(List_Machine_weizhi)
MS[i][A] = MS[i][A] + Machine_Index_add
A += 1
CHS1 = np.hstack((MS, OS))
return CHS1
if __name__=='__main__':
Matrix=[
[[2,3,4,9999,9999,9999],[9999,3,9999,2,4,9999],[1,4,5,9999,9999,9999]], #第一个工件及其对应的机器加工时间
[[3,9999,5,9999,2,9999],[4,3,9999,9999,6,9999],[9999,9999,4,9999,7,11]], #第二个工件及其对应的机器加工时间
[[5,6,9999,9999,9999,9999],[9999,4,9999,3,5,9999],[9999,9999,13,9999,9,12]],#第3个,。。。。
[[9,9999,7,9,9999,9999],[9999,6,9999,4,9999,5],[1,9999,3,9999,9999,3]], #第4个,。。。。
]
Pop_size=10
J={1:3,2:3,3:3,4:3}
J_num=4
M_num=6
e=Encode(Matrix,Pop_size,J,J_num,M_num)
CHS1=e.Global_initial()
print('CHS1----->>>')
print(CHS1)
CHS2 = e.Random_initial()
print('CHS2----->>>')
print(CHS2)
CHS3 = e.Local_initial()
print('CHS3----->>>')
print(CHS3)
Decode类
import matplotlib.pyplot as plt
from Jobs import Job
from Machines import Machine_Time_window
import numpy as np
class Decode:
def __init__(self,J,Processing_time,M_num,):
self.Processing_time = Processing_time
self.Scheduled = [] # 已经排产过的工序
self.J=J
self.M_num = M_num
self.Machines = [] # 存储机器类
self.fitness = 0
for j in range(M_num):
self.Machines.append(Machine_Time_window(j))
self.Machine_State = np.zeros(M_num, dtype=int) # 在机器上加工的工件是哪个
self.Jobs = [] #存储工件类
for k, v in J.items():
self.Jobs.append(Job(k, v))
#时间顺序矩阵和机器顺序矩阵
def Order_Matrix(self,MS):
JM=[]
T=[]
Ms_decompose=[]
Site=0
for S_i in self.J.values():
Ms_decompose.append(MS[Site:Site+S_i])
Site+=S_i
for i in range(len(Ms_decompose)):
JM_i=[]
T_i=[]
for j in range(len(Ms_decompose[i])):
O_j=self.Processing_time[i][j]
M_ij=[]
T_ij=[]
for Mac_num in range(len(O_j)): # 寻找MS对应部分的机器时间和机器顺序
if O_j[Mac_num] != 9999:
M_ij.append(Mac_num)
T_ij.append(O_j[Mac_num])
else:
continue
JM_i.append(M_ij[Ms_decompose[i][j]])
T_i.append(T_ij[Ms_decompose[i][j]])
JM.append(JM_i)
T.append(T_i)
return JM,T
def Earliest_Start(self,Job,O_num,Machine):
P_t=self.Processing_time[Job][O_num][Machine]
last_O_end = self.Jobs[Job].Last_Processing_end_time # 上道工序结束时间
Selected_Machine=Machine
M_window = self.Machines[Selected_Machine].Empty_time_window()
M_Tstart = M_window[0]
M_Tend = M_window[1]
M_Tlen = M_window[2]
Machine_end_time = self.Machines[Selected_Machine].End_time
ealiest_start = max(last_O_end, Machine_end_time)
if M_Tlen is not None: # 此处为全插入时窗
for le_i in range(len(M_Tlen)):
if M_Tlen[le_i] >= P_t:
if M_Tstart[le_i] >= last_O_end:
ealiest_start=M_Tstart[le_i]
break
if M_Tstart[le_i] < last_O_end and M_Tend[le_i] - last_O_end >= P_t:
ealiest_start = last_O_end
break
M_Ealiest = ealiest_start
End_work_time = M_Ealiest + P_t
return M_Ealiest, Selected_Machine, P_t, O_num,last_O_end,End_work_time
#解码
def Decode(self,CHS,Len_Chromo):
MS=list(CHS[0:Len_Chromo])
OS=list(CHS[Len_Chromo:2*Len_Chromo])
Needed_Matrix=self.Order_Matrix(MS)
JM=Needed_Matrix[0]
for i in OS:
Job=i
O_num=self.Jobs[Job ].Current_Processed()
Machine=JM[Job][O_num]
Para=self.Earliest_Start(Job,O_num,Machine)
self.Jobs[Job]._Input(Para[0],Para[5],Para[1])
self.Machines[Machine]._Input(Job,Para[0],Para[2],Para[3])
if Para[5]>self.fitness:
self.fitness=Para[5]
self.Gantt(self.Machines)
def Gantt(self,Machines):
M = ['red', 'blue', 'yellow', 'orange', 'green', 'palegoldenrod', 'purple', 'pink', 'Thistle', 'Magenta',
'SlateBlue', 'RoyalBlue', 'Cyan', 'Aqua', 'floralwhite', 'ghostwhite', 'goldenrod', 'mediumslateblue',
'navajowhite',
'navy', 'sandybrown', 'moccasin']
for i in range(len(Machines)):
Machine=Machines[i]
Start_time=Machine.O_start
End_time=Machine.O_end
for i_1 in range(len(End_time)):
# plt.barh(i,width=End_time[i_1]-Start_time[i_1],height=0.8,left=Start_time[i_1],\
# color=M[Machine.assigned_task[i_1][0]],edgecolor='black')
# plt.text(x=Start_time[i_1]+0.1,y=i,s=Machine.assigned_task[i_1])
plt.barh(i, width=End_time[i_1] - Start_time[i_1], height=0.8, left=Start_time[i_1], \
color='white', edgecolor='black')
plt.text(x=Start_time[i_1] + (End_time[i_1] - Start_time[i_1])/2-0.5, y=i, s=Machine.assigned_task[i_1][0])
plt.yticks(np.arange(i + 1), np.arange(1, i + 2))
plt.title('Scheduling Gantt chart')
plt.ylabel('Machines')
plt.xlabel('Time(s)')
plt.show()
if __name__=='__main__':
from Encode_for_FJSP import Encode
Matrix = [[[5, 3, 5, 3, 3, 9999, 10, 9],
[10, 9999, 5, 8, 3, 9, 9, 6],
[9999, 10, 9999, 5, 6, 2, 4, 5]],
[[5, 7, 3, 9, 8, 9999, 9, 9999],
[9999, 8, 5, 2, 6, 7, 10, 9],
[9999, 10, 9999, 5, 6, 4, 1, 7],
[10, 8, 9, 6, 4, 7, 9999, 9999]],
[[10, 9999, 9999, 7, 6, 5, 2, 4],
[9999, 10, 6, 4, 8, 9, 10, 9999],
[1, 4, 5, 6, 9999, 10, 9999, 7]],
[[3, 1, 6, 5, 9, 7, 8, 4],
[12, 11, 7, 8, 10, 5, 6, 9],
[4, 6, 2, 10, 3, 9, 5, 7]],
[[3, 6, 7, 8, 9, 9999, 10, 9999],
[10, 9999, 7, 4, 9, 8, 6, 9999],
[9999, 9, 8, 7, 4, 2, 7, 9999],
[11, 9, 9999, 6, 7, 5, 3, 6]],
[[6, 7, 1, 4, 6, 9, 9999, 10],
[11, 9999, 9, 9, 9, 7, 8, 4],
[10, 5, 9, 10, 11, 9999, 10, 9999]],
[[5, 4, 2, 6, 7, 9999, 10, 9999],
[9999, 9, 9999, 9, 11, 9, 10, 5],
[9999, 8, 9, 3, 8, 6, 9999, 10]],
[[2, 8, 5, 9, 9999, 4, 9999, 10],
[7, 4, 7, 8, 9, 9999, 10, 9999],
[9, 9, 9999, 8, 5, 6, 7, 1],
[9, 9999, 3, 7, 1, 5, 8, 9999]]]
Pop_size = 10
J = {1: 3, 2: 4, 3: 3, 4: 3, 5: 4, 6: 3, 7: 3, 8: 4}
M_num = 8
J_num = 8
O_num = 27
e = Encode(Matrix, Pop_size, J, J_num, M_num)
L=e.Len_Chromo
CHS1 = e.Global_initial()
print('CHS1----->>>')
print(CHS1)
CHS2 = e.Random_initial()
print('CHS2----->>>')
print(CHS2)
CHS3 = e.Local_initial()
print('CHS3----->>>')
print(CHS3)
C=CHS1[0]
d=Decode(J,Matrix,M_num)
d.Decode(C,L)
结果
注:工件类和机器类多余的东西可以不用管,代码给出只是为了解码部分能够运行。
注:此解码不是最优解结果