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)\)是指所有作业都完成的时间:
平均流动时间(mean flow time)\(MFT(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)\)。
定理:流水作业调度问题具有最优子结构的性质
由流水作业调度问题的最优子结构性质可知:
上式推广到一般情况,对任意作业子集S和作业i有:
\(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下最先处理的两个作业。根据最优子结构性质有:
式中
如果在调度方案的作业排序中,上述作业i和j满足\(\min\{b_i,a_j\}\geq\min\{b_j,a_i\}\),则称作业i和j满足Johson不等式。
交换作业i和j大的次序,得到另一种调度方案\(R'\),设其完成时间为\(g'(S,t)\),则有:
式中,\(t_{ij}=b_j+b_i-a_j-a_i+\max\{t,a_i+a_j-b_j,a_j\}\)
假定i和j满足Johnson不等式,则有:
所以如果两个作业i和j不满足Johnson不等式,可交换它们的处理次序使之满足,这样就不会增加完成时间。
因此,存在一个最优作业调度,使得对于任意相邻的两个作业i和j,作业i先于j处理,都有\(\min\{b_i,a_j\}\geq\min\{b_j,a_i\}\)。进一步可知,一个调度方案\(\sigma\)是最优的当且仅当对任意\(i<j\),有
根据以上的讨论,可以设计下列作业排序方法。这样做能得到最优调度方案:
- 如果\(\min\{a_0,a_1,\cdots,a_{n-1},b_0,b_1,\cdots,b_{n-1}\}\)是\(a_i\),则\(a_i\)应是最优排列的第一个作业;
- 如果\(\min\{a_0,a_1,\cdots,a_{n-1},b_0,b_1,\cdots,b_{n-1}\}\)是\(b_j\),则\(b_j\)应是最优排列的最后一个作业;
- 继续1和2的做法,直到完成所有作业的排序。
Johnson算法
求解流水作业调度问题的Johnson算法具体描述如下。
- 设a[i]和b[i](\(0\leq i<n\)) 分别为作业i在两台设备上的处理时间。建立由三元组(作业号,处理时间,设备号)组成的三元组表d。其中,处理时间是指每个作业所包含的两个任务中时间较少的处理时间。
- 对三元组表按处理时间排序,得到排序后的三元组表d。
- 对三元组表的每一项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)\)。

浙公网安备 33010602011771号