How to create the upper diagonal block matrix in a specific form.

c = input('c ');
g = input('g ');
syms Lambda_n
M = cell(c+1,1);
a_t = min([1:c+1;repmat(c-g+1,1,c+1)]);
for i = 1:c+1
v = zeros(1,c+2-i, 'sym');
v(1)= Lambda_n*i;
MCell = repmat({diag(v)}, 1, a_t(i));
M{i} = blkdiag(MCell{:});
end
B=blkdiag(M{:});
'c' will determine the size of blocks which I already explained to you that they will be in decreasing order. 'g' is basically used in a_t = ,min{j,c-g}. Here a_t determines how many time a block should be repeated. So upto c-g the order of block upper diagonal matrix will be (i+1,i) and from c-g+1 upto c+1 it will be (c-g+1,c-g+1).
This is for the main diagonal block matrix which is shown in the picture. Similarly I want to create the upper diagonal as shown by the red line in the picture. I have tried to creat it using kron function but it was just not what i wanted. Kindly help me with this.

10 Comments

This time I edited your question for you. Next time, please use the tools explained on this page to make your question more readable.
Each added part seems to be [zeros(k,1) A*eye(k)]. Is your question how to create the matrix in the image? It looks like you describe B as a matrix in your code, but it makes more sense that B is a scalar in your image. How would you define A?
I will keep in mind next time. Thank you for this. B and A both are matrices in this image and the zeros are also block matrices of respective orders. In the code the output 'B', please consider it as a whole matrix which is shown in the figure. By mistake it happened. A is a matrix of order (c+1,c) for the first block, then (c,c-1) for the second block, similarly A will have decreasing order upto (2,1).
So A is actually not the same each time it is used? That seems a very strange thing to do.
Since you have managed to generate the appropriate B, what issues did you encounter when trying to write the code for A?
The issue is not with creating the A matrix actually. The issue is with creating the upper diagonal. I can create the A. For example let's consider A is a matrix of one's. For c=3,g=1, the first block of upper diagonal block will be zero matrix of order 4*3, and A matrix of one's order 4*3. Then in the second block the size will reduced now by one. So the new dimension will be 3*2 for the block [O A O
O O A] .
So my issue is I am not able to create this upper diagonal.
That block will not be of size [2 3], but of size [2 3].*size(A). You should be able to use that to assign the contents to your pre-defined full array.
yes that block will be of size [2,3]*size(A). How can I create that?
You didn't explain how to create A. Since that is apparently obvious, the creation of that matrix shouldn't be a problem.
c = input('c ');
g = input('g ');
syms Lambda_n
for i = 1:c+1
for j = 1:c
if i==1 & j==1
A(i,j) = Lambda_n;
else A(i,j)=0;
end
end
end
This is the code for matrix A. Now for the first upper diagonal block [O A] the order of O and A will be (c+1,c). for the second block [O A O ; the order of 'O' and A will be (c,c-1). Similarly for
O O A]
third block the order of 'O' and A will be (c-1,c-2) and so on. 'O' is zero matrix.
Can someone plese help me with this probelm? I am new at MATLAB coding and I really need this job to be done. I am trying hard. If not the whole thing just give me some hint so that I can work in that direction. Please someone consider this.

Sign in to comment.

 Accepted Answer

Here is the code that will generate blocks like [O A O;O O A] given the values of c and g.
clear,clc
c = 3;
g = 1;
syms Lambda_n
%replacement for the loop:
A=Lambda_n;
A(c+1,c)=0;
put_A_here=logical([zeros(c-1,1) eye(c-1)]);
big=repmat(sym(0),size(put_A_here).*size(A));
big=insert_matrix(big,A,put_A_here);
function out=insert_matrix(big,small,L)
out=big;
A=reshape(1:numel(small),size(small));
B=repmat({zeros(size(A))},size(L));
B(L)={A};
B=cell2mat(B);
B=B(:);
out(B~=0)=small(B(B~=0));
end

6 Comments

I am not able to run this code. It's saying small is undefined. Can you please help me to understand what's happening here.
Then you changed my code. What code are you running?
No I didn't make any changes. I just copied it and run it, first it gave 'function definition not permitted in this context' error then 'small undefined variable or function' error. I don't know what to do here.
If you are using a release prior to R2016b you should mention that. Starting from that release you are allowed to put local functions in a script file. You can use something like this instead:
function big=get_A_part(c,g)
if nargin==0
c = 3;
g = 1;
end
syms Lambda_n
%replacement for the loop:
A=Lambda_n;
A(c+1,c)=0;
put_A_here=logical([zeros(c-1,1) eye(c-1)]);
big=repmat(sym(0),size(put_A_here).*size(A));
big=insert_matrix(big,A,put_A_here);
end
function out=insert_matrix(big,small,L)
out=big;
A=reshape(1:numel(small),size(small));
B=repmat({zeros(size(A))},size(L));
B(L)={A};
B=cell2mat(B);
B=B(:);
out(B~=0)=small(B(B~=0));
end
Thank you so much Rik. It's working perfectly.
In response to your email: you can actually use this function to create the entire matrix.
Note that this will be different from the image you posted (on the last line). You can easily confirm this by using this line, instead of generating the real A and B matrices:
A=sym('A');B=sym('B');
Do you notice the difference? You should always try to separate the steps into functions. That way you have a clear flow of the program. Once you have written one part you don't need to worry about the internals. You only need to worry about the interface: what inputs does it need and what will its output be. By writing functions like this, it is easy to re-use a function like insert_matrix, without having to put all the code in here twice. This way a future reader will immediately understand what is happening. (Remember: future you is a different person that may not understand what you did. Write your code so that even strangers like future you understand what you did.)
%separate input and processing: ask the user for the input once and use those as input to your functions
%in your command window (or another function) you can do this:
main(3,1,4)
function big=main(c,g,steps)
if nargin==0
%get user input
c = input('c ');
g = input('g ');
steps = input('number of A blocks ');
end
%create logical arrays for where the B and A arrays should be inserted
sz=[sum(1:steps) sum(1:steps)+1+steps];
put_A_here=generate_put_A_here(steps);
put_B_here=generate_put_B_here(sz);
%create A and B
A=get_A(c,g);
B=get_B(c,g);
%A=sym('A');B=sym('B');%useful for viewing the output array
%insert into a large symbolic array
big=repmat(sym(0),sz.*size(B));
big=insert_matrix(big,B,put_B_here);
big=insert_matrix(big,A,put_A_here);
end
function put_A_here=generate_put_A_here(steps)
%generate the staggered logical array describing where A should end up
sz=[sum(1:steps) sum(1:steps)+1+steps];
offset=floor(sqrt(2*(1:sz(1))) + 1/2);%source: https://oeis.org/A002024
[row,col]=find(eye(sz(1)));%diagonal positions
col=col+1+offset(:);%apply offset
put_A_here=false(sz);%pre-allocate output
put_A_here(sub2ind(sz,row,col))=true;%mark positions
end
function put_B_here=generate_put_B_here(sz)
%generate the extended identity matrix describing where B should end up
put_B_here=logical(eye(sz(1)));%get base positions for B
put_B_here(1,sz(2))=false;%extend to make room for A-blocks
end
function A=get_A(c,g)
syms Lambda_n
A=Lambda_n;
A(c+1,c)=0;
end
function B=get_B(c,g)
syms Lambda_n
M = cell(c+1,1);
a_t = min([1:c+1;repmat(c-g+1,1,c+1)]);
for i = 1:c+1
v = zeros(1,c+2-i, 'sym');
v(1)= Lambda_n*i;
MCell = repmat({diag(v)}, 1, a_t(i));
M{i} = blkdiag(MCell{:});
end
B=blkdiag(M{:});
end
function out=insert_matrix(big,small,L)
out=big;
A=reshape(1:numel(small),size(small));
B=repmat({zeros(size(A))},size(L));
B(L)={A};
B=cell2mat(B);
B=B(:);
out(B~=0)=small(B(B~=0));
end

Sign in to comment.

More Answers (0)

Categories

Asked:

on 20 Apr 2020

Commented:

Rik
on 22 Apr 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!