引入:何为流水线问题

有\(n\)个任务,对于每个任务有\(m\)道工序,每个任务的\(m\)道工序必须在不同的m台机器上依次完成才算把这个任务完成,在前\(i-1\)道工序完成后才能去完成第\(i\)道工序。对于每一个任务的每一道工序在每一台机器上需要的时间都是不同的,求最短完成所有任务的时间,也就是最后一个任务的最后一道工序的完成时间。

流水线问题分为可抢先调度和非抢先调度。在现实生活中,某些时候某个任务会因为突发情况而获得较高的优先级,那么我们就会停下正在做的任务,直接开始这个优先级较高的问题,这就是抢先调度。

由于抢先调度和多流水线的情况比较复杂,所以我们在比赛中很难碰见碰见了就意味着你有更多的时间去写剩下的两道题多吼哇,所以我们只研究非抢先调度的双流水线调度问题。

双流水线问题所具有的适合动态规划的性质

假设第一个机器为\(M1\),第二个机器为\(M2\),第\(i\)个任务在第一个机器上所需的时间是\(a_i\),在第二个机器上所需的时间是\(b_i\)。肯定存在某个最优的策略使得\(M2\)接受的任务的先后顺序和\(M1\)接受的任务顺序一模一样。

在最优策略下,\(M1\)肯定是没有空闲时间的,而\(M2\)只有两种状态,一种是空闲的,一种是任务积压着。不管对于那种状态,\(M2\)接受任务的顺序跟\(M1\)保持一致显然是最优的,因为这样会使\(M2\)的空闲时间最少,也就会使最后一个任务的第二道工序更快完成。

我们令\(T\)(\(s\),\(t\))表示当\(M1\)开始处理任务集合\(s\)时,\(M2\)还需要时间\(t\)才能投入使用,最后完成任务集合\(s\)的最快时间。那么对于非抢先调度问题的答案就是\(T\)(\(N\),\(0\))。

假设最优策略选择第\(i\)个任务最先做,显然答案就是\(a_i\)+\(T\)(\(N-\){\(i\)},\(b_i\))。

再推广一点,对于每个\(T\)(\(s\),\(t\)),都满足\(T\)(\(s\),\(t\))=\(min\){\(a_i\)+\(T\)(\(s-\){\(i\)},\(b_i+max\)(\(t-a_i\),0))}。意思就是在\(M2\)还需要\(t\)时间才能投入使用来执行任务集合\(s\)内的任务时,\(M1\)优先执行任务集合\(s\)里的任务,并且选择第\(i\)号任务为集合\(s\)里第一个被执行的任务,所以在执行\(a_i\)时,\(M2\)的等待时间\(t\)自然也会减少,但是就算\(M2\)上的任务清空了也只能等着\(M1\)这边的任务第一道工序加工完才能再次工作,所以后面的等待时间是\(b_i+max\)(\(t-a_i\),\(0\)),而剩下的任务集合就是\(s-\){\(i\)}。

显然这个动态规划是正确的,但是由于任务的数量过多和任务耗时较长,这个方法并不能很好的解决双流水线非抢先调度问题。

算法进化:\(Jhonson\)登场

假设在最优策略下,对于任务集合\(s\),在\(T\)(\(s\),\(t\))的情况下,第一个在\(M1\)上执行的是\(i\)号任务,第二个是\(j\)号。那么\(T\)(\(s\),\(t\))就可以转化成\(a_i+T\)(\(s-\){\(i\)},\(b_i+max\) (\(t-a_i\),\(0\))),再转化成\(a_i+a_j+T\)(\(s-\){i,j},\(t_{ij}\))。

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

在最外层的\(max\)里提出一个\(b_i-a_j\):

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

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

再提一个\(-a_i\)出来:

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

那么在最优策略下,先\(i\)后\(j\)和先\(j\)后\(i\)的区别就只能在那个\(max\)里体现出来了。而\(max\)也刚好影响着\(M2\)的空闲时间,也就是最后答案。那么我们把先\(i\)后\(j\)和先\(j\)后\(i\)的\(max\)分别写出来,他们满足下面这个关系:

\[max(t,a_i,a_i+a_j-b_i)\leqslant max(t,a_j,a_i+a_j-b_j)\]

先假设\(t\)为一个极小值,把它的影响抹去,我们化简一下:

\[max(a_i,a_i+a_j-b_i)\leqslant max(a_j,a_i+a_j-b_j)\]

\[a_i+a_j+max(-a_j,-b_i)\leqslant a_i+a_j+max(-a_i,-b_j)\]

见证奇迹的时刻到了!!我们再次化简!

\[max(-a_j,-b_i)\leqslant max(-a_i,-b_j)\]

等价于:

\[min(a_i,b_j)\leqslant min(a_j,b_i)\]

可是,也许最开始\(max\)里的\(t\)消失得不明不白,这个时候我们反着推回去,只需要满足\(min(a_i,b_j)\leqslant min(a_j,b_i)\)的话,对于任意\(t\)也就必然满足\(max(t,a_i,a_i+a_j-b_i)\leqslant max(t,a_j,a_i+a_j-b_j)\)了。所以只需要满足\(min(a_i,b_j)\leqslant min(a_j,b_i)\)就是最优的调度决策。

于是乎,传说中的\(Jhonson\)表达式就出炉了。对于任何双流水线非抢先调度问题的最优解,任意相邻的\(i,j\)都满足\(Jhonson\)表达式,因为任意相邻的\(i,j\)都有这个比较法则和小于号的传递性,所以任意不相邻的\(i,j(i<j)\),也都满足\(Jhonson\)表达式。我们只需要按照这个式子写一个\(cmp\)函数然后\(sort\)所有的任务,就可以在\(nlogn\)的时间复杂度内解决双流水线调度问题了。

最新文章

  1. java操作hdfs实例
  2. java基础之集合框架
  3. SQL Server output经典使用
  4. LTE Module User Documentation(翻译15)——示例程序、参考场景以及故障检测和调试技巧
  5. canvas API ,通俗的canvas基础知识(三)
  6. 目标识别:Bag-of-words表示图像
  7. jquery mobile (一)
  8. 搜索框中“请输入搜索keyword”
  9. (转)C++重写、重载和重定义的区别
  10. [置顶] Adapter详解
  11. usb开发
  12. C语言程序设计第六次作业--循环结构(2)
  13. ASP.NET Core应用的错误处理[4]:StatusCodePagesMiddleware中间件如何针对响应码呈现错误页面
  14. ftp:linux下利用shell脚本添加虚拟用户并赋予权限
  15. hotmail 发送邮件 的服务器地址如下
  16. R语言 平滑连接
  17. django+uwsgi+nginx+sqlite3部署+screen
  18. js中的async await
  19. 5: EL 表达式小结
  20. linux之getenv putenv setenv和unsetenv详解

热门文章

  1. 多语言中的&ldquo;默认语言&rdquo;设置
  2. Spring标签@Aspect-实现面向方向编程(@Aspect的多数据源自动加载)——SKY
  3. windowsphone8.1学习笔记之Toast通知
  4. JavaScript 中 onload 事件绑定多个方法的优化建议
  5. centos6.9下设置nginx服务开机自动启动
  6. emmet缩写格式
  7. springcloud zuul 使用zuulfilter 修改请求路径和响应头
  8. 如何禁止eclipse对js文件的校验(building validate)
  9. db2数据库还原
  10. Swift URL encode