矩阵链乘法算法

时间:2015-03-29 18:32:35

标签: algorithm matrix matrix-multiplication

我正在阅读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行中,为什么我要达到n-l + 1,为什么第6行中的j设置为i + l-1。在第7行中,m [i,j]被初始化以用于第10行的比较,但是第8行又是一个谜。

1 个答案:

答案 0 :(得分:2)

我刚刚在wikipedia上进行了算法定义,并且在那里非常全面。我会试着向你解释我是如何理解解决方案的。

问题的关键在于我们基本上试图“加括号”,即优先考虑我们如何链接矩阵以使它们最有效地倍增,并且它反映在这行代码中:

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

要理解上述立场,首先让我们确定ij是固定的,即我们试图计算m [i,j]或最有效的乘法矩阵方法{{1 }和A[i..j]是变量。

如果ki=1以及矩阵是:

,则处于非常高的水平
j=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] 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时,我们确保覆盖数组的所有元素并且不超过边界条件,即大小nj数组定义了从长度为i的{​​{1}}开始的链的末尾。

问题归结为计算某些lm[i,j]的{​​{1}},正如我之前解释的那样,通过采用分区i并尝试所有可能的值来解决j然后重新定义k作为最小值,这就是它被初始化为k的原因。

我希望我的答案不会太长,它可以让您清楚算法的流程,并帮助您理解动态编程的巨大变化。