Skip to content

Commit 84ef969

Browse files
authored
Merge pull request #925 from kosuri-indu/add/mcm-algorithm
Added Content: DP algorithm - Matrix Chain Multiplication
2 parents 6d81b79 + 82a9aa2 commit 84ef969

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
---
2+
id: matrix-chain-multiplication
3+
title: Matrix Chain Multiplication using Dynamic Programming
4+
sidebar_label: Matrix Chain Multiplication
5+
tags: [python, java, c++, javascript, programming, algorithms, dynamic programming, tutorial, in-depth]
6+
description: In this tutorial, we will learn about the Matrix Chain Multiplication problem and its solution using Dynamic Programming in Python, Java, C++, and JavaScript with detailed explanations and examples.
7+
---
8+
9+
# Matrix Chain Multiplication using Dynamic Programming
10+
11+
Matrix Chain Multiplication is a classic optimization problem that can be solved efficiently using dynamic programming. The goal is to determine the most efficient way to multiply a given sequence of matrices.
12+
13+
## Problem Statement
14+
15+
Given a sequence of matrices, find the optimal way to parenthesize the matrix product such that the total number of scalar multiplications is minimized.
16+
17+
### Intuition
18+
19+
Matrix multiplication is associative, meaning that the order of multiplication can affect the computation cost. Dynamic programming helps by breaking down the problem into subproblems, solving each subproblem just once, and storing the results.
20+
21+
## Dynamic Programming Approach
22+
23+
Using dynamic programming, we build a table `dp` where `dp[i][j]` represents the minimum number of scalar multiplications needed to compute the product of matrices from `i` to `j`.
24+
25+
## Pseudocode for Matrix Chain Multiplication using DP
26+
27+
#### Initialize:
28+
29+
```markdown
30+
for i from 1 to n:
31+
dp[i][i] = 0
32+
33+
for len from 2 to n:
34+
for i from 1 to n-len+1:
35+
j = i+len-1
36+
dp[i][j] = inf
37+
for k from i to j-1:
38+
q = dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j]
39+
if q < dp[i][j]:
40+
dp[i][j] = q
41+
42+
return dp[1][n]
43+
```
44+
### Example Output:
45+
46+
Given the matrix dimensions:
47+
- `p = [1, 2, 3, 4]`
48+
49+
The minimum number of multiplications required to multiply the sequence of matrices is `18`.
50+
51+
The matrix dimensions correspond to three matrices:
52+
- A (1x2)
53+
- B (2x3)
54+
- C (3x4)
55+
56+
By following the dynamic programming approach, the optimal way to multiply these matrices requires `18` scalar multiplications. The output is printed as: `Minimum number of multiplications is: 18`
57+
58+
You can verify this by manually checking the optimal parenthesization: `((A * B) * C) requires (1*2*3) + (1*3*4) = 6 + 12 = 18` multiplications.
59+
60+
61+
## Implementing Matrix Chain Multiplication using DP
62+
63+
### Python Implementation
64+
65+
```python
66+
def matrix_chain_order(p):
67+
n = len(p) - 1 # Number of matrices
68+
dp = [[0 for _ in range(n)] for _ in range(n)] # DP table initialization
69+
70+
# l is the chain length
71+
for l in range(2, n + 1): # l=2 means multiplying two matrices at a time
72+
for i in range(n - l + 1):
73+
j = i + l - 1
74+
dp[i][j] = float('inf') # Initialize with infinity
75+
for k in range(i, j):
76+
# q = cost/scalar multiplications
77+
q = dp[i][k] + dp[k + 1][j] + p[i] * p[k + 1] * p[j + 1]
78+
if q < dp[i][j]:
79+
dp[i][j] = q
80+
81+
return dp[0][n - 1] # Minimum cost to multiply all matrices
82+
83+
p = [1, 2, 3, 4]
84+
print("Minimum number of multiplications is:", matrix_chain_order(p))
85+
```
86+
87+
### Java Implementation
88+
89+
```java
90+
public class MatrixChainMultiplication {
91+
public static int matrixChainOrder(int[] p) {
92+
int n = p.length - 1; // Number of matrices
93+
int[][] dp = new int[n][n]; // DP table initialization
94+
95+
// l is the chain length
96+
for (int l = 2; l <= n; l++) { // l=2 means multiplying two matrices at a time
97+
for (int i = 0; i < n - l + 1; i++) {
98+
int j = i + l - 1;
99+
dp[i][j] = Integer.MAX_VALUE; // Initialize with infinity
100+
for (int k = i; k < j; k++) {
101+
// q = cost/scalar multiplications
102+
int q = dp[i][k] + dp[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
103+
if (q < dp[i][j]) {
104+
dp[i][j] = q;
105+
}
106+
}
107+
}
108+
}
109+
110+
return dp[0][n - 1]; // Minimum cost to multiply all matrices
111+
}
112+
113+
public static void main(String[] args) {
114+
int[] p = {1, 2, 3, 4};
115+
System.out.println("Minimum number of multiplications is: " + matrixChainOrder(p));
116+
}
117+
}
118+
119+
```
120+
### C++ Implementation
121+
122+
```cpp
123+
#include <iostream>
124+
#include <climits>
125+
using namespace std;
126+
127+
int matrixChainOrder(int p[], int n) {
128+
int dp[n][n]; // DP table initialization
129+
130+
// l is the chain length
131+
for (int i = 1; i < n; i++)
132+
dp[i][i] = 0; // Cost is zero when multiplying one matrix
133+
134+
for (int l = 2; l < n; l++) { // l=2 means multiplying two matrices at a time
135+
for (int i = 1; i < n - l + 1; i++) {
136+
int j = i + l - 1;
137+
dp[i][j] = INT_MAX; // Initialize with infinity
138+
for (int k = i; k <= j - 1; k++) {
139+
// q = cost/scalar multiplications
140+
int q = dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k] * p[j];
141+
if (q < dp[i][j]) {
142+
dp[i][j] = q;
143+
}
144+
}
145+
}
146+
}
147+
148+
return dp[1][n - 1]; // Minimum cost to multiply all matrices
149+
}
150+
151+
int main() {
152+
int p[] = {1, 2, 3, 4};
153+
int n = sizeof(p) / sizeof(p[0]);
154+
cout << "Minimum number of multiplications is: " << matrixChainOrder(p, n);
155+
return 0;
156+
}
157+
```
158+
159+
### JavaScript Implementation
160+
161+
```javascript
162+
function matrixChainOrder(p) {
163+
let n = p.length - 1; // Number of matrices
164+
let dp = Array.from({ length: n }, () => Array(n).fill(0)); // DP table initialization
165+
166+
// l is the chain length
167+
for (let l = 2; l <= n; l++) { // l=2 means multiplying two matrices at a time
168+
for (let i = 0; i < n - l + 1; i++) {
169+
let j = i + l - 1;
170+
dp[i][j] = Infinity; // Initialize with infinity
171+
for (let k = i; k < j; k++) {
172+
// q = cost/scalar multiplications
173+
let q = dp[i][k] + dp[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
174+
if (q < dp[i][j]) {
175+
dp[i][j] = q;
176+
}
177+
}
178+
}
179+
}
180+
181+
return dp[0][n - 1]; // Minimum cost to multiply all matrices
182+
}
183+
184+
let p = [1, 2, 3, 4];
185+
console.log("Minimum number of multiplications is:", matrixChainOrder(p));
186+
```
187+
188+
## Complexity Analysis
189+
190+
- Time Complexity: $O(n^3)$, due to the three nested loops.
191+
- Space Complexity: $O(n^2)$, for storing the DP table.
192+
193+
## Conclusion
194+
195+
Dynamic programming provides an efficient solution for the Matrix Chain Multiplication problem by breaking it into subproblems and storing intermediate results. This technique can be extended to solve other problems with overlapping subproblems and optimal substructure properties.

0 commit comments

Comments
 (0)