# Looping a function with different inputs and storing multiple outputs.

10 views (last 30 days)
Memek on 9 Jan 2020
Commented: Memek on 10 Jan 2020
The problem I'm having is related to looping a function over a grid of inputs. More specifically, I seem to be unable to create an initial matrix for preallocation such that the estimated output is stored properly. I'll provide a brief description before moving on to the actual code.
-- Description.
The goal is to loop a maximum likelihood function over a grid of three arrays. The underlying maximum likelihood function utilizes simulated annealing to numerically estimate thirteen parameters. This maximum likelihood function utilizes a kalman filter to decompose observables into unobservables; trend and cyclical terms. To overcome the identification issue related to having two error terms, I omit the error term parameters pertaining to the cyclical variables, and impose relative variances in the initial variance bounds restrictions.
Therfore, the goal is to loop the maximum likelihood function with three relative variances; such that all outputs (parameters and their associated likelihoods) are stored after every estimation (for every relative variance).
-- Code.
The idea is to loop the maximum likelihood function over a grid of three arrays. In this case, these are given by [g1, g2, g3]. For simplicity, these are (0.5:1:2.5).
1) The [P] output is a function of simulated annealing ("SIMANN") and a likelihood function ("likelihoodfunction"). The main concern here is not related to the codes within these functions, but to the storing of output values they create.
2) The "SIMANN" function only permits one input variable (theta), which is why I have chosen to loop this process multiple times, rather than modifying the "SIMANN" function directly. This isn't the most kosher way of doing this, but the underlying code in the "SIMANN" function isn't something I want to tinker with.
3) The "P" output array is 1x13, whereas "L" is 1x1.
4) In the segment below, I have tried to modify the answer from one of the threads here. This portion is only for the "L" portion of the problem at hand.
L = zeros(3,3,3)
fidx = zeros(3,3,3,3)
for g1=0.5:1:2.5
for g2=0.5:1:2.5
for g3=0.5:1:2.5
% 1. Initial (fictional) values. Not the full code, just an illustration of how the gamma values enter into theta.
theta=[1,2,3,4,5,6,7,8,9,10,g1,g2,g3]
% 2. "P" is a 1x13 array of estimated parameter values.
P=SIMANN('likelihoodfunction', theta);
% 3. The likelihood, L, is produced separately as L.
L=-likelihoodfunction(P);
fidx(g1,g2,g3,:) = [g1,g2,g3];
end
end
end
g1 = reshape(fidx(:,:,:,1), [], 1);
g2 = reshape(fidx(:,:,:,2), [], 1);
g3 = reshape(fidx(:,:,:,3), [], 1);
L = L(:);
results = table(g1, g2, g3, :);
To reiterate, the objective is to loop this segment of the code over a grid of three input arrays. The problem I'm having is how to properly define the preallocation matrix for parameters and the likelihood function, such that all estimated parameters and the associated likelihoods are properly aligned.
The code I receive, after producing "P", is as follows:
Index in position 1 is invalid. Array indices must be positive integers or
logical values.
P(theta)=theta;
-- Summary.
My problem is related to defining properly the matrix for "P" and "L" such that the loop saves the associated values into a proper matrix.
Best regards.

Stephen Cobeldick on 9 Jan 2020
Edited: Stephen Cobeldick on 9 Jan 2020
The very simple solution is to loop over indices, and not over data (like you are doing):
V1 = 0.5:1:2.5; % data!
V2 = 0.5:1:2.5; % data!
V3 = 0.5:1:2.5; % data!
N1 = numel(V1);
N2 = numel(V2);
N3 = numel(V3);
L = nan(N1,N2,N3);
for k1 = 1:N1 % indices!
for k1 = 1:N1 % indices!
for k3 = 1:N3 % indices!
% 1. Initial (fictional) values.
theta = [1,2,3,4,5,6,7,8,9,10,V1(k1),V2(k2),V3(k3)];
% 2. "P" is a 1x13 array of estimated parameter values.
P = SIMANN('likelihoodfunction', theta);
% 3. The likelihood, L, is produced separately as L.
L(k1,k2,k3) = -likelihoodfunction(P);
end
end
end

Memek on 10 Jan 2020
Thanks for the response, your suggestion partially fixes the problems I'm facing. However, I'm still having two problems here:
--
1) The post-loop section of the code creates a table with indices rather than [g1,g2,g3] values. The likelihood outputs are included for all loops, but the gamma values [V1,V2,V3] associated with [N1,N2,N3] are not included.
V1 = 0.5:1:2.5;
V2 = 0.5:1:2.5;
V3 = 0.5:1:2.5;
N1 = numel(g1);
N2 = numel(g2);
N3 = numel(g3);
L = nan(N1,N2,N3);
fidx= nan(N1,N2,N3,3);
for k1=1:N1
for k2=1:N2
for k3=1:N3
theta = [1,2,3,4,5,6,7,8,9,10,V1(k1),V2(k2),V3(k3)];
L(k1,k2,k3)=-likelihoodfunction(P);
fidx(k1,k2,k3,:) = [k1,k2,k3];
end
end
end
V1 = reshape(fidx(:,:,:,1), [], 1);
V2 = reshape(fidx(:,:,:,2), [], 1);
V3 = reshape(fidx(:,:,:,3), [], 1);
L = L(:);
results = table(V1, V2, V3, L); % The results table created is (N1, N2, N3, L).
--
2) The second problem is associated with the "P" output component. To reiterate, the "P" output is a 1x13 array of estimated parameter values. I encounter the following message when trying the code below.
Unable to perform assignment because the size of the left side is 1-by-1 and the
size of the right side is 1-by-13.
The goal is to collect all estimated parameter values—for all loops—as with the "L" component.
I have tried the following code, but I seem to encounter some problems with regards to the size of "P".
P = zeros(3,13,3);
for k1=1:N1
for k2=1:N2
for k3=1:N3
...
P(k1,k2,k3) = SIMANN('likelihoodfunction', theta);
end
end
end
Thanks for the help thus far!
Stephen Cobeldick on 10 Jan 2020
"The post-loop section of the code creates a table with indices rather than [g1,g2,g3] values"
Because that is exactly what you wrote your code to do:
fidx(k1,k2,k3,:) = [k1,k2,k3]; % store k1, k2, k3 index values.
If you want to store values from V1, V2, and V3, then that is what you need to do:
fidx(k1,k2,k3,:) = [V1(k1),V2(k2),V3(k3)]; % store data values.
"The second problem is associated with the "P" output component."
You are trying to put 13 values into one element, because your LHS indexing refers to only one element of P:
P(k1,k2,k3) = ... 1x13 array
%^^^^^^^^^ but this refers to just ONE element!
That will not work: one element of a numeric array contains one value, that is all. If you want to all put 13 values into an array then you will need to use indexing that refers to 13 elements of that array. For example:
P = nan(N1,N2,N3,13);
for k1 = 1:N1
for k2 = 1:N2
for k3 = 1:N3
...
P(k1,k2,k3,:) = SIMANN('likelihoodfunction', theta);
end
end
end
For consistency I made the first three dimensions those corresponding to V1, V2, and V3: MATLAB will automatically change the 1x13 array into a 1x1x1x13 array to fit into the location that the indexing refers to. If you really MUST keep the 1x13 orientation then do this:
P = nan(N1,13,N2,N3);
...
P(k1,:,k2,k3) = SIMANN('likelihoodfunction', theta);
Memek on 10 Jan 2020
These extensions work perfectly! I should have asked these questions three days ago, thank you. Maybe one day I'll get a hang of these (seemingly) minor nuisances.

KALYAN ACHARJYA on 9 Jan 2020
Edited: KALYAN ACHARJYA on 9 Jan 2020
Please note that you are using invalid indexing, In MATLAB allows only positive real numbers for indexing
for loop g1=0.5:1:2.5
for g2=0.5:1:2.5
for g3=0.5:1:2.5
fidx(g1,g2,g3)=
end
end
Here fidx(0.5.0...) are not allowed
fidx(indexing Values must be real position number only)
fidx(0.5)>> Wrong
fidx(-2)>> Wrong
fidx(0)>> Wrong
fidx(2)>> Correct way ..
More Example
fidx(g1,g2,g3)=...... Here g1,g2,g3 must be position interger like, 1,2,3,4 only (Not 0, or 0.4,or -4)
Hope it helps to get the error sort out, please try you can.