|
| 1 | +""" |
| 2 | +Find the minimum number of multiplications needed to multiply chain of matrices. |
| 3 | +Reference: https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ |
| 4 | +
|
| 5 | +Python doctests can be run with the following command: |
| 6 | +python -m doctest -v matrix_chain_multiply.py |
| 7 | +
|
| 8 | +Given a sequence arr[] that represents chain of 2D matrices such that |
| 9 | +the dimension of ith matrix is arr[i-1]*arr[i]. |
| 10 | +So suppose arr = [40, 20, 30, 10, 30] means we have 4 matrices of |
| 11 | +dimesions 40*20, 20*30, 30*10 and 10*30. |
| 12 | +
|
| 13 | +matrix_chain_multiply() returns an integer denoting |
| 14 | +minimum number of multiplications to multiply the chain. |
| 15 | +
|
| 16 | +We do not need to perform actual multiplication here. |
| 17 | +We only need to decide the order in which to perform the multiplication. |
| 18 | +
|
| 19 | +Hints: |
| 20 | +1. Number of multiplications (ie cost) to multiply 2 matrices |
| 21 | +of size m*p and p*n is m*p*n. |
| 22 | +2. Cost of matrix multiplication is neither associative ie (M1*M2)*M3 != M1*(M2*M3) |
| 23 | +3. Matrix multiplication is not commutative. So, M1*M2 does not mean M2*M1 can be done. |
| 24 | +4. To determine the required order, we can try different combinations. |
| 25 | +So, this problem has overlapping sub-problems and can be solved using recursion. |
| 26 | +We use Dynamic Programming for optimal time complexity. |
| 27 | +
|
| 28 | +Example input : |
| 29 | +arr = [40, 20, 30, 10, 30] |
| 30 | +output : 26000 |
| 31 | +""" |
| 32 | + |
| 33 | + |
| 34 | +def matrix_chain_multiply(arr: list[int]) -> int: |
| 35 | + """ |
| 36 | + Find the minimum number of multiplcations to multiply |
| 37 | + chain of matrices. |
| 38 | +
|
| 39 | + Args: |
| 40 | + arr : The input array of integers. |
| 41 | +
|
| 42 | + Returns: |
| 43 | + int: Minimum number of multiplications needed to multiply the chain |
| 44 | +
|
| 45 | + Examples: |
| 46 | + >>> matrix_chain_multiply([1,2,3,4,3]) |
| 47 | + 30 |
| 48 | + >>> matrix_chain_multiply([10]) |
| 49 | + 0 |
| 50 | + >>> matrix_chain_multiply([10, 20]) |
| 51 | + 0 |
| 52 | + >>> matrix_chain_multiply([19, 2, 19]) |
| 53 | + 722 |
| 54 | + """ |
| 55 | + # first edge case |
| 56 | + if len(arr) < 2: |
| 57 | + return 0 |
| 58 | + # initialising 2D dp matrix |
| 59 | + n = len(arr) |
| 60 | + dp = [[float("inf") for j in range(n)] for i in range(n)] |
| 61 | + # we want minimum cost of multiplication of matrices |
| 62 | + # of dimension (i*k) and (k*j). This cost is arr[i-1]*arr[k]*arr[j]. |
| 63 | + for i in range(n - 1, 0, -1): |
| 64 | + for j in range(i, n): |
| 65 | + if i == j: |
| 66 | + dp[i][j] = 0 |
| 67 | + continue |
| 68 | + for k in range(i, j): |
| 69 | + dp[i][j] = min( |
| 70 | + dp[i][j], dp[i][k] + dp[k + 1][j] + arr[i - 1] * arr[k] * arr[j] |
| 71 | + ) |
| 72 | + return dp[1][n - 1] |
| 73 | + |
| 74 | + |
| 75 | +if __name__ == "__main__": |
| 76 | + import doctest |
| 77 | + |
| 78 | + doctest.testmod() |
0 commit comments