functions.jl (3756B)
1 #/usr/bin/julia 2 3 using LinearAlgebra 4 5 @doc raw""" 6 mode_k_dot(T, Z, k) 7 8 Compute the mode-$k$ contraction of a tensor $S$ of size $n_1 × ⋯ × n_d$ 9 with a matrix $Z$ of size $r × n_k$ 10 11 Out: A tensor $S$ of size $n_1 × ⋯ × n_{k-1} × r × n_{k+1} × ⋯ × n_d$ 12 """ 13 function mode_k_dot(S, Z, k) 14 n = size(S) 15 r = size(Z)[1] 16 17 if length(n) < k 18 error("Try a smaller k") 19 end 20 if (size(Z))[2] != n[k] 21 error("Z not of the correct size for mode-k contraction") 22 end 23 24 end_dim = [[n[i] for i in 1:(k-1)]..., r, [n[i] for i in (k+1):length(n)]...] 25 alpha_dim = [n[i] for i in 1:length(n) if i!=k] 26 T = [] 27 for alpha in 1:r 28 s = zeros(alpha_dim...) 29 for i_k in 1:n[k] 30 s += Z[alpha, i_k] * selectdim(S, k, i_k) 31 end 32 append!(T, s) 33 end 34 return reshape(T, end_dim...) 35 end 36 37 @doc raw""" 38 multiplication_tensor(n) 39 40 Compute the multiplication tensor for the multiplication $T$ of two matrices $A$ and $B$ 41 of size \alpha $n × n$, satisfying the column major convention 42 43 $C_k = ∑_{i, j}^{n^2} T_{ijk} ⋅ A_i ⋅ B_k$ 44 """ 45 function multiplication_tensor(n) 46 T = zeros(Int, n^2, n^2, n^2) 47 U = zeros(n^2, n^3) 48 V = zeros(n^2, n^3) 49 W = zeros(n^2, n^3) 50 51 count = 1 52 for m=1:n:n^2, l=1:n 53 k = (l-1)+m 54 for (i, j) in zip(collect(l:n:n^2), collect(m:m+n)) 55 T[i, j, k] = 1 56 U[i, count] = 1 57 V[j, count] = 1 58 W[k, count] = 1 59 count += 1 60 end 61 end 62 return T, [U, V, W] 63 end 64 65 @doc raw""" 66 cpd_eval(U_i) 67 68 Evaluate a rank-r CPD of a tensor $S$ of size $n_1 × ⋯ × n_d$, given $d$ 69 matrices $U_i$ of the size $n_k × r$. 70 71 $U_i = [U_1, … , U_d]$ 72 """ 73 function cpd_eval(U_i) 74 reverse!(U_i) 75 d = length(U_i) 76 r = size(U_i[1])[2] 77 n_d = [size(U_i[i])[1] for i in 1:d] 78 s = zeros(n_d...) 79 80 for alpha in 1:r 81 k = kron(U_i[1][:, alpha], U_i[2][:, alpha]) 82 for i in 2:(d-1) 83 k = kron(k, U_i[i+1][:, alpha]) 84 end 85 s += reshape(k, n_d...) 86 end 87 return s 88 end 89 90 @doc raw""" 91 cpd_multiply(A, B, U, V, W) 92 93 Compute the matrix multiplication $A ⋅ B$ using the rank-$n^3$ CPD of the multiplication Tensor, 94 without evaluating the tensor 95 """ 96 function cpd_multiply(A, B, U, V, W) 97 n = size(A)[1] 98 r = size(U)[2] 99 C = zeros(n, n) 100 for k=1:n^2 101 C[k] = sum(sum(A[i] * U[i, alpha] for i=1:n^2) 102 * sum(B[j] * V[j, alpha] for j=1:n^2) 103 * W[k, alpha] for alpha=1:r) 104 end 105 return C 106 end 107 108 @doc raw""" 109 strassen_alg(A, B) 110 111 Implementation of the Stranssens Algorithm for two matrices $A$ and $B$ 112 of the size $2 × 2$ 113 """ 114 function strassen_alg(A, B) 115 if size(A) != (2, 2) || size(B) != (2, 2) 116 error("Choose 2x2 Matrices") 117 end 118 C = zeros(2, 2) 119 M_1 = (A[1] + A[4])*(B[1] + B[4]) 120 M_2 = (A[2] + A[4])*B[1] 121 M_3 = A[1]*(B[3] - B[4]) 122 M_4 = A[4]*(B[2] - B[1]) 123 M_5 = (A[1] + A[3])*B[4] 124 M_6 = (A[2] - A[1])*(B[1] + B[3]) 125 M_7 = (A[3] - A[4])*(B[2] + B[4]) 126 127 C[1] = M_1 + M_4 - M_5 + M_7 128 C[2] = M_2 + M_4 129 C[3] = M_3 + M_5 130 C[4] = M_1 - M_2 + M_3 + M_6 131 return C 132 end 133 @doc raw""" 134 rank_7_CPD() 135 136 Get the rank-7 CPD of the $2 × 2$ multiplication tensor 137 (Strassens Algorithm) 138 """ 139 function rank_7_CPD() 140 U = [1 0 1 0 1 -1 0 # A_i placement in M_{ijk} 141 0 1 0 0 0 1 0 142 0 0 0 0 1 0 1 143 1 1 0 1 0 0 -1]; 144 145 V = [1 1 0 -1 0 1 0 # B_j placement in M_{ijk} 146 0 0 0 1 0 0 1 147 0 0 1 0 0 1 0 148 1 0 -1 0 1 0 1]; 149 150 W = [1 0 0 1 -1 0 1 # M_{ijk} placement in C_k 151 0 1 0 1 0 0 0 152 0 0 1 0 1 0 0 153 1 -1 1 0 0 1 0]; 154 155 return U, V, W 156 end