简体   繁体   中英

Diagonal matrix in matlab

I am having trouble creating this matrix in matlab, basically I need to create a matrix that has -1 going across the center diagonal followed be 4s on the diagonal outside of that (example below). All the other values can be zero.

 A5 = [-1 4 0 0 0;
     4 -1 4 0 0;
     0 4 -1 4 0;
     0 0 4 -1 4;
     0 0 0 4 -1];

I have tried using a command v = [4]; D = diag(v) v = [4]; D = diag(v) but that only works for the center diagonal.

This can also be done using a toeplitz matrix:

function out = tridiag(a,b,c,N)
% TRIDIAG generates a tri-diagonal matrix of size NxN.
% lower diagonal is a
%  main diagonal is b
% upper diagonal is c
out = toeplitz([b,a,zeros(1,N-2)],[b,c,zeros(1,N-2)]);

>> tridiag(4,-1,4,5)

ans =

    -1     4     0     0     0
     4    -1     4     0     0
     0     4    -1     4     0
     0     0     4    -1     4
     0     0     0     4    -1

Note #1: When your desired output is symmetric, you can omit the 2 nd input to toeplitz .

Note #2: As the size of the matrix increases, there comes a point where it makes more sense to store it as sparse , as this saves memory and improves performance (assuming your matrix is indeed sparse , ie comprised mostly of zeros, as it happens with a tridiagonal matrix). Some useful functions are spdiags , sptoeplitz FEX and blktridiag FEX .

A little hackish, but here it goes:

N = 7; % matrix size
v = [11 22 33]; % row vector containing the diagonal values
w = [0 v(end:-1:1)];
result = w(max(numel(v)+1-abs(bsxfun(@minus, 1:N, (1:N).')),1))

This gives

result =
    11    22    33     0     0     0     0
    22    11    22    33     0     0     0
    33    22    11    22    33     0     0
     0    33    22    11    22    33     0
     0     0    33    22    11    22    33
     0     0     0    33    22    11    22
     0     0     0     0    33    22    11

To understand how it works, see some intermediate steps:

>> abs(bsxfun(@minus, 1:N, (1:N).'))
ans =
     0     1     2     3     4     5     6
     1     0     1     2     3     4     5
     2     1     0     1     2     3     4
     3     2     1     0     1     2     3
     4     3     2     1     0     1     2
     5     4     3     2     1     0     1
     6     5     4     3     2     1     0

>> max(numel(v)+1-abs(bsxfun(@minus, 1:N, (1:N).')),1)
ans =
     4     3     2     1     1     1     1
     3     4     3     2     1     1     1
     2     3     4     3     2     1     1
     1     2     3     4     3     2     1
     1     1     2     3     4     3     2
     1     1     1     2     3     4     3
     1     1     1     1     2     3     4

Use D = diag(u,k) to shift u in k levels above the main diagonal, and D = diag(u,-k) for the opposite direction. Keep in mind that you need u to be in the right length of the k diagonal you want, so if the final matrix is n*n, the k 's diagonal will have only n-abs(k) elements.

For you case:

n = 5;           % the size of the matrix 
v = ones(n,1)-2;   % make the vector for the main diagonal
u = ones(n-1,1)*4; % make the vector for +1 and -1 diagonal
A5 = diag(v)+diag(u,1)+diag(u,-1) % combine everything together

Which gives:

A5 =

    -1     4     0     0     0
     4    -1     4     0     0
     0     4    -1     4     0
     0     0     4    -1     4
     0     0     0     4    -1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM