多机调度问题是生产管理与控制的一个基本问题。按照加工设备数量和加工作业的流云方式,一般可分为单机调度、并行机调度、Flowshop调度、可重入式调度和Jobshop调度会多种类型。作业调度中的许多问题,不仅具有随机性、约束复杂、规模大及多目标冲突等点,而且许多都属于NP完全问题,即使在单机情形也是如此。因此,如何寻求有效可行的度求解方案,一直是生产管理与控制研究的热点和难点。
一、多机调度问题
多机调度问题是个NP完全问题,到目前为止没有有效的算法(求得最优解的有效的算法),但是利用贪心算法可以近似求出最优解,采用最长处理时间作业优先的贪心选择策略,可以设计出较好的解。在n<m时,我们大可以为每个作业分配一台机器,而在n>m时,我们选择将所有的作用按处理时间从大到小排序,按照这个顺序给每个作业分配最先空闲的机器。对于每一个任务i,m个机器都可以选择执行或不执行,对于每一种情况进行递归回溯,在这个过程中更新最优解,剪枝策略:默认完成全部任务的时间为最长时间即best=INF,当执行当前任务需要的时间小于best时进行回溯,否则不进行递归出口,当回溯到第n个任务时结束,更新最优解。
设有\(n\)个独立的作业{1, 2, …, n}, 由m台相同的机器进行加工处理,作业\(i\)所需时间为\(T_i\)。约定:任何作业可以在任何一台机器上加工处理,但未完工前不允许中断处理,任何作业不能拆分成更小的子作业。要求给出一种作业执行次序,使所给的\(n\)个作业在尽可能短的时间内由\(m\)台机器加工处理完成,计算\(n\)由\(m\)台机器处理的最短时间,并给出作业加工顺序。
二、算法思想
设计思路:
(1)搜索从开始节点(根节点)出发,以深度优先搜索搜索整个解空间。
(2)每搜索完一条路径则记录下T和best序列,开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处向纵深方向移至一个新结点后并成为一个新的活结点,也成为当前扩展结点。
(3)如果在当前的扩展结点处不能再向纵深方向扩展,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点;直至找到一个解或全部解。
贪心法求解多机调度问题的贪心策略是最长处理时间作业优先,即把处理时间最长的作业分配给最先空闲的机器,这样可以保证处理时间长的作业优先处理,从而在整体上获得尽可能短的处理时间。按照最长处理时间作业优先的贪心策略,当m≥n时,只要将机器i的[0,ti)时间区间分配给作业i即可;当m<n时,首先将n个作业依其所需的处理时间从大到小排序,然后依此顺序将作业分配给空闲的处理机。
三、算法Python实现
# 多机调度问题——最佳调度问题
n = 9 # 任务数
k = 4 # 机器数
best = 99999 # 最优值(完成全部任务的最早时间)
len = [] # 每台机器已安排的时间
t = [10,14,3,9,21,6,18,16,5] # 每个任务所需的时间
x = [] # 当前路径(调度)
bestx = [] # 最优路径(调度)
# 计算任务完成的时间
def comp():
tmp = 0
for i in range(k):
if len[i] > tmp:
tmp = len[i]
return tmp
# 以深度优先遍历方式遍历解空间树
def search(dep, len, t):
global best
if dep == n:
tmp = comp()
if tmp < best:
best = tmp
for i in range(n):
bestx[i] = x[i]
return
for i in range(k):
len[i] += t[dep]
x[dep] = i + 1
if len[i] < best:
search(dep + 1, len, t)
len[i] -= t[dep]
if __name__=="__main__":
len = [0 for _ in range(k)] # k长度
x = [0 for _ in range(n)] # n长度
bestx = [0 for _ in range(n)] # n长度
search(0, len, t)
print("最优值:", best)
print("最优解:", bestx)
最优值: 26
最优解: [1, 2, 2, 2, 3, 4, 4, 1, 3]