# Creating dynamic variables using loops | Automatic Variables using loops

3 views (last 30 days)
Rishi Balasubramanian on 30 Dec 2020
Edited: Stephen23 on 30 Dec 2020
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
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.

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))

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
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)

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...
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.
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).