ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Julia Recursive Matrix Chain Multiplication

Julia

Goal -- WPM

Ready
Exercise Algorithm Area
1function matrix_chain_order(p::Vector{Int})
2n = length(p) - 1
3if n < 1
4return 0, Matrix{Int}(undef, 0, 0) # Handle no matrices or single matrix case
5end
6
7# m[i, j] = Minimum number of scalar multiplications needed to compute the matrix A[i]A[i+1]...A[j]
8# s[i, j] = Index of the split point k that achieved the minimum cost in m[i, j]
9m = Matrix{Int}(undef, n, n)
10s = Matrix{Int}(undef, n, n)
11
12# Cost is zero when multiplying one matrix
13for i in 1:n
14m[i, i] = 0
15end
16
17# L is the chain length
18for L in 2:n
19for i in 1:(n - L + 1)
20j = i + L - 1
21m[i, j] = typemax(Int)
22for k in i:(j - 1)
23# q = cost/scalar multiplications
24q = m[i, k] + m[k + 1, j] + p[i] * p[k + 1] * p[j + 1]
25if q < m[i, j]
26m[i, j] = q
27s[i, j] = k
28end
29end
30end
31end
32
33return m[1, n], s
34end
35
36# Helper function to print the optimal parenthesization (optional but good for understanding)
37function print_optimal_parens(s::Matrix{Int}, i::Int, j::Int)
38if i == j
39print("A$i")
40else
41print("(")
42print_optimal_parens(s, i, s[i, j])
43print_optimal_parens(s, s[i, j] + 1, j)
44print(")")
45end
46end
47
48# Main function to call and display results
49function solve_matrix_chain(dims::Vector{Int})
50if length(dims) < 2
51println("Error: Need at least two dimensions to define one matrix.")
52return
53end
54# Check for invalid dimensions (non-positive)
55if any(d <= 0 for d in dims)
56println("Error: Matrix dimensions must be positive.")
57return
58end
59
60min_cost, split_points = matrix_chain_order(dims)
61println("Minimum number of scalar multiplications: ", min_cost)
62print("Optimal parenthesization: ")
63if size(split_points, 1) > 0
64print_optimal_parens(split_points, 1, size(split_points, 1))
65println()
66else
67println("N/A (single matrix or no matrices)")
68end
69end
Algorithm description viewbox

Julia Recursive Matrix Chain Multiplication

Algorithm description:

This Julia program calculates the minimum number of scalar multiplications required to multiply a chain of matrices and determines the optimal parenthesization. It uses dynamic programming to solve the matrix chain multiplication problem efficiently. This is crucial in computer graphics, scientific computing, and any domain involving extensive matrix operations where performance is critical.

Algorithm explanation:

The `matrix_chain_order` function implements a dynamic programming approach to solve the matrix chain multiplication problem. It computes `m[i, j]`, the minimum cost to multiply matrices A_i through A_j, and `s[i, j]`, the split point `k` that yields this minimum cost. The algorithm iterates through increasing chain lengths `L`, filling the `m` and `s` tables. The time complexity is O(n^3) due to three nested loops, and the space complexity is O(n^2) for storing the `m` and `s` tables. Edge cases include handling fewer than two dimensions (no matrices or one matrix), returning 0 cost, and ensuring all dimensions are positive. The `print_optimal_parens` helper reconstructs the optimal parenthesization from the `s` table.

Pseudocode:

function matrix_chain_order(p):
  n = length(p) - 1
  if n < 1: return 0, empty_matrix

  initialize m[n, n] and s[n, n]
  for i from 1 to n: m[i, i] = 0

  for L from 2 to n: // chain length
    for i from 1 to n - L + 1:
      j = i + L - 1
      m[i, j] = infinity
      for k from i to j - 1:
        cost = m[i, k] + m[k + 1, j] + p[i] * p[k + 1] * p[j + 1]
        if cost < m[i, j]:
          m[i, j] = cost
          s[i, j] = k
  return m[1, n], s

function print_optimal_parens(s, i, j):
  if i == j: print "A" + i
  else:
    print "("
    print_optimal_parens(s, i, s[i, j])
    print_optimal_parens(s, s[i, j] + 1, j)
    print ")"