Consider two matrices A and B defined by
A=rand(10,3);
B=rand(3,10);
I'm interested in multiplying the vectors defined the first, second, and third rows in B by the vectors defined the first, second, and third columns in A, respectively. My intent is to generate ten, 3X3 matrices defined by
Matrix1= B(:,1)*A(1,:)
Matrix2= B(:,2)*A(2,:)
...
Matrix10= B(:,10)*A(10,:)
My initial thought was something like
B(:,1:10)*A(1:10,:)
but this approach populates the matrices B and A prior to multiplication, yielding a single 3X3 matrix. How to I change the "order-of-operations" if you will---call each vector on a term-by-term basis, multiplying in between each call to generate the desired matrix? Of course, I really want to avoid having to use for loops.

 채택된 답변

Matt J
Matt J 2012년 10월 15일

0 개 추천

Here's a completely vectorized method, which requires James Tursa's MTIMESX function, available at the link below
A=reshape(A',1,3,10);
B=reshape(B,3,1,10);
C=mtimesx(B,A)

댓글 수: 3

John
John 2012년 10월 15일
Thanks everyone for your prompt comments. I tested each solution by defining
A=rand(10000,3);
B=rand(3,10000);
and nesting each code fragment into 100-iteration for loop. Here were the speeds on my box:
Azzi: 1.46 seconds
Matt Fig's cellfun approach: 7.33 seconds (your prediction was right---the cellfun approach was much slower)
Matt J's cellfun approach: 9.06 seconds
MTIMESX function: 0.156 seconds.
Wow---an order-of-magnitude speed increase over for loops using MTIMESX. That was pretty sick. I think there might be a lot of functionality in this James Tursa code that I need to check out.
Thanks again for all your help!
Amandeep Gautam
Amandeep Gautam 2015년 10월 22일
I wonder if there is anything wrong with A' * B? Seems like it does the same thing. Can you comment?
That will generate an error
>> A=rand(10,3); B=rand(3,10); A'*B
Error using *
Inner matrix dimensions must agree.

댓글을 달려면 로그인하십시오.

추가 답변 (4개)

Azzi Abdelmalek
Azzi Abdelmalek 2012년 10월 15일
편집: Azzi Abdelmalek 2012년 10월 15일

0 개 추천

for k=1:10
matrix{k}=B(:,k)*A(k,:)
end
%or
for k=1:10
matrix(:,:,k)=B(:,k)*A(k,:)
end
Matt Fig
Matt Fig 2012년 10월 15일
편집: Matt Fig 2012년 10월 15일

0 개 추천

I think you can avoid FOR loops, but I see no reason to do so here:
A=randi(10,10,3);
B=randi(10,3,10);
for ii = 10:-1:1,C{ii} = B(:,ii)*A(ii,:);end
Here is a vectorization, but I can almost guarantee you it will be slower than the above FOR loop:
cellfun(@mtimes,mat2cell(B,3,ones(1,10)).',mat2cell(A,ones(1,10),3),'Un',0)
Matt J
Matt J 2012년 10월 15일

0 개 추천

Here's a 1-liner. It's syntactically brief, but not superior to using loops directly,
C=cellfun(@(a,b) a(:)*b(:).', num2cell(B,1), num2cell(A,2).', 'uni',0)
Richard Brown
Richard Brown 2012년 10월 15일
편집: Richard Brown 2012년 10월 15일

0 개 추천

There is a built in way to do it quickly if you use sparse multiplication. Essentially, you construct the block diagonal matrix blkdiag(B(:, 1), ... , B(:, N)) directly, and multiply it by A to give Y = [B(:, 1)*A(1, :) ; ... ; B(:, N) * A(N, :)]
N = 10000;
A = rand(N, 3);
B = rand(3, N);
I = 1:3*N;
J = repmat(1:N, 3, 1);
Y = mat2cell(sparse(I, J, B) * A, repmat(3, N, 1), 3);
edit: brief explanation added

댓글 수: 3

Matt J
Matt J 2012년 10월 16일
Note: both mat2cell and repmat are mfiles that use for-loops, so the solution is not precisely speaking "builtin"
Richard Brown
Richard Brown 2012년 10월 16일
Well, it depends what precisely speaking we mean by "built in" doesn't it?! My definition is that if it comes with a basic MATLAB install it's builtin.
Also, the mat2cell call isn't necessary -- it's just to convert it to the output format in some of the other answers. And the code doesn't touch the branch of repmat that uses for loops. Poor old for loops, they get such a hard time here :)
Matt J
Matt J 2012년 10월 16일
I suppose that's true...

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Resizing and Reshaping Matrices에 대해 자세히 알아보기

태그

질문:

2012년 10월 15일

댓글:

2015년 10월 22일

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by