Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a diagonal of zeros to a matrix in MATLAB

Suppose I have a matrix A of dimension Nx(N-1) in MATLAB, e.g.

N=5;
A=[1  2  3  4;
   5  6  7  8;
   9  10 11 12;
   13 14 15 16;
   17 18 19 20 ];

I want to transform A into an NxN matrix B, just by adding a zero diagonal, i.e.,

B=[ 0  1   2   3   4;
    5  0   6   7   8;
    9  10  0   11  12;
    13 14  15  0   16;
    17 18  19  20  0];

This code does what I want:

B_temp = zeros(N,N); 
B_temp(1,:) = [0 A(1,:)];
B_temp(N,:) = [A(N,:) 0];
for j=2:N-1
    B_temp(j,:)= [A(j,1:j-1) 0 A(j,j:end)];
end
B = B_temp; 

Could you suggest an efficient way to vectorise it?

like image 420
TEX Avatar asked Dec 08 '17 11:12

TEX


People also ask

How do you add a diagonal to a matrix in Matlab?

D = diag( v ) returns a square diagonal matrix with the elements of vector v on the main diagonal. D = diag( v , k ) places the elements of vector v on the k th diagonal. k=0 represents the main diagonal, k>0 is above the main diagonal, and k<0 is below the main diagonal.

How do you add diagonals to a matrix?

Calculate the sum of diagonal elements of a matrix Let us understand the logic before going to a solution. (i=j). and condition for the right diagonal element is ( i+j=N-1). where i and j are position coordinates and N is the size of Matrix.

Can a diagonal matrix have a zero of the diagonal?

A diagonal matrix is defined as a square matrix in which all off-diagonal entries are zero. (Note that a diagonal matrix is necessarily symmetric.) Entries on the main diagonal may or may not be zero.

What do you call a matrix with zeros on the diagonal?

A hollow matrix may be a square matrix whose diagonal elements are all equal to zero.


1 Answers

You can do this with upper and lower triangular parts of the matrix (triu and tril).

Then it's a 1 line solution:

B = [tril(A,-1) zeros(N, 1)] + [zeros(N,1) triu(A)];

Edit: benchmark

This is a comparison of the loop method, the 2 methods in Sardar's answer, and my method above.

Benchmark code, using timeit for timing and directly lifting code from question and answers:

function benchie()
    N = 1e4; A = rand(N,N-1); % Initialise large matrix
    % Set up anonymous functions for input to timeit
    s1 = @() sardar1(A,N); s2 = @() sardar2(A,N); 
    w =  @() wolfie(A,N); u = @() user3285148(A,N);
    % timings
    timeit(s1), timeit(s2), timeit(w), timeit(u)
end
function sardar1(A, N) % using eye as an indexing matrix
    B=double(~eye(N)); B(find(B))=A.'; B=B.';
end
function sardar2(A,N) % similar to sardar1, but avoiding slow operations
    B=1-eye(N); B(logical(B))=A.'; B=B.';
end
function wolfie(A,N) % using triangular parts of the matrix
    B = [tril(A,-1) zeros(N, 1)] + [zeros(N,1) triu(A)];
end
function user3285148(A, N) % original looping method
    B = zeros(N,N); B(1,:) = [0 A(1,:)]; B(N,:) = [A(N,:) 0];
    for j=2:N-1; B(j,:)= [A(j,1:j-1) 0 A(j,j:end)]; end
end

Results:

  • Sardar method 1: 2.83 secs
  • Sardar method 2: 1.82 secs
  • My method: 1.45 secs
  • Looping method: 3.80 secs (!)

Conclusions:

  • Your desire to vectorise this was well founded, looping is way slower than other methods.
  • Avoiding data conversions and find for large matrices is important, saving ~35% processing time between Sardar's methods.
  • By avoiding indexing all together you can save a further 20% processing time.
like image 118
Wolfie Avatar answered Sep 17 '22 20:09

Wolfie