FJSP-GA/Decode.py

125 lines
5.5 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_Load = np.zeros(M_num, dtype=int) # 机器总负载
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
# 解码操作适配新编码前半部分为OS后半部分为MS
def decode(self, CHS, Len_Chromo):
"""
:param CHS: 种群基因
:param Len_Chromo: 工序总数OS和MS各占一半长度
:return: 双目标值 [最大加工时间, 负载标准差]
"""
# 重置状态
self.fitness = 0
self.Machine_Load = np.zeros(self.M_num, dtype=int)
for machine in self.Machines:
machine.assigned_task = []
machine.O_start = []
machine.O_end = []
machine.End_time = 0
for job in self.Jobs:
job.Processed = []
job.J_start = []
job.J_end = []
job.J_machine = []
job.Last_Processing_Machine = None
job.Last_Processing_end_time = 0
OS = list(CHS[0:Len_Chromo]) # 前半部分为工件排列
MS = list(CHS[Len_Chromo:2 * Len_Chromo]) # 后半部分为机器索引
Needed_Matrix = self.Order_Matrix(MS)
JM, TM = Needed_Matrix[0], Needed_Matrix[1]
for i in OS:
Job = i
O_num = self.Jobs[Job].Current_Processed() # 现在加工的工序
Machine = JM[Job][O_num] # 确定加工机器
Process_time = TM[Job][O_num] # 确定加工时间
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]) # 机器完成该工件该工序
self.Machine_Load[Machine] += Process_time # 累加机器负载
# 计算负载均衡度(标准差)
load_std = np.std(self.Machine_Load)
return [self.fitness, load_std]