Python 实现作业排程问题

1. 问题描述

  • Automobile factory with two assembly lines
    • Each line has n stations: $S_{1, 1},...,S_{1, n}$ and $S_{2, 1},...,S_{2, n}$
    • Corresponding stations $S_{1, j}$ and $S_{2, j}$ perform the same function but can take different amounts of time $a_{1, j}$ and $a_{2, j}$
    • Entry times $e_1$ and $e_2$ and exit times $x_1$ and $x_2$

装配线问题示意图

给出一个示例的装配线,要求输出最优的排程方案

2. 思路分析

首先, 利用动态规划思想找出递归关系, 这个是最重要的一步

递归式

这里的 $f_1[j]$ 表示在第一条装配线的第 j 个站台处理完之后所花费的最少的时间. $f_2[j]$ 也是同理.

然后, 根据这个关系, 我们就可以自底向上构建 $f_1$$f_2$ 这两个数组了.

伪码描述如下

伪码

3. 代码实现

# 最优排程问题
def fastest_way(a:list, t:list, e:list, x:list, n:int) -> list:
    '''
    解决最优排程问题
    :param a: 两条线上各自的每个站点的各自处理时间
    :param t: 两条线上各自的每个前 n - 1 个站点的切换时间
    :param e: 两条线的各自的 entry 时间
    :param x: 两条线的各自的 exit 时间
    :param n: 每条线的工作站的数目
    :return: 最优时间, 路径和最后一个走过的工作站点
    '''
    # 两条线上每个站的处理时间
    a1, a2 = a # 自动解包
    # 两条线在第 i 个站换线需要的时间
    t1, t2 = t
    # 两条线上 e 和 x 的数值
    e1, e2 = e
    x1, x2 = x
    # 两条线在每个装配点所花费的最小时间表(动态规划)
    f1 = [0 for i in range(n)]
    f2 = [0 for i in range(n)]
    route = [[0 for i in range(n)], [0 for i in range(n)]]  # 存储路径
    time = float('inf') # 最优时间
    final_line = 0 # 最后一个节点所在的线路
    # 初始化
    f1[0] = e1 + a1[0]
    route[0][0] = 1 # 1 表示走第一条线路
    f2[0] = e2 + a2[0]
    route[1][0] = 2 # 2 表示走第二条线路
    for i in range(1, n):
        if f1[i - 1] + a1[i] < f2[i - 1] + t2[i - 1] + a1[i]:
            f1[i] = f1[i - 1] + a1[i]
            route[0][i] = 1
        else:
            f1[i] = f2[i - 1] + t2[i - 1] + a1[i]
            route[0][i] = 2
        if f2[i - 1] + a2[i] < f1[i - 1] + t1[i - 1] + a2[i]:
            f2[i] = f2[i - 1] + a2[i]
            route[1][i] = 2
        else:
            f2[i] = f1[i - 1] + t1[i - 1] + a2[i]
            route[1][i] = 1
    if (f1[n - 1] + x1 < f2[n - 1] + x2):
        time = f1[n - 1] + x1
        final_line = 1
    else:
        time = f2[n - 1] + x2
        final_line = 2
    return [time, route, final_line]

def print_route(i:int, j:int, route:list, n:int):
    '''
    递归打印装配的线路图
    :param i: 装配线, 0 represents the first assembly line, 1 represents the second line
    :param j: 当前节点
    :param route: 存储两条线路的节点的父节点的 list
    :param n: 装配线的节点数
    :return: None
    '''
    if j == 1:
        print('[Line: ' + str(i) + ' Station: ' + str(j) + ']', end=' ')
    else:
        print_route(route[i - 1][j - 1], j - 1, route, n)
        print('[Line: ' + str(i) + ' Station: ' + str(j) + ']', end=' ')
    if j != n:
        print('=>', end=' ')
    else:
        print()

if __name__ == '__main__':
    n = 5  # 每条线工作站的数目
    # 两条线上每个站的处理时间
    a1 = [7, 9, 3, 4, 8]
    a2 = [8, 5, 6, 4, 5]
    # 两条线在第 i 个站换线需要的时间
    t1 = [2, 3, 1, 3]
    t2 = [2, 1, 2, 2]
    # 两条线上 e 和 x 的数值
    e1 = 2
    e2 = 4
    x1 = 3
    x2 = 6
    a = [a1, a2]
    t = [t1, t2]
    e = [e1, e2]
    x = [x1, x2]
    res = fastest_way(a, t, e, x, n)
    time, route, final_line = res
    print('The shortest time:', time)
    print('The best assembly line is: ', end='')
    print_route(final_line, 5, route, n)

输出

The shortest time: 35
The best assembly line is: [Line: 1 Station: 1] => [Line: 2 Station: 2] => [Line: 1 Station: 3] => [Line: 1 Station: 4] => [Line: 1 Station: 5] 

Python 实现作业排程问题
http://fanyfull.github.io/2021/05/26/Python-实现作业排程问题/
作者
Fany Full
发布于
2021年5月26日
许可协议