用python实现利用改进遗传算法求解FJSP染色体解码部分(改进版本)

之前的解码可能会出现解码不正确的现象导致甘特图出来有些问题,现在给出改进版本:

就直接上代码了:

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)

结果

注:工件类和机器类多余的东西可以不用管,代码给出只是为了解码部分能够运行。

注:此解码不是最优解结果

猜你喜欢

转载自blog.csdn.net/crazy_girl_me/article/details/114787030
今日推荐