Creating dynamic variables using loops | Automatic Variables using loops

2 views (last 30 days)
Hello,
I believe that I am in a predicament. I have already read that trying to create variables from a loop (using eval like A1, A2, ... ) is not advisable and its better to initialize empty matrices using zeros. But I think that I have to breach this. Please advise on alternative options if you know any.
Here's the trouble.
So I need to be creating a cyclic matrix. I will create a base matrix where each element is an identity matrix shifted right by that element. For example I have created a base matrix -
Ha =
1 2 4 8 16
5 10 20 9 18
25 19 7 14 28
Now each element is actually supposed to be an identity matrix. All identity matrices's size are 31x31.
So Ha(1,1) is identity matrix of size 31x31 (hereafter referred as eye(31))
Ha (1,2) is eye(31) cyclically shifted right by 2
Ha (1,3) is eye(31) cyclically shifted right by 4
Ha (2,3) is eye(31) cyclically shifted right by 20
And so on.....
I believe that I must be creating variables like A1, A2, A4,.... to as many as I have in Ha.
How do I bypass this without creating variables using loops.
If it helps, the final matrix size is row*31 by col*31 = 3*31, 5*31
Size of Final Matrix = 93, 155
  1 Comment
Stephen23
Stephen23 on 30 Dec 2020
Edited: Stephen23 on 30 Dec 2020
"I believe that I am in a predicament."
Yes, a self-made predicament caused by this:
"I have already read that trying to create variables from a loop (using eval like A1, A2, ... ) is not advisable and its better to initialize empty matrices using zeros."
Aaah, some good advice that probably should be heeded.
But I think that I have to breach this."
I doubt that. Nothing in your explanation excludes using simpler, more reliable code, e.g. based on arrays, indexing, etc.

Sign in to comment.

Accepted Answer

Jan
Jan on 30 Dec 2020
Edited: Jan on 30 Dec 2020
[EDITED]: The direction for shiftig needs a minus sign and is applied along dimension 1:
Ha = [1 2 4 8 16; ...
5 10 20 9 18; ...
25 19 7 14 28];
HaC = cell(size(Ha));
Ha(1, 1) = 0; % Not 1
Data = eye(31);
for k = 1:numel(HaC)
HaC{k} = circshift(Data, -Ha(k), 1);
end
M = cell2mat(HaC);
Now instead of different variables you have a cell array. But you actually want to create a matrix? Then do this directly:
M = nan([31, 31, size(Ha)]);
Ha(1, 1) = 0; % Not 1
Data = eye(31);
for i3 = 1:size(Ha, 1)
for i4 = 1:size(Ha, 2)
M(:, :, i3, i4) = circshift(Data, -Ha(i3, i4), 1);
end
end
M = reshape(permute(M, [1,3,2,4]), 31 * size(Ha))

More Answers (2)

Stephen23
Stephen23 on 30 Dec 2020
Edited: Stephen23 on 30 Dec 2020
"How do I bypass this without creating variables using loops."
Here is a simple solution using basic MATLAB operations, no bad data design required:
Ha = [...
1 2 4 8 16
5 10 20 9 18
25 19 7 14 28];
F = @(n) circshift(eye(31),n,2);
C = arrayfun(F,Ha,'uni',0);
M = cell2mat(C);
size(M)
ans = 1×2
93 155
  3 Comments
Stephen23
Stephen23 on 30 Dec 2020
Edited: Stephen23 on 30 Dec 2020
"But explain to me how the code works."
F is an anonymous function with one input variable n, that creates a 31x31 identity matrix and circshifts that matrix by n. Then arrayfun applies that function to your matrix, returning a cell array where each cell contains one of the shifted matrices. Then cell2mat simply concatenates all of those matrices into one big matrix. Simple.
You can trivially change the identity matrix size by changing the input to eye (note that it can accept a row and column argument).
Stephen23
Stephen23 on 30 Dec 2020
Edited: Stephen23 on 30 Dec 2020
Because your original question and your example are inconsistent I have provided both solutions here:
Ha = [...
1 2 4 8 16;...
5 10 20 9 18;...
25 19 7 14 28];
F = @(n) circshift(eye(31),-n,2); % following your question: 2nd dim.
C = arrayfun(F,Ha,'uni',0);
M = cell2mat(C);
imagesc(M)
Ha = [...
0 2 4 8 16;...% example shows first value should be 0.
5 10 20 9 18;...
25 19 7 14 28];
F = @(n) circshift(eye(31),-n,1); % following your example: 1st dim.
C = arrayfun(F,Ha,'uni',0);
M = cell2mat(C);
imagesc(M)

Sign in to comment.


Rishi Balasubramanian
Rishi Balasubramanian on 30 Dec 2020
Okay, I kinda don't understand I guess, as I did not get the expected result from any of the answers, except Stephen's, but it had a slight error in it too.
The correct result that I am expecting is the result of this code -
I1 = eye(31);
I2 = circshift(I1, -2);
I4 = circshift(I1, -4);
I8 = circshift(I1, -8);
I16 = circshift(I1, -16);
I5 = circshift(I1, -5);
I10 = circshift(I1, -10);
I20 = circshift(I1, -20);
I9 = circshift(I1, -9);
I18 = circshift(I1, -18);
I25 = circshift(I1, -25);
I19 = circshift(I1, -19);
I7 = circshift(I1, -7);
I14 = circshift(I1, -14);
I28 = circshift(I1, -28);
Ha = [I1 I2 I4 I8 I16
I5 I10 I20 I9 I18
I25 I19 I7 I14 I28];
An imagesc(Ha) command would have produced this result -
But the results from the answers were a bit off. If you guys could help it out, it'd be great. And sorry for not being direct with the question. English is my second language and I'm trying to do my best here...
  6 Comments
Rishi Balasubramanian
Rishi Balasubramanian on 30 Dec 2020
Btw Jan got the answer, Stephen's looked more easier to understand. Wish I could accept both the answers, but I am going with Jan's. Thanks for the help.
Stephen23
Stephen23 on 30 Dec 2020
Edited: Stephen23 on 30 Dec 2020
"I guess that first matrix also is shifted by 1, hence the wrong answer."
It is exactly what you specified in your question, where you defined that the first matrix should have circshift of one:
Because later you changed your mind, I included both zero and one in my comment here.
"Is there a way to skip the first one and do the rest"
Why so complex? Just set the first element of Ha to zero, exactly as both Jan and I used.
"Jan got the answer..:"
After you kept changing and adding new information, in the end both Jan and my code gave exactly the same outputs. Exactly the same. No difference. Indistinguishable. One might even say identical. I know this because I tried them, and compared them using isequal. Did you?
"That's where the answer gets messed up."
The code here (including the two minor edits to the code given in my answer due to your changes in the requirements) gives exactly the same output as what you showed in your "answer" above (and the same as Jan's code).

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!