fYpsE
fYpsE

Reputation: 67

create a tridiagonal matrix with other matrices in Matlab

I have an algorithm that creates random nxn-matrices A(i,j) and now I want this matrices in a tridiagonal shape:

A(1,1) A(1,2)  0       0      0
A(2,1) A(2,2) A(2,3)   0      0
  0    A(3,2) A(3,3) A(3,4)   0
  0      0    A(4,3) A(4,4) A(4,5)

And so on.

I tried the commands diag and tridiag but both are just working for integers.

EDIT I will explain my problem with an example: I create different random 3x3matrices:

a=randi(10,3);
b=randi(10,3);
...
k=randi(10,3)

And now I want to create a big tridiagonal matrix L where the random matrices a,...,k are on the sub-, super- and diagonal line:

L= a b 0 0 0
   c d e 0 0
   0 f g h 0
   0 0 i j k

Upvotes: 1

Views: 871

Answers (2)

Divakar
Divakar

Reputation: 221644

It seems you want to keep both subdiagonal and superdiagonal elements in there alongwith the diagonal ones.

Approach #1

First approach could be with bsxfun there for a generic m x n sized matrix -

[m,n] = size(A); %// get size
Aout = A.*( bsxfun(@le,[0:m-1]',1:n) & bsxfun(@ge,[1:m]',0:n-1))

Sample run -

A =
     1     2     2     2     6
     6     4     8     4     3
     8     5     6     5     4
     7     9     4     2     6
Aout =
     1     2     0     0     0
     6     4     8     0     0
     0     5     6     5     0
     0     0     4     2     6

Approach #2

If you were working with tridiag obtained from here, you could have just done the following for n x n sized matrices -

Aout = A.*tridiag(1,1,1,n)

Edit

With reference to the edited part of the question, this code should work -

%// Create regularly shaped all matrices holding variable. 
%// This regularity would be used for cutting into a 3D array in the next step
A = cat(1,NaN(3),a,c,b,d,f,e,g,i,h,j,NaN(3),k,NaN(3),NaN(3));

%// Cut A after every 9 rows
N = 9;
Acut = permute(reshape(A,N,size(A,1)/N,[]),[1 3 2])

%// Create mask that will act as the building unit for L
m = 4;n = 5; 
mask = bsxfun(@le,[0:m-1]',1:n) & bsxfun(@ge,[1:m]',0:n-1)

%// Setup L with ones at places where elements from matrices are top be put
sf = 3; %// scaling factor
L = double(mask(ceil(1/sf:1/sf:size(mask,1)), ceil(1/sf:1/sf:size(mask,2))))

%// Finally, place the elements from matrices into their respective places
L(L==1) = Acut(~isnan(Acut))

Upvotes: 0

Rash
Rash

Reputation: 4336

You have to figure out a combination of trill and triu

 a = randi(9,4,5);
 a .* triu(ones(4,5),-1).*tril(ones(4,5),1)

 >>ans =

 4     6     0     0     0
 9     1     7     0     0
 0     8     7     7     0
 0     0     4     1     8

And for floating data it will do the same,

 a = rand(4,5);
 a .* triu(ones(4,5),-1).*tril(ones(4,5),1)

>>ans =

0.6948    0.4387         0         0         0
0.3171    0.3816    0.4898         0         0
     0    0.7655    0.4456    0.2760         0
     0         0    0.6463    0.6797    0.4984

More efficiently (thanks to @Divakar),

a.*(triu(ones(4,5),-1) & tril(ones(4,5),1));

Or even more simpler (thanks to @LuisMendo),

tril(triu(a,-1),1);

Upvotes: 2

Related Questions