0x07算法设计与分析复习(二):算法设计策略-动态规划法5

参考书籍:算法设计与分析——C++语言描述(第二版)

算法设计策略-动态规划法

流水作业调度

问题描述

假定处理一个作业需要执行若干项不同类型的任务,每一类任务只能在某一台设备上执行。设一条流水线上有n个作业\(J=\{J_0,J_1,\cdots,J_{n-1}\}\)和m台设备\(P=\{P_1,P_2,\cdots,P_m\}\)。每个作业需依次执行m个任务,其中第\(j(1\leq j\leq m)\)个任务只能在第j台设备上执行。所谓依次执行,是指对任意作业,在第j-1项任务完成之前,第j项任务不能开始处理。且每台设备任何时刻只能处理一项任务。设第i个作业的第j项任务\(T_{ij}\)所需的时间为\(t_{ji}(1\leq j\leq m,0\leq i<n)\)。如何将这\(n\times m\)个任务分配给m台设备,使得这n个作业都能顺利完成,这就是流水线作业调度(flow shop schedule)

对于流水线上的作业调度,有两种基本的方式,一种是非抢先调度(nonpreemptive schedule),它要求在一台设备上处理一项任务,必须等到该任务处理完毕才能处理另一项任务。另一种是抢先调度(preemptive schedule),它允许暂时中断当前任务,转而先处理其他任务,随后再接着处理被暂时中断的任务。

作业i的完成时间\(f_i(S)\)是指再调度方案S下,该作业的所有任务都已完成的时间。一种调度方案S的完成时间\(F(S)\)是指所有作业都完成的时间:

\[F(s)=\underset{0\leq i<n}{\max}\{f_i(S)\} \]

平均流动时间(mean flow time)\(MFT(S)\)定义为:

\[MFT(S)=\frac{1}{n}\sum_{i=0}^{n-1}f_i(S) \]

一组给定的作业的最优完成时间\(F(S)\)的最小值。

OFT表示非抢先调度最优完成时间

POMT:表示抢先调度最优完成时间

OMFT:表示非抢先调度最优平均完成时间

POMFT:表示抢先调度最优平均完成时间

对于\(m>2\),要得到具有OFT和POFT的调度方案是困难的,要得到具有OMFT的调度方案也是困难的。

下面只讨论当\(m=2\)时获得OFT的调度方案的算法,这就是双机流水作业调度问题。为方便,用\(a_i\)表示\(t_{1i}\)\(b_i\)表示\(t_{2i}\),两者分别为作业i再第一台设备和第二台设备上的处理时间。作为对比,批处理作业调度问题是求使得所有作业的完成时间之和\(FT(S)=\sum_{i=0}^{n-1}f_i(S)\)最小的调度方案。(务必不要将两者弄混)

双机流水作业调度描述为:设有n个作业的集合\(\{0,1,2,\cdots,n-1\}\),每个作业都有两项任务要求再两台设备\(P_1\)\(P_2\)组成的流水线上完成加工。每个作业的加工顺序总是先再\(P_1\)上加工,然后\(P_2\)加工。\(P_1\)\(P_2\)加工作业i所需的时间分别为\(a_i\)\(b_i\)。流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在设备\(P_1\)上开始加工,到最后一个作业在\(P_2\)上加工完成所需的时间最少,即求使\(F(S)\)有最小值的调度方案。

动态规划法求解

设全部作业的集合为\(N=\{0,1,\cdots,n-1\}\)。设\(\sigma=\{\sigma(0),\sigma(1),\cdots,\sigma(k-1)\}\)是k个作业的一种调度方案,\(f_1\)\(f_2\)分别是在设备\(P_1\)\(P_2\)上,按该调度方案处理k个作业的时间。在\(P_1\)完成前\(k\)个作业的处理后,设备\(P_2\)还需用\(t=f_2-f_1\)时间去处理完前k的作业中没有完成处理的作业,即在t时间之前,设备\(P_2\)不能开始处理以后的作业。设这些剩余额作业组成的作业集为S,\(S\subseteq N\)是N的作业子集。令\(g(S,t)\)为假定设备\(P_2\)直到\(t\)时间后才可使用的情况下,使用设备\(P_1\)\(P_2\)处理S中作业的最优调度方案所需的最短时间。那么流水作业调度问题的最优值为\(g(N,0)\)

定理:流水作业调度问题具有最优子结构的性质

由流水作业调度问题的最优子结构性质可知:

\[g(N,0)=\underset{0\leq i<n}{\min}\{a_i+g(N-\{i\},b_i)\} \]

上式推广到一般情况,对任意作业子集S和作业i有:

\[g(S,t)=a_i+g(S-\{i\},t'),\quad t'=b_i+\max \{t-a_i,0\} \]

\(t'=b_i+\max \{t-a_i,0\}\)是因为任务\(b_i\)\(\max\{a_i,t\}\)之前不能在设备\(P_2\)上处理,因此,当作业i处理完毕时,有\(f_2-f_1=b_i+\max\{a_i,t\}-a_i=b_i+\max\{t-a_i,0\}\)\(t'\)决定了集合\(S-\{i\}\)中的作业在\(P_2\)上可以开始处理的时间。

Johnson不等式

设R是关于作业集合S的任一调度方案。假定设备\(P_2\)在t时间之后可使用,令i和j是在方案R下最先处理的两个作业。根据最优子结构性质有:

\[g(S,t)=a_i+g(S-\{i\},b_i+\max\{t-a_i,0\})=a_i+a_j+g(S-\{i,j\},t_{ij}) \]

式中

\[\begin{aligned} t_{ij}&=b_j+\max\{b_i+\max\{t-a_i,0\}-a_j,0\}\\ &=b_j+b_i-a_j+\max\{\max\{t-a_i,0\},a_j-b_i\}\\ &=b_j+b_i-a_j+\max\{t-a_i,a_j-b_i,0\}\\ &=b_j+b_i-a_j-a_i+\max\{t,a_i+a_j-b_i,a_i\} \end{aligned} \]

如果在调度方案的作业排序中,上述作业i和j满足\(\min\{b_i,a_j\}\geq\min\{b_j,a_i\}\),则称作业i和j满足Johson不等式

交换作业i和j大的次序,得到另一种调度方案\(R'\),设其完成时间为\(g'(S,t)\),则有:

\[g'(S,t)=a_i+a_j+g(S-\{i,j\},t_{ji}) \]

式中,\(t_{ij}=b_j+b_i-a_j-a_i+\max\{t,a_i+a_j-b_j,a_j\}\)

假定i和j满足Johnson不等式,则有:

\[\begin{aligned} &\max\{-b_i,-a_j\}\leq\max\{-b_j,-a_i\}\\ &a_i+a_j+\max\{-b_i,-a_j\}\leq a_i+a_j+\max\{-b_j,-a_i\}\\ &\max\{a_i+a_j-b_i,a_i\}\leq\max\{a_i+a_j-b_j,a_j\}\\ &\max\{t,a_i+a_j-b_i,a_i\}\leq \max\{t,a_i+a_j-b_j,a_j\} \end{aligned} \]

所以如果两个作业i和j不满足Johnson不等式,可交换它们的处理次序使之满足,这样就不会增加完成时间。

因此,存在一个最优作业调度,使得对于任意相邻的两个作业i和j,作业i先于j处理,都有\(\min\{b_i,a_j\}\geq\min\{b_j,a_i\}\)。进一步可知,一个调度方案\(\sigma\)是最优的当且仅当对任意\(i<j\),有

\[\min\{b_{\sigma(i)},a_{\sigma(j)}\}\geq\min\{b_{\sigma(j)},a_{\sigma(i)}\} \]

根据以上的讨论,可以设计下列作业排序方法。这样做能得到最优调度方案:

  1. 如果\(\min\{a_0,a_1,\cdots,a_{n-1},b_0,b_1,\cdots,b_{n-1}\}\)\(a_i\),则\(a_i\)应是最优排列的第一个作业;
  2. 如果\(\min\{a_0,a_1,\cdots,a_{n-1},b_0,b_1,\cdots,b_{n-1}\}\)\(b_j\),则\(b_j\)应是最优排列的最后一个作业;
  3. 继续1和2的做法,直到完成所有作业的排序。

Johnson算法

求解流水作业调度问题的Johnson算法具体描述如下。

  1. 设a[i]和b[i](\(0\leq i<n\)) 分别为作业i在两台设备上的处理时间。建立由三元组(作业号,处理时间,设备号)组成的三元组表d。其中,处理时间是指每个作业所包含的两个任务中时间较少的处理时间。
  2. 对三元组表按处理时间排序,得到排序后的三元组表d。
  3. 对三元组表的每一项d[i](\(0\leq i<n\)),从左右两端生成最优作业排列c[j](\(0\leq j<n\)),c[j]是作业号。如果d[i]的设备号为1,则将作业i置于c的左端末尾,否则置于c的右端末尾。
//Johnson算法
struct Triplet{
    //三元组结构
    int operator <(Triplet b)const {return t<b.t;}
    int jobNo,t,ab;//jobNo为作业号,t为处理时间,ab为设备号
};

void FlowShop(int n,int *a,int *b,int *c)
{
    Triplet d[mSize]={{0,0,0}};
    for(int i=0;i<n;i++){
        //算法步骤一,生成三元组表d
        if(a[i]<b[i]){
            d[i].jobNo=i;
            d[i].ab=0;
            d[i].t=a[i];
        } else {
            d[i].jobNo=i;
            d[i].ab=1;
            d[i].t=b[i];
        }
    }
    Sort(d,n);//算法步骤二,任意排序算法
    int left=0,right=n-1;
    for(i=0;i<n;i++){
        //算法步骤三,生成最优解
        if(d[i].ab==0)
            c[left++]=d[i].jobNo;
        else
            c[right--]=d[i].jobNo;
    }
}

Johnson算法的时间取决于对作业集的排序,因此最坏情况下算法的时间复杂度为\(O(n\log n)\),所需空间复杂度为\(O(n)\)

posted @ 2018-01-09 11:05  main_c  阅读(578)  评论(0)    收藏  举报