算法设计与分析 实验四 动态规划求解流水线问题
Posted 上山打老虎D
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法设计与分析 实验四 动态规划求解流水线问题相关的知识,希望对你有一定的参考价值。
动态规划求解流水线问题
一、实验目的与要求
1. 实验目的:
(1) 掌握动态规划算法设计思想。
(2) 掌握流水线问题的动态规划解法。
2. 实验亮点:
(1)使用动态规划算法进行了优化,大大降低了程序的运行时间。并给出了详细的规划方程。
(2)选用了更合理的数据结构进行优化,将程序可处理的数据量上限提高到
1
0
1
3
10^13
1013并将程序运行的时间降低至
1
/
100
1/100
1/100。
(3)每个算法均有详细的伪代码描述。并对不同数据量级下做对比并做出数据折线图。
(4)对算法的正确性进行了逻辑上与数据上的验证。
二、实验内容与方法
1. 实验内容:
汽车厂有两条流水线,每条流水线有n个处理环节(station): S 1 , 1 S_{1,1} S1,1,…, S 1 , n S_{1,n} S1,n 和 S 2 , 1 S_{2,1} S2,1,…, S 2 , n S_{2,n} S2,n,其中下标的第一个字母表示流水线编号(流水线1和流水线2)。其中 S 1 , j S_{1,j} S1,j 和 S 2 , j S_{2,j} S2,j完成相同的功能,但是花费的时间不同,分别是 a 1 , j a_{1,j} a1,j , a 2 , j a_{2,j} a2,j 。两条流水线的输入时间分别为 e 1 e_1 e1 和 e 2 e_2 e2, 输出时间是 x 1 x_1 x1 和 x 2 x_2 x2。
每个安装步骤完成后,有两个选择:
1)停在同一条安装线上,没有转移代价;
2)转到另一条安装线上,转移代价:
S
i
,
j
S_{i,j}
Si,j 的代价是
t
i
,
j
t_{i,j}
ti,j, j = 1,…,n - 1
问题: 如何选择安装线1和安装线2的节点组合,从而最小化安装一台车的总时间?
2. 实验要求:
- 给出解决问题的动态规划方程;
- 随机产生 S 1 , j S_{1, j} S1,j, S 2 , j S_{2, j} S2,j , t i , j t_{i, j} ti,j的值,对小数据模型利用蛮力法测试算法的正确性;
- 随机产生 S 1 , j S_{1, j} S1,j, S 2 , j S_{2, j} S2,j , t i , j t_{i, j} ti,j的值,对不同数据规模( n n n的值)测试算法效率,并与理论效率进行比对,请提供能处理的数据最大规模,注意要在有限时间内处理完;
- 该算法是否有效率提高的空间?包括空间效率和时间效率。
三、实验步骤与过程
(一)暴力穷举法
1、算法描述:
对于暴力穷举解决流水线问题,只需对所有组合可能进行完备穷举,并选择较小的时间消耗作为最终结果。由于暴力法是对每一种解的完备搜索,因此暴力法的正确性有很高的保证。
2、时间复杂度分析:
对于一条流水线上的每个单元,存在两种选择,即选择在流水线1上或在流水线2上。因此,对于 n n n个单元,存在 2 n 2^n 2n种不同的选择。因此暴力穷举法时间复杂度为 O ( 2 n ) O(2^n ) O(2n)
3、编程实现:
伪代码如下
//find each combination by binary
bitset<LEN> flagBit;
//least cost
int res = 1e9
//cost of chassis enters
int e[2]
//cost of each station
int a[2][LEN]
//cost of transform
int t[2][LEN]
//Use binary to brute force each combination
while (flagBit!=0):
//Use binary to identify the combination
//'0' for line 0, '1' for line 1
currentCost = 0
//chassis enters
if (flagBit[0] == 0):
currentCost += (e[0] + a[0][0])
else:
currentCost += (e[1] + a[1][0])
//each station
for i from 1 to LEN:
//cost of a station
currentCost += a[flagBit[i]][i]
//if transform
if flagBit[i] != flagBit[i - 1]
currentCost += t[flagBit[i - 1]][i - 1]
res = min(res, currentCost)
flagBit--
print(res)
①通过二进制表示每个流水线的选择情况,如果为0则选择第一个流水线,如果为1则选择第二个流水线
②在循环中进行判断,如果当前环节流水线与上一环节的流水线不相同,则需额外加上转移流水线消耗的时间。
③进入流水线与退出流水线的消耗时间直接加到当前运行时间即可
④完成一次可能的计算后,将当前时间消耗值与当前最小时间消耗值进行比较,如果小于当前最小时间消耗值,则进行更新。
⑤完成所有可能的穷举后即可获得最小时间消耗值。
4、运行并测试:
使用随机数生成器生成了不同大小的多组测试数据。为了避免运行时的偶然情况,对于每个数量级下的多组数据进行20次测试并取平均值作为该数据量级下的结果,并统计如下:
数据量 | 21 | 22 | 23 | 24 | 25 |
---|---|---|---|---|---|
时间消耗 | 1365.37 | 2801.65 | 5773.67 | 11980 | 24755.9 |
数据量 | 26 | 27 | 28 | 29 | 30 |
时间消耗 | 50664.1 | 103965 | 210728 | 436047 | 893954 |
选取数据量为25时的运行时间为理论值,将各个数据取对数并作图如下:
通过分析可知,对于全体数据,时间复杂度大致满足
O
(
2
n
)
O(2^n )
O(2n),证明时间复杂度分析是正确的。通过观察图像,我们也可以发现,当数据量较小时,实际运行时间要比理论运行时间短这是因为算法运行过程中每运行一次都要开辟动态空间,每次开辟空间均会对后面算法的执行造成影响。当数据量较小时,已经开辟的动态空间较少,对算法影响小,因此会比较快;但当数据量较大时,已经开辟了很多空间,对算法影响较大,因此会比较慢。
(二)动态规划法
1、算法描述:
(1)分析规划过程:
通过分析,我们可以知道,当流水线运行到第j个配件站是最优的,则到达该配件站前可能为
S
(
1
,
j
−
1
)
S(1,j-1)
S(1,j−1)或
S
(
2
,
j
−
1
)
S(2,j-1)
S(2,j−1),且到达
S
(
1
,
j
−
1
)
S(1,j-1)
S(1,j−1)或
S
(
2
,
j
−
1
)
S(2,j-1)
S(2,j−1)的路径同样也为最短的。即到达S(1,j)的最优解包含了到达
S
(
1
,
j
−
1
)
S(1,j-1)
S(1,j−1)或
S
(
2
,
j
−
1
)
S(2,j-1)
S(2,j−1)的最优解。对于通过的最优路线,必然通过了流水线1或流水线2的
j
−
1
j-1
j−1配件站。因此,通过
S
(
1
,
j
)
S(1,j)
S(1,j)的最优路线只能是如下两种选择:
①通过配件站
S
(
1
,
j
−
1
)
S(1,j-1)
S(1,j−1),然后直接到达
S
(
1
,
j
)
S(1,j)
S(1,j)
②通过配件站
S
(
2
,
j
−
1
)
S(2,j-1)
S(2,j−1),然后从流水线2到流水线1最后到达
S
(
1
,
j
)
S(1,j)
S(1,j)
由于流水线1与流水线2是完全对称的,因此需要找到到达某一配件站的最短时间,只需解决两个子问题的最短时间,并通过对子问题的求解最后构造出整个问题的最优解即可。
(2)分析动态规划方程:
首先我们将到达最后出口的最短时间记作
f
∗
f^*
f∗,流水线长度都为
n
n
n,则有:
f
∗
=
m
i
n
(
f
1
[
n
]
+
x
1
,
f
2
[
n
]
+
x
2
)
f^*=min(f_1 [n]+x_1,f_2 [n]+x_2 )
f∗=min(f1[n]+x1,f2[n]+x2)
当进入流水线第一个环节时,则可得:
f
1
[
1
]
=
e
1
+
a
1
,
1
f_1 [1]=e_1+a_{1,1}
f1[1]=e1+a1,1
f
2
[
1
]
=
e
2
+
a
2
,
1
f_2 [1]=e_2+a_{2,1}
f2以上是关于算法设计与分析 实验四 动态规划求解流水线问题的主要内容,如果未能解决你的问题,请参考以下文章