干货|遗传+禁忌混合算法(HA)算法求解柔性作业车间调度问题(FJSP)附java代码-第一部分

过去小编简单了解过作业车间调度问题(JSP),这两个月简单接触了柔性车间调度问题(FJSP),但是因为一些原因打算暂时研究到这里。在研究的时候,小编发现网上这方面的中文资源不多,那么秉持着普度众生的原则,就在这里和大家分享一下最近研究的一些成果。

柔性作业车间调度问题介绍

之前我们曾经做过车间调度问题(JSP)的内容,相关可以看这篇文章:
干货|禁忌搜索算法求解作业车间调度问题(附Java代码)

这里再简单介绍一下FJSP:

集合 J = J 1 , J 2 , . . . . . . , J n J={J_1, J_2, ......, J_n} J=J1,J2,......,Jn表示一系列相互独立的工件,任一工件 J i J_i Ji需要经过 O 11 , O 12 , . . . . . . , O 1 k O_{11}, O_{12},......,O_{1k} O11,O12,......,O1k等一系列工序的加工方可完成,工序之间按照固定的加工顺序依次完成。集合 U = U 1 , U 2 , . . . . . . , U n U={U_1, U_2, ......, U_n} U=U1,U2,......,Un表示可用的加工机器, O i j O_{ij} Oij表示工件 i i i的第 j j j道工序,可以在可用机器集合 U i j U_{ij} Uij中的任意机器上进行加工。每道工序的加工时间与加工机器相关。

一道工序一旦开始加工,就不能中断。每台机器一次只能加工一道工序。在初始加工时刻,所有工件和机器都是可用的。

一般来说,该问题的目标是最小化Makespan,通常用L来表示,即从开始加工到所有工件加工完毕总的时长。

综上所述,柔性车间调度问题和车间调度问题相似,在此之上改变了一个条件:对JSP,每道工序只能在某个特定的机器上加工;对FJSP,工序可能有多个可加工的机器(且不同机器上加工时间不同)。

所以,FJSP不光要选择工序在机器上加工的顺序,还要选择在哪个机器上加工。这也意味着FJSP是比JSP更复杂的优化问题。

根据小编这段时间的研究,学术界目前比较常用的启发式求解算法是种群进化+邻域搜索混合算法,其中GA+TS是比较成熟的算法体系。接下来主要参考论文 An effective hybrid genetic algorithm and tabu search for flexible job shop scheduling problem 的算法,介绍论文里的混合算法HA,以及小编自己复现的代码。
(代码和论文可在文末下载)

算法总体结构
算法总体的流程如上图所示,简单来说就是在GA的过程中,对每一个子代个体进行tabu search优化。下面小编分别对GA部分和TS部分进行讲解。

遗传算法部分

大家知道,不同的启发式算法在不同问题下效果会有很大的差别。过去小编在研究VRP问题时,GA的表现不是很好,编码、解码过程也相对复杂。但是GA在FJSP上表现的却非常优秀,因此大部分算法采取GA或类似GA的种群进化算法作为基础。仅仅是GA部分,已经可以以相当快的速度得到还算不错的解。

编码解码

FJSP的GA编码采取两行数字的方式。一串叫做OS(operation sequence),一串叫做MS(machine sequence)。之前我们提到过,求解FJSP需要做两个选择:工序加工顺序的选择;工序加工机器的选择。顾名思义,两串编码分别对应这两种选择。
FJSP GA编码
上图是一个FJSP算例的编码和对应解。

表a代表算例。

在这里插入图片描述

算例中有三个工件需要加工,每个工件分别有两道工序(不同工件加工工序不一定一样多)。除了J3的工序T2(task)外,所有工序都可以在三台机器上加工,对应的加工时间如表a所示。

表b的OS String和MS String代表染色体编码。

在这里插入图片描述

OS String中有N个数字(N代表总工序数),每一位数字代表一道工序对应的工件。简单的说,在decode的过程中,优先安排靠左的工件到对应机器上。同一数字出现的次数代表工件的第k道工序,例如第一个“1”代表O11,也就是J1T1。第二个“3”代表O31,J3T1。第三个“1”代表O12,J1T2。

MS String中也有N个数字,代表每个工件选择的机器。MS的顺序按照工件顺序排列,如图,J1、J2、J3都有2道工序,那么第一位数字“2”则代表O11,J1T1,需要安排在第二个可以加工的机器上。注意这里的数字不代表机器序号,代表的是可加工的机器。例如最后一位数字“2”,代表的不是machine2,因为J3T3无法在machine2上加工;它代表的是J3T3第二个可加工的机器,也就是machine3。

表c用甘特图表示了表b中编码解码出的一个可行解。

在这里插入图片描述

最基本的思路是按照OS的顺序,在甘特图中一个接一个填入工序。但这样做后你会发现,O22本应该出现在O12后面(在OS中第二个2出现在第二个1后面),但它却跑到了O12前面;但是,图中的解确实可行,而且优于我们之前的做法。这就涉及一个查找的过程,是decode中的一个优化。

这里介绍一下如何优化decode。首先,我们设定 a s i j as_{ij} asij (allowing starting time),代表Oij的在工序约束(必须在同一工件上一道工序结束后才能开始加工)下的最早允许开始时间; c i j c_{ij} cij代表Oij的结束时间。则我们得到公式 a s i j = c i ( j − 1 ) as_{ij} = c_{i(j - 1)} asij=ci(j1)

从第一道工序开始按OS的顺序,安排工序Oij:

  1. 计算 a s i j as_{ij} asij
  2. 检查工序所在加工机器中的所有空闲时间区间 [ t s , t e ] [t_s, t_e] [ts,te]。例如对O22而言,其所在加工机器M1中的空闲时间区间有一个: [ 0 , 4 ] [0, 4] [0,4]
  3. i f : m a x ( a s i j , t s ) + t i j k < t e if: max(as_{ij}, t_s) + t_{ijk} < t_e if:max(asij,ts)+tijk<te,则设置当前工序Oij的开始时间 s i j = t s s_{ij} = t_s sij=ts。其中 t i j k t_{ijk} tijk表示Oij在机器k上加工的时间。
  4. 否则,检查下一个空闲时间区间。若所有区间都不满足,放置机器最后。
  5. 设置工序加工结束时间 c i ( j − 1 ) = s i j + t i j k c_{i(j - 1)} = s_{ij} + t{ijk} ci(j1)=sij+tijk

编码的过程则比较简单。MS编码自不用说,按顺序把机器需要排列好就行;OS编码论文中没提编码方法,小编觉得可以对所有工序直接按照starting time排序,再按规则填入数字即可。简单试验后发现,对一串染色体进行这样的解码编码后得到的染色体与原本的染色体是相同的。

除了编码解码外,其他交叉、变异、选择部分与一般的GA算法没有太大差别。对一串合法的OS序列,无论进行怎样的交换、插入运算,都可以解码成可行解。对MS序列,在同一工件范围内任意交换顺序,也可以保证得到可行解。所以后续处理相对常规。

下面我们分别介绍相关步骤。

初始解生成

初始解生成采用随机生成的方式。

交叉

OS

OS String介绍两种crossover方法,分别为POX(precedence operation crossover )和JBX(job-basedcrossover ),每次迭代分别以50%的概率选择其中一个实行。

先介绍POX。

在这里插入图片描述

记父代为P1,P2,子代为O1,O2。

  1. 将工件随机分配成两组,Jobset1和Jobset12;
  2. 将P1中属于JS1的部分插入O1相同位置处,将P2中属于JS1的部分插入O1相同位置处;
  3. 将P1中属于JS2的部分按顺序插入O1的空余位置中(如图所示),P2同。

JBX非常类似:

在这里插入图片描述

  1. 将工件随机分配成两组,Jobset1和Jobset12;
  2. 将P1中属于JS1的部分插入O1相同位置处,P2中属于JS2的部分插入O2相同位置中;
  3. 将P2中属于JS2的部分按顺序插入O1的空余位置中(如图所示),P1则插入O2中。

MS

在这里插入图片描述
MS更简单,随机选择两个位置,如图所示,属于范围内的P1部分放到O1中,不属于范围内的P2部分放到O1中;属于范围内的P2部分放到O2中,不属于范围内的P1部分放到O2中。

变异

OS

OS的变异有两种方法,交换式和邻域式。

在这里插入图片描述
交换式即随机选择两点交换位置。

在这里插入图片描述
邻域式则是选择三个点,组成 C 2 3 = 6 C^3_2 = 6 C23=6种情况,再随机选择其中一种。

选择

选择可以有多种方法。精英选择,锦标赛选择,轮盘赌选择。这里介绍论文里使用的前两种。(小编的代码中三种都有写)

精英选择:直接按适应度排序,取最优的几个。

锦标赛选择:每次随机选择k个子代(k一般在2~6之间,论文里采用k=2),选出其中最优的一个。

论文里采用精英选择+竞标赛选择的方法。

禁忌搜索算法部分

禁忌搜索算法部分是嵌套在GA中的。按原论文的说法,对每一代子代的每一个个体,都需要decode成可行解,然后运用禁忌搜索优化解,再编码回GA编码,进入下一代。(听起来就觉得时间复杂度蛮高的)

除了甘特图外,JSP / FJSP还有自己的一套表示解的方法,称为析取图。简单来说,就是把工序作为点,前后加工关系作为边,以此表示工序的加工顺序。

如前文所说,由于嵌套至每一个个体,算法的运行时间很容易爆炸,多写一个循环都会产生不可估量的后果。同时,原论文在这一部分没有很详细的描述,因此小编在复现这一部分的时候也没有处理的很好,来来回回写了多个Tabu Search。由于篇幅原因,这一部分暂时留到下期讲,后续应该还会对小编的代码进行简单讲解,请大家多多关注!

参考

[1]Li, Xinyu , and L. Gao . “An effective hybrid genetic algorithm and tabu search for flexible job shop scheduling problem.” International Journal of Production Economics 174.Apr.(2016):93-110.

[2]Zhang, Chao Yong , P. G. Li , and Y. R. Zailin Guan . “A tabu search algorithm with a new neighborhood structure for the job shop scheduling problem.” Computers & Operations Research 34.11(2007):3229-3242.

[3]Mastrolilli, Monaldo , and L. M. Gambardella . “Effective Neighbourhood Functions for the Flexible Job Shop Problem.” Journal of Scheduling 3.1(2015):3-20.

[4]Zhang, Guohui , L. Gao , and Y. Shi . “An effective genetic algorithm for the flexible job-shop scheduling problem.” Expert Systems with Applications 38.4(2011):3563-3573.

代码下载

扫描下方二维码,登录公众号【程序猿声】,输入【FJSPHA】不带【】即可免费获取相关代码!

也可以访问作者github下载对应代码:点击这里!

在这里插入图片描述

  • 6
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
本文介绍了使用Matlab实现多目标灰狼优化算法(Multi-Objective Grey Wolf Optimizer,MOGWO)来求解柔性作业车间调度问题(Flexible Job-Shop Scheduling Problem,FJSP)的方法。 1. 柔性作业车间调度问题 柔性作业车间调度问题是指在一台机器上,需要安排多个作业在多个工序上进行加工,每个作业需要在不同的工序上进行加工,每个工序需要一定的时间和资源,同时需要考虑不同的约束条件(如最早开始时间、最迟完成时间、作业间的优先关系等),目标是最小化完成所有作业的总时间或最小化机器的空闲时间。 2. 多目标灰狼优化算法 多目标灰狼优化算法是基于灰狼优化算法(Grey Wolf Optimizer,GWO)的多目标优化版本。该算法模拟了灰狼社会的行为,通过抓住“alpha”、“beta”和“delta”三个主导灰狼的行为来优化目标函数。多目标灰狼优化算法可以同时优化多个目标函数。 3. 求解柔性作业车间调度问题 求解柔性作业车间调度问题的过程可以分为以下几个步骤: (1)编写目标函数:将FJSP问题转化为目标函数,将多个目标函数合并成一个多目标函数。 (2)确定参数:确定算法的参数,如灰狼个数、最大迭代次数、交叉率等。 (3)初始化灰狼群体:根据问题的特性,初始化灰狼群体。 (4)灰狼优化过程:根据多目标灰狼优化算法,进行灰狼优化过程。 (5)结果分析:分析灰狼优化的结果,得到最优解。 4. Matlab实现 在Matlab中,可以使用以下代码实现MOGWO算法求解FJSP问题: % FJSP问题的目标函数 function f = FJSP(x) % x为决策变量,即作业的加工顺序 % 定义多个目标函数 f(1) = 计算完成所有作业的总时间 f(2) = 计算机器的空闲时间 % 将多个目标函数合并成一个多目标函数 f = [f(1) f(2)] end % MOGWO算法 function [bestx, bestf] = MOGWO(f, lb, ub, MaxIt, nPop, nObj, pCrossover, pMutation) % f为目标函数,lb和ub为决策变量的上下界,MaxIt为最大迭代次数,nPop为灰狼个数,nObj为目标函数个数,pCrossover和pMutation分别为交叉率和变异率 % 初始化灰狼群体 X = repmat(lb, nPop, 1) + rand(nPop, nObj).*(repmat(ub-lb, nPop, 1)); % 迭代优化过程 for it = 1:MaxIt % 计算适应度 F = zeros(nPop, nObj); for i = 1:nPop F(i,:) = f(X(i,:)); end % 更新最优解 [bestf, idx] = min(F); bestx = X(idx,:); % 更新灰狼位置 for i = 1:nPop % 计算灰狼位置 A = 2*rand(nObj,1)-1; C = 2*rand(nObj,1); D = abs(C.*bestx - X(i,:)); X1 = bestx - A.*D; % 交叉和变异 mask = rand(nObj,1) < pCrossover; X2 = X1; X2(~mask) = X(i,~mask); mask = rand(nObj,1) < pMutation; X3 = X2; X3(mask) = lb(mask) + rand(sum(mask),1).*(ub(mask)-lb(mask)); % 更新灰狼位置 X(i,:) = X3; end end end % 测试 % 假设有10个作业,每个作业需要在3个机器上进行加工 nJob = 10; nMachine = 3; % 初始化上下界 lb = zeros(1, nJob*nMachine); ub = ones(1, nJob*nMachine); % 假设最大迭代次数为100,灰狼个数为50,目标函数个数为2 MaxIt = 100; nPop = 50; nObj = 2; % 假设交叉率为0.8,变异率为0.3 pCrossover = 0.8; pMutation = 0.3; % 调用MOGWO算法求解FJSP问题 [bestx, bestf] = MOGWO(@FJSP, lb, ub, MaxIt, nPop, nObj, pCrossover, pMutation); % 输出结果 disp('Best Solution:'); disp(bestx); disp('Best Objective:'); disp(bestf);
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值