【问题标题】:Dynamic Programming algorithms and real world usage动态规划算法和现实世界的使用
【发布时间】:2012-02-27 19:48:45
【问题描述】:

我过去研究过经典的 DP 问题和算法(硬币、最长递增子序列、最长公共子序列等)。

我知道这些算法有实际应用(例如遗传算法,仅举一个例子)。但我的疑问是,这些算法是否在现代计算机科学中具有实际应用,在现代计算机科学中,输入的规模非常大,并且仅在一台机器上无法解决问题。

我的观点是,这些算法很难并行化(即Parallel Dynamic Programming),而且在大多数公式中内存占用是二次方的,因此很难处理相当大的输入。

有人有这方面的真实用例吗?

【问题讨论】:

  • 内存占用是二次方的,但节省的时间值得每个字节。编写基于递归关系计算斐波那契数列的程序的 2 个实现,一个有缓存,另一个没有。配置文件,并查看结果。
  • @UmNyobe:fibonachi 不是一个很好的例子,它可以在O(1) 中解决:) [当然我同意你的观点]。
  • 这就是为什么我说基于递归关系。我以斐波那契为例,因为它可以在 30 分钟内完成。
  • Fibonacci 使用的是记忆,而不是 DP。我同意这是相关的。
  • LCS 可以使用线性空间求解。我认为,通过在 LCS 上设置一个最大界限,时间也可以降低到线性。

标签: algorithm dynamic-programming


【解决方案1】:

实际应用:diff。这是一个必不可少的 Linux 实用程序,它通过使用 DP 算法解决longest common subsequence 问题来发现两个文件之间的差异。

使用 DP 算法是因为在许多情况下它们是唯一实用的解决方案。而且,它们并没有什么问题。

内存使用量: 通常,可以使用滑动窗口来显着减少内存使用量。使用朴素的自下而上 DP 求解斐波那契时,需要 O(n) 内存。滑动窗口将其提高到 O(1) 内存(我知道 magical constant time solution,但这不是重点)。

并行化:自上而下的 DP 通常很容易并行化。自下而上可能是也可能不是。 @amit 的例子(并行化最长公共子序列)是一个很好的例子,只要知道前面的对角线,任何给定的对角线的瓦片都可以独立求解。

【讨论】:

    【解决方案2】:

    The longest common subsequence问题和Longest common substring problem有时对于分析字符串很重要[例如分析基因序列]。并且可以使用动态规划有效地解决它们。

    注意您可以并行化此算法:您可以在对角线上 [从左、下到右、上] 进行迭代 - 所以总共有 2n-1 次迭代。并且在每个对角线中:每个单元不依赖于该对角线中的其他单元 - 因此可以在这里进行并行化,每个线程将在该对角线上有一个单元块。

    请注意,使用这种方法的数据同步也是最小的:每个线程只需将数据传输到他的“相邻线程”,因此即使内存不共享也可以完成。

    另外,正如@larsmans 所提到的,这两个问题都可以使用线性空间——在每一点你只需要“记住”当前 + 2 个最后对角线,而不是整个矩阵。

    另一个使用动态编程解决的常见问题polynomial interpolation。使用Newton Interpolation 可以有效地完成插值,首先需要计算divided differences - 这是使用动态规划构建的。

    【讨论】:

    • 我知道它们对遗传算法很有用(我改进了这个问题)。我质疑这些对于非平凡的输入大小是否实用。
    • @SavinoSguera:(1)我编辑并添加了一个额外的应用程序用于实际的 dp。 (2) 我在回答中介绍了如何并行化这个算法——所以这些算法是可扩展的,使用这些并行化方法。您甚至可以迭代地使用map reduce 并动态构建矩阵,因为每次迭代中的数据 [正如我所展示的那样] 并不相互依赖。
    • @SavinoSguera 另外,请注意genetic algorithms 和遗传分析算法不是一回事
    猜你喜欢
    • 2020-11-05
    • 2015-02-21
    • 2011-06-26
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2012-03-26
    相关资源
    最近更新 更多