How to extract block matrices along the diagonal entries without looping?
Ältere Kommentare anzeigen
I have a square matrix, A with dimension (N*k x N*k), and I want to extract the sum of all the diagonal entries of the block matrices (each block, Aii, with dimension NxN).
A =
[A11, A12, ..., A1k
A21, A22, ..., A2k
...
Ak1, Ak2, ..., Akk]
Then I want to obtain the sum of the main diagonal (A11 + A22 + ...), and (A21 + A32 + ...) and so on...
A is symmetric in the blocks, i.e. A12 = A21, so lower/upper entries suffice.
If you have a way to extract the sum just for the main diagonal it will be excellent as well, since deleting block rows and block columns will get me the desired diagonal.
Multiple loops is unfortunately not an option for me due to the size of the problem.
9 Kommentare
Image Analyst
am 27 Jul. 2014
What is the size exactly? Is Nxk more than 10 thousand or so?
Anders
am 27 Jul. 2014
Star Strider
am 27 Jul. 2014
The obvious next question: what are N and k?
Anders
am 27 Jul. 2014
per isakson
am 27 Jul. 2014
"Without looping"   - even if that is faster?
Image Analyst
am 27 Jul. 2014
That's a rather small array. The "size of the problem" is smaller than a run of the mill color digital image. Why are you afraid of a for loop in such a small array? I'd use a for loop just because it's so simple and intuitive. Maybe someone will come along and give you a one liner that uses some exotic matrix like toeplitz, hankle, circulant, or something. But a for loop to do a few million iterations should complete in less than a second.
Anders
am 27 Jul. 2014
Star Strider
am 27 Jul. 2014
So you have a matrix of 1400 (3x3) submatrices, and you want the sums of the (main) diagonals of the submatrices, probably returned as a matrix, or do I have it backwards?
Anders
am 28 Jul. 2014
Akzeptierte Antwort
Weitere Antworten (5)
per isakson
am 28 Jul. 2014
Bearbeitet: per isakson
am 28 Jul. 2014
This function takes 3 seconds on my machine and I guess less than half of that on the machine of Image.
function S = cssm()
N = 3;
k = 1400;
A = rand( N*k, N*k );
S = zeros( N, k, k );
cc_blk = 0;
for cc = 1 : N : N*k
cc_blk = cc_blk + 1;
rr_blk = 0;
for rr = 1 : N : cc
rr_blk = rr_blk + 1;
S(:,rr_blk,cc_blk) = [ A(rr ,cc)+A(rr+1,cc+1)+A(rr+2,cc+2)
A(rr+1,cc)+A(rr+2,cc+1)
A(rr+2,cc) ];
end
end
end
1 Kommentar
Image Analyst
am 28 Jul. 2014
Bearbeitet: Image Analyst
am 28 Jul. 2014
On my Dell M6800:
Elapsed time is 1.102767 seconds.
Does this get the sum of the diagonals all the way down to the very bottom of the matrix like my toeplitz solution does?
Image Analyst
am 27 Jul. 2014
Why not simply do
% Create sample data
A = rand(N*k, N*k);
N = 3;
k = 1400;
% Initialize mask
mask = zeros(N*k, N*k);
tic; % Start timer
for row = 1 : N : N*k
r1 = row;
r2 = r1 + N - 1;
mask(r1:r2, r1:r2) = 1;
end
% Extract from A
A_masked = A .* mask;
toc; % Takes 0.05 seconds on my computer.
It's simple and fast - only 0.05 seconds on my computer even with the sizes you gave.
2 Kommentare
Image Analyst
am 28 Jul. 2014
After seeing per's answer and reading yours again, I think this might not be what you wanted. I had thought that k was the smaller dimension and you had a bunch of blocks k wide placed along the main diagonal.
Image Analyst
am 28 Jul. 2014
Bearbeitet: Image Analyst
am 28 Jul. 2014
An alternative way:
tic
N = 3;
k = 1400;
A = rand( N*k, N*k );
c = 1:k;
r = 1:k;
% Get the sums going down from the top row.
t = toeplitz(c,r);
upper_t = triu(t);
for c = 1 : k
diagVector = A(upper_t == c);
theDiagSumsTop(c) = sum(diagVector);
end
toc
Takes 4.6 seconds though.
4 Kommentare
Image Analyst
am 28 Jul. 2014
I did sum the diagonals with my toeplitz method. Now you're saying something about blocks and submatrixes so I don't know what you're wanting to sum. Please give a small example with say a dozen rows and columns and 3 blocks and tell what you want summed.
per isakson
am 28 Jul. 2014
"% S is an (Ni x Ni)"   I assume that this comment is a mistake. It contradicts the comment, "% Collected in an [Ni x N]-matrix"
Anders
am 28 Jul. 2014
Image Analyst
am 29 Jul. 2014
It's not clear. All I asked for was a simple example array, like
m=[
1 2 3 0 0 0 0 0 0;...
2 1 5 0 0 0 0 0 0;...
3 5 1 0 0 0 0 0 0;...
0 0 0 9 8 3 0 0 0;...
0 0 0 8 5 2 0 0 0;...
0 0 0 3 2 7 0 0 0;...
0 0 0 0 0 0 7 3 1;...
0 0 0 0 0 0 3 4 5;...
0 0 0 0 0 0 1 5 1]
and then you tell me if the second sum is actually 3 sums: 2+5 (just over the first block), then 8+2, then 3+5, OR if it's just a single sum of 2+5+0+8+2+0+3+5 (diagonal crosses all 3 blocks). But if you don't want to, that's fine. Good luck. By the way, the toeplitz solution I gave covers all the blocks, not just one of them.
Swarup Rj
am 19 Jan. 2015
0 Stimmen
Is it same as " FINDING THE SUM OF DIAGONAL BLOCKS OF A MATRIX."
I am solving an optimization problem on Clustering.
If you have the code .. do help.. :-)
Kategorien
Mehr zu Operating on Diagonal Matrices finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!