Home > Software design >  How do I calculate the sum of products of entries of a 2D and 3D array?
How do I calculate the sum of products of entries of a 2D and 3D array?

Time:01-23

Let $X \in \mathbb{R}^{M\times N}$ be a 2-dimensional array. Let $Y \in \mathbb{R}^{M \times N \times K$ be a 3-dimensional array. I have these data arrays in Julia.

I want to calculate the number $$ \sum_{k = 1}^{K} \sum_{n = 1}^N \sum_{m = 1}^M X_{m,n} Y_{m, n, k}. $$ How can I calculate it using matrix/array product in Julia? This will be my objective function in an optimisation program.

I know how to calculate products of vectors and matrices (2D arrays). However, I am not sure how the products work with 3D arrays in Julia.

CodePudding user response:

You just need sum(X.*Y). The .* operator automatically will multiply things element by element, but will repeat if these is an dimension along which one of the tensors has size one and one doesn't (the third dimension in this case), i.e. it does exactly what you're asking for.

CodePudding user response:

Assuming we have these values for the dimensions

M = 3
N = 4
K = 2

makes some X matrix data

X = 10 .* ones( M , N )

then make your 3D data matrix data Y

Y = reshape( 1:M*N*K , (M , N, K) )
3×4×2 reshape(::UnitRange{Int64}, 3, 4, 2) with eltype Int64:
[:, :, 1] =
 1  4  7  10
 2  5  8  11
 3  6  9  12

[:, :, 2] =
 13  16  19  22
 14  17  20  23
 15  18  21  24

we can get the length of the 3rd dimension via size(Y)[3] which produces value 2. We can find the product of X and the second 3d slice of Y via

X .* Y[:,:,2]
3×4 Matrix{Float64}:
 130.0  160.0  190.0  220.0
 140.0  170.0  200.0  230.0
 150.0  180.0  210.0  240.0

we can get the product of X with each 3d slice of Y via

X .* Y
3×4×2 Array{Float64, 3}:
[:, :, 1] =
 10.0  40.0  70.0  100.0
 20.0  50.0  80.0  110.0
 30.0  60.0  90.0  120.0

[:, :, 2] =
 130.0  160.0  190.0  220.0
 140.0  170.0  200.0  230.0
 150.0  180.0  210.0  240.0

if you want you can use a map function to explicitly multiply X by each of the 3rd dimension values of Y by

XprodY1 = map( k -> X .* Y[:,:,k] , 1:size(Y)[3] )
2-element Vector{Matrix{Float64}}:
 [10.0 40.0 70.0 100.0; 20.0 50.0 80.0 110.0; 30.0 60.0 90.0 120.0]
 [130.0 160.0 190.0 220.0; 140.0 170.0 200.0 230.0; 150.0 180.0 210.0 240.0]

and that produces the same 2 matrices but this time each XY_k slice is a component of a vector and not part of a 3d array but in this way you can do more manual control of the multiplications.

To get the sum of the matrix multiplications across dimension K (3rd dim of Y),

sum( X .* Y )
3000

An alternative is sum( X .* Y , dims=3 ) produces a MxN matrix where each entry is the sum of (m,n) over k. sum( sum( X .* Y , dims=(1,2) ) ) also gives the total sum from the XY_k products. You could do this in the expanded form with all the for loops if you want

sumXY = 0
for k in 1:size(Y)[3]
    for j in 1:size(Y)[2]
        for i in 1:size(Y)[1]
            sumXY  = X[i,j] * Y[i,j,k]
        end
    end
end
sumXY
3000.0
  • Related