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

基于遗传算法求解柔性作业车间调度问题代码实现(包括标准算例准换、编码、解码的详细讲述)_crazy_girl_me的博客-CSDN博客

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

就直接上代码了:

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)

结果

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

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

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
遗传算法是一种模拟自然选择和遗传机制的搜索和优化方法,该方法通常用于解决复杂的优化问题。而Python是一种高级编程语言,具有简洁的语法和强大的库支持。因此,使用Python实现遗传算法可以方便地编写和调试算法,并且可以利用其丰富的库来加速算法的运行和优化。 在Python中,首先需要定义问题的适应度函数,它用于评估每个个体的适应程度。然后,定义一些遗传算法的基本操作,如选择、交叉和变异。选择操作根据个体的适应程度来保留一部分较优的个体。交叉操作随机选择两个个体,并通过交换部分遗传信息来产生新的个体。变异操作通过在个体中引入随机变化来增加多样性。 接下来,需要初始化一组个体作为初始种群,并迭代执行选择、交叉和变异操作直至满足停止准则。停止准则可以是达到一定迭代次数或达到问题的最优解。 为了实现这些操作,Python提供了许多功能强大的库,如NumPy用于处理数组和矩阵计算,Matplotlib用于绘制和可视化结果,以及其他一些优化库如DEAP等,可以方便地实现遗传算法的各个步骤。 总结来说,使用Python实现遗传算法可以方便地编写、调试和优化算法,同时利用丰富的库支持,可以快速地实现复杂的优化问题。这对于对遗传算法和优化问题感兴趣的研究人员和工程师来说,是一个非常有吸引力和有用的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码丽莲梦露

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值