用python实现改进遗传算法求解FJSP问题的完整编码

学习目标:

上两篇内容写了遗传算法求解FJSP算法的编码和初始化以及解码方式,今天把完整的算法代码放上来,与大家一块学习。


算法的基本步骤:

用python实现改进遗传算法求解FJSP问题的完整编码

用python实现改进遗传算法求解FJSP问题的完整编码

 


代码:

 

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]<Min:
                Min=Machine_index[j_1]
                Min_index=j_1
            else:
                Min=Min
                Min_index=Min_index
        MS[i]=Min_index+1
    return MS
# 变异操作
# 工序变异部分
def Variation_Operation(Tr,OS,MS):
    r = random.randint(2, 6)      #在变异染色体中选择r个位置
    random.shuffle(Tr)
    T_r = Tr[0:r]
    O_ky=[]
    for i in range(len(OS)):
        for j in range(len(T_r)):
            if i==T_r[j]:
                O_ky.append(OS[i])
    # print(O_ky)
    A=np.array(list(itertools.permutations(O_ky,r)))
    CHS_T=[]
    for k in range(len(A)):
        H=A[k]
        for k_1 in range(len(T_r)):
            I_1=T_r[k_1]
            I_2=H[k_1]
            OS[I_1]=I_2
        CHS=MS+OS
        CHS_T.append(list(CHS))
    M=np.array(CHS_T)
    W=fitness(M,k+1)
    Fit_index = []
    for i_1 in range(k+1):
        Fit_index.append(i_1)
    disp = zip(Fit_index, W)
    Disp = dict(disp)
    B_1 = sorted(Disp.items(), key=lambda item: item[1])
    B=dict(B_1)
    B_0=list(B.keys())
    B0=B_0[0]
    return CHS_T[B0]
#选择操作
def Select(Fit_value,POP_SIZE):
    Fit_index=[]
    for i in range(POP_SIZE):
        Fit_index.append(i)
    # print(Fit_index,Fit_value)
    disp=zip(Fit_index,Fit_value)
    Disp=dict(disp)
    A=sorted(Disp.items(), key=lambda item: item[1])
    D=dict(A)
    Pop_leave=int(POP_SIZE*0.6)
    CHS_index=[]
    for j, (k, v) in enumerate(D.items()):
        if j in range(0, Pop_leave):
            CHS_index.append(k)
    return CHS_index
#画甘特图
def gatt(End_time,Start_time,CHS):
    Start=[]
    End=[]
    M=['red','blue','yellow','orange','green']
    for i in range(6):
        for j in range(12):
            if End_time[i][j]!=0:
                plt.barh(i,width=End_time[i][j]-Start_time[i][j],left=Start_time[i][j],color=M[CHS[j+12]-1],edgecolor='white')
                plt.text(x=Start_time[i][j]+0.3,y=i,s=(CHS[j+12],End_time[i,j]))
                Start.append(Start_time[i][j])
                End.append(End_time[i][j])
    plt.yticks(np.arange(i + 1), np.arange(1, i + 2))
    plt.show()

def main():
    GSP = 0.6  # 全局选择的GS概率
    LSP = 0.3  # 局部选择的LS概率
    RSP = 0.1  # 随机选择的RS概率
    POP_SIZE = 100  # 种群规模
    Max_Itertions = 100  # 最大迭代次数=100
    T0_1 = 12  # 染色体长度的一半
    M0 = 6  # 机器数
    N = 4  # 工件数
    GS_1 = int(POP_SIZE * GSP)  # 全局选择的个数
    LS_1 = int(POP_SIZE * LSP)  # 局部选择的个数
    RS_1 = int(POP_SIZE * RSP)  # 随机选择的个数
    T_R=[0,1,2,3,4,5,6,7,8,9,10,11]

    CSH = np.zeros([POP_SIZE, T0_1 * 2], dtype=int)  # 初始化种群
    GS_MS_1 = np.zeros([GS_1,T0_1],dtype=int)     # 机器选择部分MS
    GS_OS_1 = np.zeros([GS_1,T0_1],dtype=int)  # 工序选择部分OS
    LS_MS_1 = np.zeros([LS_1,T0_1],dtype=int)  # 机器选择部分MS
    LS_OS_1 = np.zeros([LS_1,T0_1],dtype=int)  # 工序选择部分OS
    RS_MS_1 = np.zeros([RS_1,T0_1],dtype=int)  # 机器选择部分MS
    RS_OS_1 = np.zeros([RS_1,T0_1],dtype=int)  # 工序选择部分OS

    O_set1 = [1, 2, 3, 4]

    OS_List = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]

    L = [
        [[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个,。。。。
    ]
    O_L = np.array(L)
    CHS0=Global_initial(T0_1, O_L, GS_1, GS_MS_1, N, M0, OS_List, GS_OS_1)      #全局选择部分染色体
    CHS1=Local_initial(T0_1, O_L, LS_1, LS_MS_1, N, M0, OS_List, LS_OS_1)       #局部训责部分染色体
    CHS2=Random_initial(T0_1, O_L, RS_1, RS_MS_1, N, M0, OS_List, RS_OS_1)      #随机选择部分染色体
    C=np.vstack((CHS0,CHS1,CHS2))           #将初始化染色体合并到一个矩阵
    Fit=[]
    for i in range(len(C)):                #计算每个染色体个体的适应度
        M=C[i]
        A=Chromosome_decoding(M,O_L,T0_1,N)
        F=np.max(A[1])
        Fit.append(F)
    Min=min(Fit)
    while Max_Itertions>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<len(PC):
                CHS_2=C_J[PC[k+1]]
            else:
                break
            MS_crossover=Crossover_Machine(T0_1,T_R,CHS_1[0:12],CHS_2[0:12])
            OS_crossover=Crossover_Operation(O_set1,CHS_1[12:24],CHS_2[12:24])
            CHS_crossover_1=np.hstack((MS_crossover[0],OS_crossover[0]))
            CHS_crossover_2 = np.hstack((MS_crossover[1], OS_crossover[1]))
            CHS_crossover=np.vstack((CHS_crossover_1,CHS_crossover_2))
            C_J=np.vstack((C_J,CHS_crossover))
        Fit_1 = []
        for i_1 in range(len(C_J)):  # 计算每个染色体个体的适应度
            M_0 = C_J[i_1]
            A = Chromosome_decoding(M_0, O_L, T0_1, N)
            F = np.max(A[1])
            Fit_1.append(F)
        Min_1=min(Fit_1)

        if Min_1<Min:
            Min=Min_1
            S_1 = Select(Fit_1, len(C_J))
            Min_Index = S_1[0]
            Min_CHS = C_J[Min_Index]
    Chromo=Chromosome_decoding(Min_CHS,O_L,T0_1,N)
    print(Min)
    gatt(Chromo[1],Chromo[0],Min_CHS)		#画甘特图


main()

结果分析:

用python实现改进遗传算法求解FJSP问题的完整编码

用python实现改进遗传算法求解FJSP问题的完整编码