bsxfun-like for matrix product
Asked Answered
C

3

5

I need to multiply a matrix A with n matrices, and get n matrices back. For example, multiply a 2x2 matrix with 3 2x2 matrices stacked as a 2x2x3 Matlab array. bsxfun is what I usually use for such situations, but it only applies for element-wise operations. I could do something like:

blkdiag(a, a, a) * blkdiag(b(:,:,1), b(:,:,2), b(:,:,3))

but I need a solution for arbitrary n - ?

Cindacindee answered 13/1, 2014 at 10:20 Comment(2)
mathworks.com/matlabcentral/newsreader/view_thread/311944 check out the comments for FEX linksInhospitality
Cannot test now, but in the example times is used, perhaps mtimes can be substituted here.Amphiprostyle
I
7

You can reshape the stacked matrices. Suppose you have k-by-k matrix a and a stack of m k-by-k matrices sb and you want the product a*sb(:,:,ii) for ii = 1..m. Then all you need is

sza = size(a);
b = reshape( b, sza(2), [] ); % concatenate all matrices aloong the second dim
res = a * b; 
res = reshape( res, sza(1), [], size(sb,3) ); % stack back to 3d
Inferno answered 13/1, 2014 at 12:30 Comment(6)
+1 Well thought. But you need to store size(sb,3) before reshaping b, in order to use it at the endClift
@LuisMendo if you pay close attention I have two variables: sb for the "stacked" version and just b for the resized one.Inferno
Oh I see. I thought you were using (and overwriting) b.Clift
@LuisMendo but you are right that when reshaping and messing with arrays' sizes one better keep track of what is going on...Inferno
@Inferno In this case it should be b = reshape( sb, sza(2), [] );Omarr
BTW, what if I'd like to calculate sb(:,:,ii)*a?Omarr
C
3

Your solution can be adapted to arbitrary size using comma-saparated lists obtained from cell arrays:

[k m n] = size(B);
Acell = mat2cell(repmat(A,[1 1 n]),k,m,ones(1,n));
Bcell = mat2cell(B,k,m,ones(1,n));
blkdiag(Acell{:}) * blkdiag(Bcell{:});

You could then stack the blocks on a 3D array using this answer, and keep only the relevant ones.

But in this case a good old loop is probably faster:

C = NaN(size(B));
for nn = 1:n
    C(:,:,nn) = A * B(:,:,nn);
end
Clift answered 13/1, 2014 at 11:46 Comment(0)
C
1

For large stacks of matrices and/or vectors over which to execute matrix multiplication, speed can start becoming an issue. To avoid re-inventing the wheel, you could simply compile and use the following fast MEX code: MTIMESX - Mathworks. As a rule of thumb, MATLAB is often quite inefficient at executing for loops over large numbers of operations which look like they should be vectorizable; I cannot think of a straightforward way of generalising Shai's answer to this case.

Celinecelinka answered 11/5, 2020 at 1:55 Comment(2)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.Elodia
Given that the link itself is to the mathworks page for downloading code developed by a 3rd party ( mtimesx - GitHub ), it would not be appropriate for me to claim any part of their work as my own answer. If the link becomes broken, I would naturally attempt to replace it or else delete my answer.Celinecelinka

© 2022 - 2024 — McMap. All rights reserved.