Creating dynamic variables using loops | Automatic Variables using loops

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

Stephen23
Stephen23 2020년 12월 30일
편집: Stephen23 2020년 12월 30일
"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
Jan 2020년 12월 30일
편집: Jan 2020년 12월 30일
[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))

추가 답변 (2개)

Stephen23
Stephen23 2020년 12월 30일
편집: Stephen23 2020년 12월 30일
"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

Omg, that works like crazy. But explain to me how the code works. Im trying to write a generalised code that accepts the row, column size and size of Identity matrix.
Stephen23
Stephen23 2020년 12월 30일
편집: Stephen23 2020년 12월 30일
"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).
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)

댓글을 달려면 로그인하십시오.

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

Stephen23
Stephen23 2020년 12월 30일
편집: Stephen23 2020년 12월 30일
Your example does not match your question. In your question you wrote "...each element is an identity matrix shifted right by that element." (bold added), but in your example above you relied on the circshift default behavior when the dimension argument is not specified, which is "... then circshift shifts along the first dimension of A whose size does not equal 1", which in your case is the first dimension (rows).
So your example shifts along the first dimension, but in your question you specified the second dimension.
Which is correct: your question or this example?
Jan
Jan 2020년 12월 30일
편집: Jan 2020년 12월 30일
In addition the first matrix is not shifted by 1 element, but by 0 elements. So why is Ha(1,1) not 0? I've adjusted my answer accordingly.
The main point remains: There is no reason to create the variables dynamically, because the problem can be solved directly with cell, a loop or arrayfun.
Okay, the example is the correct one. The matrix diagonal is shifted right, by the number of the element. ANd yeah, the I1 matrix(first) is not shifted, it is a normal Identity matrix I1.
I tried the answers and Stephen's answer works upto the cell2mat concatenation part. That's where the answer gets messed up. I need the exact result as I posted the imagesc picture. For some reason, the concat doesn't work as it did in my elaborate direct approach program. Any ideas on how to do that? I guess that first matrix also is shifted by 1, hence the wrong answer. Is there a way to skip the first one and do the rest????
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 2020년 12월 30일
편집: Stephen23 2020년 12월 30일
"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).

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

질문:

2020년 12월 30일

편집:

2020년 12월 30일

Community Treasure Hunt

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

Start Hunting!

Translated by