Error when creating a tensor from a for loop

4 views (last 30 days)
I want to write a function that stores calculated values ​​depending on the position in x1, x2 and x3 in a tensor (3D array). My current code works with a regular spacing of 1 between the array values:
F_array = zeros(27, 27, 27);
for x1 = -13:1:13
for x2 = -13:1:13
for x3 = -13:1:13
% F = f(x1, x2, x3);
F_array(x1+14, x2+14, x3+14) = F;
end
end
end
To get more accurate result, I tried to reduce the spacing between the array values to 0.5:
F_array = zeros(53, 53, 53);
for x1 = -13:0.5:13
for x2 = -13:0.5:13
for x3 = -13:0.5:13
% F = f(x1, x2, x3);
F_array(x1+27, x2+27, x3+27) = F;
end
end
end
However, now I get the following error message:
"Index in position 3 is invalid. Array indices must be positive integers or logical values."
I don't see any overall difference in the codes. Can anyone tell me what is causing this problem?

Accepted Answer

Stephen23
Stephen23 on 2 Jan 2025
Edited: Stephen23 on 2 Jan 2025
"Can anyone tell me what is causing this problem?"
Explanation
Look at the values that you are using as indices. For the 1st code using integer steps, e.g.:
x1 = -13:1:13;
x1+14
ans = 1×27
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
For the 2nd code using steps of 0.5:
x1 = -13:0.5:13;
x1+27
ans = 1×53
14.0000 14.5000 15.0000 15.5000 16.0000 16.5000 17.0000 17.5000 18.0000 18.5000 19.0000 19.5000 20.0000 20.5000 21.0000 21.5000 22.0000 22.5000 23.0000 23.5000 24.0000 24.5000 25.0000 25.5000 26.0000 26.5000 27.0000 27.5000 28.0000 28.5000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Are MATLAB indices allowed to contain fractional parts? (hint: no). Is 14.5 a valid index?(hint: no).
"I don't see any overall difference in the codes."
Your computer does not care what you "see" or imagine or want or hope or believe your code is doing. To debug code you need to look at what it actually is doing. Usually the first step is to display the relevant values, to see if they make sense.
Error messages are also very important.
Solution
In general with MATLAB it is much easier and more reliable to loop over indices, not over data values. Once you learn to do this, your code will be more robust and much more generalised. In your specific case, do NOT fiddle around with offsets and scaling: this is a dead-end approach that forces you to awkwardly modify all of your code every time you want to change any step size or start point. Ugh, bad code design! It forces you into writing code that makes you do more work.
However you can easily write code that works for any data vector (including data vectors with e.g. unequal step sizes or real-world sampled data):
V1 = -13:0.5:13; % the step size here is irrelevant
V2 = -13:0.5:13; % the step size here is irrelevant
V3 = -13:0.5:13; % the step size here is irrelevant
N1 = numel(V1);
N2 = numel(V2);
N3 = numel(V3);
F_array = nan(N1,N2,N3); % automatically adjust the output array size
for k1 = 1:N1
for k2 = 1:N2
for k3 = 1:N3
F = f(V1(k1),V2(k2),V3(k3));
F_array(k1,k2,k3) = F;
end
end
end
Now you can change the step size or start value and it will work automatically adjust the output array size and the indices and how many iterations without you needing to make any other changes... this is how you write generalised code.
Do NOT fiddle around with offsets & scaling, unless you really want fragile code that is painful to modify and maintain.
  1 Comment
Bruce
Bruce on 2 Jan 2025
Thank you for the explanation and the solution, it works very well.

Sign in to comment.

More Answers (1)

Sameer
Sameer on 2 Jan 2025
The issue arises because the indices in MATLAB must be positive integers. When you change the spacing between the values to 0.5, the indices "x1+27", "x2+27", and "x3+27" become non-integers, which is not allowed for indexing.
To fix this, you need to convert the indices to integers. One way to do this is by scaling the indices appropriately.
You can do this by multiplying the indices by 2 to account for the 0.5 spacing and then adding an offset.
Here's how you can modify your code:
F_array = zeros(53, 53, 53);
for x1 = -13:0.5:13
for x2 = -13:0.5:13
for x3 = -13:0.5:13
% F = f(x1, x2, x3);
idx1 = round((x1 + 13) * 2 + 1);
idx2 = round((x2 + 13) * 2 + 1);
idx3 = round((x3 + 13) * 2 + 1);
F_array(idx1, idx2, idx3) = F;
end
end
end
Hope this helps!
  1 Comment
Bruce
Bruce on 2 Jan 2025
Thanks, this approach helped fix the issue, but I extended the code as Stephen suggested to make it more robust.

Sign in to comment.

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!