【问题标题】:Matrix chain multiplication algorithm矩阵链乘法算法
【发布时间】:2015-03-29 18:32:35
【问题描述】:

我正在阅读 Thoman Cormen 的“算法简介”,但我无法理解下面写的算法。

        Matrix-Chain-Order(p)
        1 n ← length[p] − 1
        2 for i ← 1 to n
        3     do m[i, i] ← 0
        4     for l ← 2 to n                     //l is the chain length.
        5         do for i ← 1 to n − l + 1      // what is this?
        6                do j ← i + l − 1        // what is this?
        7                   m[i, j] ← ∞
        8                   for k ← i to j − 1
        9                       do q ← m[i, k] + m[k + 1, j] + pi−1pkpj
       10                          if q < m[i, j]
       11                            then m[i, j] ← q
       12                                s[i, j] ← k
       13 return m and s

现在,我知道算法是如何工作的了。我知道如何继续构建表格和所有这些。换句话说,我知道直到第 4 行会发生什么,我也知道第 9 到 13 行是关于什么的。 我在理解“for”循环的微妙之处时遇到了问题。第 4 到 8 行很难理解。在第 5 行中,为什么 i 上升到 n-l+1,为什么第 6 行中的 j 设置为 i+l-1。在第 7 行,m[i, j] 为第 10 行的比较而初始化,但第 8 行又是一个谜。

【问题讨论】:

    标签: algorithm matrix matrix-multiplication


    【解决方案1】:

    我刚刚浏览了wikipedia 上的算法定义,那里的内容非常全面。我将尝试向您解释我是如何理解解决方案的。

    问题的症结在于我们基本上是在尝试“加括号”,即优先考虑我们如何链接我们的矩阵,以便它们最有效地相乘,这反映在这行代码中:

    q = m[i,k] + m[k+1,j] + p[i-1]*p[k]*p[j];
    

    要理解上述立场,首先让我们确定 ij 在这里是固定的,即我们正在尝试计算 m[i,j] 或矩阵乘法 A[i..j]k 的最有效方法是变量。

    所以如果i=1j=3 和矩阵是:

    (A*B)*C //We are trying to establish where the outer most parenthesis should be
    

    我们不知道它应该在哪里,因此我们尝试所有可能性并选择最小化m[i,j] 的组合。所以我们尝试:

    i=1 and j=3
    A*(B*C) //k=1
    (A*B)*C //k=2
    

    很明显k 应该从ij-1 变化,这反映在循环中,因为我们尝试所有可能的组合并采用最有效的组合。所以对于任何k,我们将有两个分区:A[i..k]A[k+1...j]

    所以对于k 的这个分区,A[i..j] 的乘法成本是:

     m[i,k]  //Minimum cost of multiplication of A[i..k]
    
     m[k+1,j] //Minimum cost of multiplication of A[k+1..j]
    
     p[i-1]*p[k]*p[j]; //Final cost of multiplying the two partitions i.e. A[i..k] and A[k+1..j], where p contains the dimensions of the matrices.
    

    A 是 10 × 30 矩阵,B 是 30 × 5 矩阵,C 是 5 × 60 矩阵。然后, p[] = [10,30,5,60] 即矩阵 Ai 的维度为 p[i-1] x p[i] for i = 1..n

    这就是动态编程的全部意义所在。所以我们尝试k 的所有组合并计算m[i,j],但为此我们还需要计算m[i,k]m[k+1,j],即我们将问题分解成更小的子问题,其中引入了链长的概念。

    因此,对于所有矩阵A[i..n],我们计算出乘以长度为l 的较小矩阵链的最有效方法。

    l 的最小值显然是 2,最大值是 n,这是我们解决了我解释的较小的子问题后得到的。

    让我们来看看你难以理解的代码:

     for l ← 2 to n                     //l is the chain length.
      do for i ← 1 to n − l + 1      
      do j ← i + l − 1        
      m[i, j] ← ∞
    

    现在让我们再次考虑 4 个矩阵 H,I,J,K 的较小示例,您正在查看的第一个链长度为 2。因此,在遍历矩阵数组时。

     A[1..4] = H,I,J,K //where A[1] = H and A[4] = K
     For l = 2
     Our loop should go from i=1 to i=3, as for every i we are looking at the chain of length 2.
    
     So when i = 1, we would compute
     m[1,2] i.e. minimum cost to multiply chain (H,I)
    
     and when i = 3, we would compute
     m[3,4] i.e. minimum cost to multiply chain (J,K)
    

    当链长为 3 时,我们会:

      For i=1, j=3
      m[i,j] -> m[1,3] i.e. minimum cost to multiply chain (H,I,J)
    
      For i=2, j=4
      m[i,j] -> m[2,4] i.e. minimum cost to multiply chain (I,J,K)
    

    因此,当我们将i 定义为不超过n-l+1j=i+l-1 时,我们确保我们覆盖了数组的所有元素并且不超过边界条件,即数组的大小为@987654355 @ 和 j 定义从 i 开始的链的结尾,长度为 l

    所以问题归结为计算m[i,j] 的一些ij,正如我之前解释的那样,通过获取分区k 并尝试k 的所有可能值然后重新将m[i,j] 定义为最小值,这就是它被初始化为 的原因。

    我希望我的回答不会太长,它可以让您清楚地了解算法是如何流动的,并帮助您了解动态编程的巨大范围。

    【讨论】:

    • 谢谢。我感谢您的时间和精力。 :)
    • 不用担心@EsterVojkollari。考虑将答案标记为已接受,以便遇到类似问题的其他人也可以获得一些帮助。 :)
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 2017-09-12
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多