How to create N+1 dimensional array by taking exterior product of 1st dimension of two N dimensional arrays?
5 views (last 30 days)
Show older comments
I would like to efficiently create an N+1 dimensional array C, whose first 2 dimensions are the exterior product of the 1st dimension of the N dimensional arrays A and B. The exterior product of m by 1 column vectors x and y is the m by m matrix x*y'.
As an example, given the 2 by 3 by 5 arrays A and B, I would like to create the 2 by 2 by 3 by 5 array C such that C(i,j,k,l) = A(i,k,l)*B(j,k,l).
For efficiency pruposes, I would like to do this without for loops, to the extent possible (I know how to do this with slow, ugly, brute force for loops). Given that I will apply this to YALMIP sdpvar arrays, implicit expansion can't be used. The following (non-exhaustive list) can be used in any combination:
reshape
repmat
vec'ing (i.e., A(:))
.*
kron
bsxfun (if needed)
Thanks.
0 Comments
Accepted Answer
Bruno Luong
on 7 Dec 2020
Solution without expansion as requested
sizeA = size(A);
reshapeB = reshape(B,[1 size(B)]);
reshapeA = reshape(A,[sizeA(1) 1 sizeA(2:end)]);
rA = ones(size(size(A))); rA(2)=size(B,1);
rB = ones(size(size(B))); rB(1)=size(A,1);
C = repmat(reshapeA,rA) .* repmat(reshapeB,rB) ;
4 Comments
Bruno Luong
on 7 Dec 2020
I believe James's answer deserves the acceptation. My contribution is next to nothing.
More Answers (1)
James Tursa
on 7 Dec 2020
Edited: James Tursa
on 7 Dec 2020
Maybe try this:
sizeB = size(B);
reshapeA = reshape(A,[1 size(A)]);
reshapeB = reshape(B,[sizeB(1) 1 sizeB(2:end)]);
C = reshapeA .* reshapeB; % would do this if implicit expansion works for your case
C = bsxfun(@times,reshapeA,reshapeB); % try this if implicit expansion doesn't work for your case
Or you can swap where the 1's go in A and B if you want the 2D transpose in those first two dimensions.
EDIT
Corrected last lines above to use reshapeA and reshapeB.
Also my comment about the 1's was intended to steer you towards this solution if it was more appropriate:
sizeA = size(A);
reshapeA = reshape(A,[sizeA(1) 1 sizeA(2:end)]);
reshapeB = reshape(B,[1 size(B)]);
etc.
7 Comments
James Tursa
on 7 Dec 2020
Sorry I apparently misunderstood. But according to your post, using bsxfun was acceptable so that is what I gave you with this line, which doesn't use implicit expansion:
C = bsxfun(@times,reshapeA,reshapeB);
However, as long as you have a solution that works for you from Bruno, all is good.
See Also
Categories
Find more on Linear Algebra in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!