4、问题规模缩小。公式(2)说明一般情况下,对作业集S进行调度,在M2机器上的等待时间,除了需要等该部件在M1机器上完毕时间,还要抵冲一部分本来的等待时间,假如抵冲已成负值,自然仍需等待M1将作业做完,所以公式取max{t-ai,0}。
3、动态规划法求解思绪
假设有一组作业需要在M1和M2 两台机器上进行流水作业,他们在M1和M2上的作业时间如下表:
问题是如何安排他们的加工顺序,使得,到最后一个作业在机器M2上加工完毕所需要的时间最少。也就是所有作业在两台机器所有加工完毕所需的时间最少。
思绪如下:考虑假如只有一个作业的情况,肯定所需时间就是
5、它自身需要在M1和M2 上的加工时间总和;假如有两个作业就要考虑在两种不同的加工顺序下选取最优的一种作为候选,三个作业的时会出现三种组合情况(0,(1,2)); (1,(0,2)); (2,(0,1)),拿第一种为例,它表达先加工作业0,然后再按照作业1和作业2的优化顺序加工;将三种的作业时间计算出来,取最小值,即为三个作业的优化结果,同理可对更多的作业进行排序优化。具体做法是,用类似矩阵连乘的办法,自底向上将所有能的情况计算出来,并产生一个表,供后面的计算查用,减少反复计算的工作量。
对于j1 作业M2 的等待时间为b0,事实上在M2加工j0作业的同时,M1 并行加工j1,实
6、际它需要等待b1-a0时间。
2+4+(5-4)+2=9
从J0和J1两个作业的加工顺序,可以看出,先加工J0后J1,所用时间最短为9,将其填入表中,依此类推,即可得出最优解。
a4+a0+a2+a1+a3+[(b4+b0+b1+b2)-(a0+a1+a2+a3)]+b3
=1+2+3+4+6+[(7+5+2+3)-(2+4+3+6)]+1
=16+[17-15]+1=19
选其中加工时间短的作为候选方案;在具体计算时非最优子集不必考虑,这样可以减少计算次数。
4、流水作业调度的Johnson法则
7、 设兀是作业集S在机器M2的等待时间为t时的任一最优调度。若在这个调度中,安排在最前面的两个作业分别是i 和j ,即π(1)=I,π(2)=j。则有动态规划递归式可得
其中
假如作业i和j满足min{bi,aj} ≥min{bj,ai},则称作业i和j满足Johnson不等式。假如作业i和j 不满足Johnson不等式,则互换作业i和j满足Johnson不等式。
证明 :在作业集S中,对于机器M2 的等待时间为t的调度π,互换作业i和j 的加工顺序,得到作业集S 的另一个调度π’,它所需的加工时间为
当作业i和j 满足Jo
8、hnson 不等式 min{bi,aj} ≥min{bj,ai}时,有
从而
由此可得
因此,对任意t 有
从而,tij≤tji,由此可见,换句话说,当作业i 和j不满足Johnson 不等式时,互换它们的加工顺序后,作业i和j满足Johnson 不等式,且不增长加工时间。由此可知,对于流水作业调度问题,必存在最优调度π,使得作业π(i)和π(i+1)满足Johnson 不等式:
这样的调度π称为满足Johnson 法则的调度。进一步还可以证明,调度满足Johnson 法则当且仅当对任意i9、具有相同的加工时间,从而所有满足Johnson 法则的调度均为最优调度。
5、流水作业调度问题Johnson算法
从上面的分析可知,流水作业调度问题一定存在满足Johnson法则的最优调度,且容易由下面的算法拟定:
流水作业调度问题的Johnson算法:
(1)令N1={i|ai=bi};
(2)将N1中作业按ai的非减序排序;将N2中作业按bi的非增序排序;
(3)N1中作业接N2中作业构成满足Johnson法则的最优调度。
Johnson算法中分类及排序的作用(验证不等式)设数组c[]为
10、排序后的作业排列,排序结果如下:
红线左侧满足 a[c[i]]<=b[c[i]] 和 a[c[i]]<=a[c[i+1]] 符合johnson 不等式,min(b[c[i]],a[c[i+1]])>=min(b[c[i+1]],a[c[i]])其调度顺序最优;
红线右侧满足 b[c[i]]<=a[c[i]] 和 b[c[i]]>=b[c[i+1]] 符合johnson 不等式,min(b[c[i]],a[c[i+1]])>=min(b[c[i+1]],a[c[i]])其调度顺序最优;
中间过渡部分横向比较,左侧a[c[i]]< b[c[i]] 右侧b[
11、c[i+1]]<=a[c[i+1] ]满足min(b[c[i]],a[c[i+1]])>=min(b[c[i+1]],a[c[i]])其调度顺序也最优;
程序具体代码如下:
[cpp] view plain copy
1. //3d9 动态规划 流水作业调度问题
2. #include "stdafx.h"
3. #include
4. using namespace std;
5.
6. const int N = 5;
7.
8. class Jobtype
9. {
10. pub
12、lic:
11. int operator <=(Jobtype a) const
12. {
13. return(key<=a.key);
14. }
15. int key,index;
16. bool job;
17. };
18.
19. int FlowShop(int n,int a[],int b[],int c[]);
20. void BubbleSort(Jobtype *d,int n);//本例采用冒泡
13、排序
21.
22. int main()
23. {
24. int a[] = {2,4,3,6,1};
25. int b[] = {5,2,3,1,7};
26. int c[N];
27.
28. int minTime = FlowShop(N,a,b,c);
29.
30. cout<<"作业在机器1上的运营时间为:"<14、]<<" ";
34. }
35. cout<15、
45. for(int i=0; i16、
58. d[i].key = a[i]>b[i]?b[i]:a[i];//按Johnson法则分别取相应的b[i]或a[i]值作为关键字
59. d[i].job = a[i]<=b[i];//给符合条件a[i]
17、for(int i=0; i18、 }
78.
79. j = a[c[0]];
80. k = j+b[c[0]];
81. for(int i=1; i19、eturn k;
89. }
90.
91. //冒泡排序
92. void BubbleSort(Jobtype *d,int n)
93. {
94. int i,j,flag;
95. Jobtype temp;
96.
97. for(i=0;ii;j--){
100. //假如前一个数大于后一个数,则互换
101.
20、 if(d[j]<=d[j-1]){
102. temp = d[j];
103. d[j] = d[j-1];
104. d[j-1] = temp;
105. flag = 1;
106. }
107. }
108. //假如本次排序没有进行一次互换,则break,减少了执行之间。
109. if(flag == 0){
110. break;
111. }
112. }
113. }
运营结果如下: