Matrix chain multiplication (or the matrix chain ordering problem computes, for each 2 ≤ k ≤ n, the minimum costs of all subsequences of length k using the costs of smaller subsequences already computed.
It has the same asymptotic runtime and requires no recursion.
Pseudocode:
<syntaxhighlight lang="java">
// Matrix A[i] has dimension dims[i-1] x dims[i] for i = 1..n
MatrixChainOrder(int dims[])
{
// length[dims] = n + 1
n = dims.length - 1;
// m[i,j] = Minimum number of scalar multiplications (i.e., cost)
// needed to compute the matrix A[i]A[i+1]...A[j] = A[i..j]
// The cost is zero when multiplying one matrix
for (i = 1; i <= n; i++)
m[i, i] = 0;
for (len = 2; len <= n; len++) { // Subsequence lengths
for (i = 1; i <= n - len + 1; i++) {
j = i + len - 1;
m[i, j] = MAXINT;
for (k = i; k <= j - 1; k++) {
cost = m[i, k] + m[k+1, j] + dims[i-1]*dims[k]*dims[j];
if (cost < m[i, j]) {
m[i, j] = cost;
s[i, j] = k; // Index of the subsequence split that achieved minimal cost
}
}
}
}
}
</syntaxhighlight>
- Note: The first index for dims is 0 and the first index for and is 1.
A Python implementation using the memoization decorator from the standard library:
<syntaxhighlight lang="python3">
from functools import cache
def matrix_chain_order(dims: list[int]) -> int:
@cache
def a(i, j):
return min(
(a(i, k) + dims[i] * dims[k] * dims[j] + a(k, j) for k in range(i + 1, j)),
default=0,
)
return a(0, len(dims) - 1)
</syntaxhighlight>
More efficient algorithms
There are algorithms that are more efficient than the O(n<sup>3</sup>) dynamic programming algorithm, though they are more complex.
Hu & Shing
An algorithm published by T. C. Hu and M.-T. Shing achieves O(n log n) computational complexity.
They showed how the matrix chain multiplication problem can be transformed (or reduced) into the problem of triangulation of a regular polygon. The polygon is oriented such that there is a horizontal bottom side, called the base, which represents the final result. The other n sides of the polygon, in the clockwise direction, represent the matrices. The vertices on each end of a side are the dimensions of the matrix represented by that side. With n matrices in the multiplication chain there are n−1 binary operations and C<sub>n−1</sub> ways of placing parentheses, where C<sub>n−1</sub> is the (n−1)-th Catalan number. The algorithm exploits that there are also C<sub>n−1</sub> possible triangulations of a polygon with n+1 sides.
This image illustrates possible triangulations of a regular hexagon. These correspond to the different ways that parentheses can be placed to order the multiplications for a product of 5 matrices.
400px|center
For the example below, there are four sides: A, B, C and the final result ABC. A is a 10×30 matrix, B is a 30×5 matrix, C is a 5×60 matrix, and the final result is a 10×60 matrix. The regular polygon for this example is a 4-gon, i.e. a square:
125px|center
The matrix product AB is a 10x5 matrix and BC is a 30x60 matrix. The two possible triangulations in this example are:
<gallery mode="packed">
File:Matrix chain multiplication polygon example AB.svg|alt=(AB)C|Polygon representation of (AB)C
File:Matrix chain multiplication polygon example BC.svg|alt=A(BC)|Polygon representation of A(BC)
</gallery>
The cost of a single triangle in terms of the number of multiplications needed is the product of its vertices. The total cost of a particular triangulation of the polygon is the sum of the costs of all its triangles:
:(AB)C: (10×30×5) + (10×5×60) = 1500 + 3000 = 4500 multiplications
:A(BC): (30×5×60) + (10×30×60) = 9000 + 18000 = 27000 multiplications
Hu & Shing developed an algorithm that finds an optimum solution for the minimum cost partition problem in O(n log n) time. Their proof of correctness of the algorithm relies on "Lemma 1" proved in a 1981 technical report and omitted from the published paper.
Other O(n log n) algorithms
Wang, Zhu and Tian have published a simplified O(n log m) algorithm, where n is the number of matrices in the chain and m is the number of local minimums in the dimension sequence of the given matrix chain.
Chin-Hu-Shing approximate solution
An algorithm created independently by Chin and Hu & Shing runs in O(n) and produces a parenthesization which is at most 15.47% worse than the optimal choice. In most cases the algorithm yields the optimal solution or a solution which is only 1-2 percent worse than the optimal one. A practical instance of this comes from the ordering of join operations in databases; see .
Another somewhat contrived special case of this is string concatenation of a list of strings. In C, for example, the cost of concatenating two strings of length m and n using strcat is O(m + n), since we need O(m) time to find the end of the first string and O(n) time to copy the second string onto the end of it. Using this cost function, we can write a dynamic programming algorithm to find the fastest way to concatenate a sequence of strings. However, this optimization is rather useless because we can straightforwardly concatenate the strings in time proportional to the sum of their lengths. A similar problem exists for singly linked lists.
Another generalization is to solve the problem when parallel processors are available. In this case, instead of adding the costs of computing each factor of a matrix product, we take the maximum because we can do them simultaneously. This can drastically affect both the minimum cost and the final optimal grouping; more "balanced" groupings that keep all the processors busy are favored. There are even more sophisticated approaches.
See also
- Associahedron
- Tamari lattice
