2

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) but that only works for the center diagonal.

user3609179
  • 301
  • 8
  • 20

3 Answers3

6

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 2nd 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, i.e. comprised mostly of zeros, as it happens with a tridiagonal matrix). Some useful functions are spdiags, sptoeplitzFEX and blktridiagFEX.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
4

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
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
2

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
EBH
  • 10,350
  • 3
  • 34
  • 59