FJSP-GA/Decode.py

104 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
from Job import Job
from Machine import Machine_Time_window
class Decode:
def __init__(self, J, Processing_time, M_num):
"""
:param J: 各工件对应的工序数字典
:param Processing_time: 各工件的加工时间矩阵
:param M_num: 加工机器数
"""
self.Processing_time = Processing_time
self.M_num = M_num
self.J = J
self.Machines = [] # 存储机器类
self.Scheduled = [] # 已经排产过的工序
self.fitness = 0 # 适应度
self.Machine_State = np.zeros(M_num, dtype=int) # 在机器上加工的工件是哪个
self.Jobs = [] # 存储工件类
for j in range(M_num):
self.Machines.append(Machine_Time_window(j))
for k, v in J.items():
self.Jobs.append(Job(k, v))
# 时间顺序矩阵和机器顺序矩阵根据基因的MS部分转换
def Order_Matrix(self, MS):
JM = []
T = []
Ms_decompose = []
Site = 0
# 按照基因的MS部分按工件序号划分
for S_i in self.J.values():
Ms_decompose.append(MS[Site:Site + S_i]) #对MS按照每道工序数进行切分
Site += S_i
for i in range(len(Ms_decompose)): # len(Ms_decompose)表示工件数
JM_i = []
T_i = []
for j in range(len(Ms_decompose[i])): # len(Ms_decompose[i])表示每一个工件对应的工序数
O_j = self.Processing_time[i][j] # 工件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):
"""
:param CHS: 种群基因
:param Len_Chromo: MS与OS的分解线
:return: 适应度,即最大加工时间
"""
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] # 用基因的OS部分的工件序号以及工序序号索引机器顺序矩阵的机器序号
Para = self.Earliest_Start(Job, O_num, Machine)
self.Jobs[Job]._Input(Para[0], Para[5], Para[1]) # 工件完成该工序
if Para[5] > self.fitness:
self.fitness = Para[5]
self.Machines[Machine]._Input(Job, Para[0], Para[2], Para[3]) # 机器完成该工件该工序
return self.fitness