Introduction
.
Matrix Chain Multiplication is a classic problem in computer science and operations research. The goal is to determine the most efficient way to multiply a given sequence of matrices. The problem does not involve performing the actual multiplications but rather determining the order of multiplications that minimizes the total number of scalar multiplications.
.
Working
When multiplying multiple matrices, the order in which the matrices are multiplied can significantly affect the number of operations required.
For example, given three matrices A, B, and C, the product can be computed in two different ways: (AB)C or A(BC).
Each way requires a different number of operations. The Matrix Chain Multiplication problem seeks the optimal order of multiplication for a given sequence of matrices to minimize these operations.
.
First off, it should be noted that matrix multiplication is associative, but not commutative. But since it is associative, we always have:
((AB)(CD)) = (A(B(CD)))
or equality for any such grouping as long as the matrices in the product appear in the same order.
.
It may appear on the surface that the amount of work done won’t change if you change the parenthesizing of the expression, but we can prove that is not the case with the following example:
Let A be a 2×10 matrix
Let B be a 10×50 matrix
Let C be a 50×20 matrix
.
Consider computing A(BC) –
Number of multiplications for (BC) = 10x50x20 = 10000, creating a 10×20 answer matrix
Number of multiplications for A(BC) = 2x10x20 = 400,
Total multiplications = 10000 + 400 = 10400.
.
Consider computing (AB)C –
Number of multiplications for (AB) = 2x10x50 = 1000, creating a 2×50 answer matrix
Number of multiplications for (AB)C = 2x50x20 = 2000,
Total multiplications = 1000 + 2000 = 3000, a significant difference.
Thus, the (AB)C is the winner because the goal to multiply the fewest number of multiplications necessary to compute the product.
.
Dynamic Programming Approach
The Matrix Chain Multiplication (MCM) problem is indeed solved using dynamic programming.
This approach efficiently finds the optimal order of matrix multiplications by breaking the problem into smaller subproblems, solving each subproblem once, and storing the solutions for future reference.
This method avoids redundant calculations and significantly reduces the time complexity compared to a naive approach.
.
We have a recursive formula –
N[i][j] = min value of N[i][k] + N[k+1][j] + d[i]d[k+1]d[j+1], over all valid values of k.
Where N[i][j] is the minimum number of multiplications needed to multiply matrices from A[i] to A[j], d[] represents the dimension.
Smaller problems need to be solved before larger ones.
For example, we need to know N[i][i+1] the number of multiplications to multiply any adjacent pair of matrices, before moving on to larger tasks.
Next, we solve for all values of the form N[i][i+2], then N[i][i+3]​, and so on. Here is the algorithm –
.
Algorithm of MCM by Dynamic Programming Approach
- Initialize N[i][i] = 0 and all other entries in N to ∞.
- Loop through the chain lengths
- For i = 1 to n−1
- For j=0 to n−1−i:
- For k = j to j + i − 1:
- If N[j][j+i−1] > N[j][k] + N[k+1][j+i−1] + d[j]d[k+1]d[i+j]
- Update N[j][j+i−1] = N[j][k] + N[k+1][j+i−1] + d[j]d[k+1]d[i+j​]
- If N[j][j+i−1] > N[j][k] + N[k+1][j+i−1] + d[j]d[k+1]d[i+j]
- For k = j to j + i − 1:
- For j=0 to n−1−i:
- For i = 1 to n−1
This way, we solve the smaller sub-problems first, gradually building up to the solution for the entire chain.
Â
Example –
Initialize N[i][i] = 0 and all other entries in N to ∞.
.
First, we determine the number of multiplications necessary for 2 matrices –
A x B uses 2 x 4 x 2 = 16 multiplications
B x C uses 4 x 2 x 3 = 24 multiplications
C x D uses 2 x 3 x 1 = 6 multiplications
D x E uses 3 x 1 x 4 = 12 multiplications
.
Now, let’s determine the number of multiplications necessary for 3 matrices
(A x B) x C uses 16 + 0 + 2x2x3 = 28 multiplications
A x (B x C) uses 0 + 24 + 2x4x3 = 48 multiplications,
so 28 is min.
.
(B x C) x D uses 24 + 0 + 4x3x1 = 36 multiplications
B x (C x D) uses 0 + 6 + 4x2x1 = 14 multiplications,
so 14 is min.
.
(C x D) x E uses 6 + 0 + 2x1x4 = 14 multiplications
C x (D x E) uses 0 + 12 + 2x3x4 = 36,
so 14 is min.
.
Four matrices next –
A x (B x C x D) uses 0 + 14 + 2x4x1 = 22 multiplications
(A x B) x (C x D) uses 16 + 6 + 2x2x1 = 26 multiplications
(A x B x C) x D uses 28 + 0 + 2x3x1 = 34 multiplications
So, 22 is min.
Â
B x (C x D x E) uses 0 + 14 + 4x2x4 = 46 multiplications
(B x C) x (D x E) uses 24 + 12 + 4x3x4 = 84 multiplications
(B x C x D) x E uses 14 + 0 + 4x1x4 = 30 multiplications
So, 30 is min.
.
For the answer –
A x (B x C x D x E) uses 0 + 30 + 2x4x4 = 62 multiplications
(A x B) x (C x D x E) uses 16 + 14 + 2x2x4 = 46 multiplications
(A x B x C) x (D x E) uses 28 + 12 + 2x3x4 = 64 multiplications
(A x B x C x D) x E uses 22 + 0 + 2x1x4 = 30 multiplications
Answer = 30 multiplications
.
Source code of Matrix Chain Multiplication
// COMPUTER GEEK – compgeek.co.in
// Write a program for Matrix Chain Multiplication
Â
#include <stdio.h>
#include <limits.h>
Â
// Function to find the minimum number of multiplications needed
void matrixChainOrder(int p[], int n) {
   int m[n][n]; // m[i][j] stores the minimum number of multiplications needed to compute the matrix A[i]A[i+1]…A[j]
   int i, j, k, L, q;
Â
   // Initialize the diagonal values to 0, since a single matrix needs 0 multiplications
   for (i = 1; i < n; i++) {
       m[i][i] = 0;
   }
Â
   // L is the chain length
   for (L = 2; L < n; L++) {
       for (i = 1; i < n – L + 1; i++) {
           j = i + L – 1;
           m[i][j] = INT_MAX;
           for (k = i; k <= j – 1; k++) {
               // q is the cost of scalar multiplications
               q = m[i][k] + m[k + 1][j] + p[i – 1] * p[k] * p[j];
               if (q < m[i][j]) {
                   m[i][j] = q;
               }
           }
       }
   }
Â
   // Print the minimum number of multiplications needed
   printf(“Minimum number of multiplications is %d\n”, m[1][n – 1]);
}
Â
int main() {
   int n;
Â
   printf(“Enter the number of matrices: “);
   scanf(“%d”, &n);
Â
   int p[n + 1];
   printf(“Enter the dimensions of the matrices: “);
   for (int i = 0; i <= n; i++) {
       scanf(“%d”, &p[i]);
   }
Â
   matrixChainOrder(p, n + 1);
Â
   return 0;
}
// COMPUTER GEEK – compgeek.co.in
// Write a program for Matrix Chain Multiplication
Â
#include <iostream>
#include <vector>
#include <climits>
Â
using namespace std;
Â
int matrixChainMultiplication(const vector<int>& p) {
   int n = p.size() – 1;
   vector<vector<int>> m(n, vector<int>(n, 0));
  Â
   for (int l = 2; l <= n; l++) {
       for (int i = 0; i <= n – l; i++) {
           int j = i + l – 1;
           m[i][j] = INT_MAX;
           for (int k = i; k < j; k++) {
               int q = m[i][k] + m[k+1][j] + p[i] * p[k+1] * p[j+1];
               if (q < m[i][j]) {
                   m[i][j] = q;
               }
           }
       }
   }
  Â
   return m[0][n-1];
}
Â
int main() {
   int n;
   cout << “Enter the number of matrices: “;
   cin >> n;
  Â
   vector<int> dimensions(n + 1);
   cout << “Enter the dimensions of the matrices: “;
   for (int i = 0; i <= n; i++) {
       cin >> dimensions[i];
   }
  Â
   cout << “Minimum number of multiplications is ” << matrixChainMultiplication(dimensions) << endl;
  Â
   return 0;
}
// COMPUTER GEEK – compgeek.co.in
// Write a program for Matrix Chain Multiplication
Â
import java.util.Scanner;
Â
public class MatrixChainMultiplication {
Â
   public static int matrixChainOrder(int[] p) {
       int n = p.length – 1;
       int[][] m = new int[n][n];
Â
       for (int l = 2; l <= n; l++) {
           for (int i = 0; i <= n – l; i++) {
               int j = i + l – 1;
               m[i][j] = Integer.MAX_VALUE;
               for (int k = i; k < j; k++) {
                   int q = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
                   if (q < m[i][j]) {
                       m[i][j] = q;
                   }
               }
           }
       }
      Â
       return m[0][n – 1];
   }
Â
   public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
       System.out.print(“Enter the number of matrices: “);
       int n = sc.nextInt();
      Â
       int[] dimensions = new int[n + 1];
       System.out.print(“Enter the dimensions of the matrices: “);
       for (int i = 0; i <= n; i++) {
           dimensions[i] = sc.nextInt();
       }
      Â
       System.out.println(“Minimum number of multiplications is ” + matrixChainOrder(dimensions));
   }
}
# COMPUTER GEEK – compgeek.co.in
# Write a program for Matrix Chain Multiplication
Â
def matrix_chain_order(p):
   n = len(p) – 1
   m = [[0] * n for _ in range(n)]
Â
   for l in range(2, n + 1):
       for i in range(n – l + 1):
           j = i + l – 1
           m[i][j] = float(‘inf’)
           for k in range(i, j):
               q = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1]
               if q < m[i][j]:
                   m[i][j] = q
Â
   return m[0][n – 1]
Â
if __name__ == “__main__”:
   n = int(input(“Enter the number of matrices: “))
   dimensions = list(map(int, input(“Enter the dimensions of the matrices: “).split()))
  Â
   print(“Minimum number of multiplications is”, matrix_chain_order(dimensions))
Enter the number of matrices: 5
// (2×4) (4×2) (2×3) (3×1) (1×4) -> 2 4 2 3 1 4
Enter the dimensions of the matrices: 2 4 2 3 1 4
Minimum number of multiplications is 30
=== Code Execution Successful ===
Time complexity of the Matrix Chain Multiplication
The time complexity of the Matrix Chain Multiplication algorithm, when solved using dynamic programming, is O(n^3).
First, initializing the DP table, which is a 2D array of size n x n, takes O(n2) time. The core of the algorithm involves three nested loops, so combining these operations results in a total time complexity of O(n) * O(n) * O(n) = O(n3).
.
Space complexity of the Matrix Chain Multiplication
The space complexity of the Matrix Chain Multiplication algorithm using dynamic programming is O(n2). This complexity is mainly due to the storage requirements for the dynamic programming table.
.
Applications of Matrix Chain Multiplication Algorithm
- Computer Graphics – In graphics processing, matrix chain multiplication is used to compute transformations of objects and scenes efficiently, which involves multiple matrix multiplications.
- Optimization Problems – The algorithm is used in various optimization problems where multiple operations are performed on matrices, such as in network design and resource allocation.
- Scientific Computations – It is applied in scientific and engineering fields where large-scale matrix operations are common, such as simulations and modelling in physics and engineering.
- Machine Learning – In machine learning and data science, matrix chain multiplication can be used for optimizing algorithms that involve multiple matrix operations, such as in neural network training and data processing.
Test Yourself
Q1- What is the Matrix Chain Multiplication problem, and why is it important?
The Matrix Chain Multiplication problem involves finding the most efficient way to multiply a sequence of matrices.
It’s important because matrix multiplication is associative but not commutative, meaning the order of multiplication affects the computational cost.
Efficiently determining the order minimizes the total number of scalar multiplications required, which can be crucial for reducing computation time in applications such as computer graphics, scientific simulations, and machine learning.
Q2- Explain the concept of dynamic programming as it applies to Matrix Chain Multiplication.
Dynamic programming is a method used to solve problems by breaking them down into smaller overlapping subproblems and solving each subproblem once, storing the results for future reference. In Matrix Chain Multiplication, dynamic programming helps find the optimal multiplication order by solving subproblems related to smaller sequences of matrices and combining their solutions to determine the optimal order for the entire sequence.
Q3- How does the recursive formula for Matrix Chain Multiplication work?
The recursive formula for Matrix Chain Multiplication is N[i][j] = mini≤k<j​(N[i][k] + N[k+1][j] + d[i] × d[k+1] × d[j+1]).
This formula calculates the minimum number of multiplications required to multiply matrices from index i to j by considering all possible places to split the product into two subproducts and combining their costs with the cost of multiplying the resulting matrices.
Q4- How does the time complexity of the dynamic programming solution to the Matrix Chain Multiplication problem compare to a naive approach?
The time complexity of the dynamic programming solution is O(n3), where n is the number of matrices. This is significantly more efficient than the naive approach, which has an exponential time complexity. The dynamic programming approach reduces redundant calculations by storing and reusing results of subproblems.
Q5- What are the advantages of using dynamic programming for solving the Matrix Chain Multiplication problem?
The advantages include reduced time complexity compared to naive approaches, as it avoids redundant calculations by storing intermediate results.
It provides an efficient way to find the optimal multiplication order, leading to fewer scalar multiplications and faster computation times.
Q6- Provide an example where the Matrix Chain Multiplication algorithm significantly reduces computational cost compared to a naive method.
Consider multiplying matrices A (2×10), B (10×50), and C (50×20).
Naively computing (AB)C requires 1000 + 2000 = 3000 multiplications,
while computing A(BC) requires 10000 + 400= 10400 multiplications.
The dynamic programming approach identifies (AB)C as optimal, saving significant computational cost.
Q7- Explain the role of matrix dimensions in determining the cost of multiplication in Matrix Chain Multiplication.
Matrix dimensions affect the cost of multiplication because the number of scalar multiplications required depends on the dimensions of the matrices being multiplied.
Specifically, if multiplying matrices A (p x q) and B (q x r), the cost is p × q × r. Larger dimensions lead to higher multiplication costs, so choosing an optimal multiplication order is crucial for minimizing the total cost.
Q8- Which of the following statements about Matrix Chain Multiplication is true?
The order of multiplication does not affect the total number of multiplications
The Matrix Chain Multiplication problem can be solved in constant time.
Matrix Chain Multiplication is associative but not commutative.
Dynamic programming does not improve the efficiency of solving the Matrix Chain Multiplication problem.
Ans – (3)
Explanation – Matrix multiplication is associative, meaning the grouping of matrices does not change the result, but it is not commutative, meaning the order of multiplication affects the result.
Q9- How is the minimum number of multiplications calculated in Matrix Chain Multiplication?
By multiplying all matrices in a given order.
By selecting the minimum value among all possible splits.
By adding the dimensions of the matrices.
By multiplying the number of matrices by their dimensions.
Ans – (2)
Explanation – The algorithm considers all possible places to split the chain and calculates the cost for each split to determine the minimum number of multiplications.
Q10- Which of the following is a key advantage of using dynamic programming for Matrix Chain Multiplication?
It requires no storage for intermediate results.
It provides an exponential time complexity solution.
It avoids redundant calculations by storing results of subproblems.
It eliminates the need for matrix dimensions.
Ans – (3)
Explanation – Dynamic programming stores intermediate results to avoid recalculating solutions for the same subproblems, improving efficiency.
Q11- For a sequence of 5 matrices, how many distinct parenthesizations are possible?
5
14
42
1
Ans – (3)
Explanation – The number of distinct parenthesizations for a sequence of 5 matrices is given by the Catalan number C4, which is 42.
Q12- What information is required to solve the Matrix Chain Multiplication problem?
The number of matrices and their dimensions.
The multiplication order of the matrices.
The total number of scalar multiplications for all matrices.
The identity matrix of each matrix.
Ans – (1)
Explanation – To solve the problem, you need the dimensions of each matrix to calculate the cost of multiplications and determine the optimal order.Â