Multidimensional lookup table using griddedInterpolant

15 views (last 30 days)
Hi, I have a function that computes an output value and I want to create a lookup table with interpolation (and I've found griddedInterpolant can do that) of these computed values, varying the parameters passed to the function. I'd like to be able to specify a number of vectors that contain varying parameters, maybe just 1 vector of varying parameters or maybe many - I want to able to change it fairly easily. In the example below I am varying 3 parameters, so the resultant look up table will be a 3D array. I am using allcomb from the file exchange to generate all the different combinations of input parameters, looping over them and performing a calculation with the values from each row. I want the griddedInterpolant to be able to give me the result corresponding to the configuration but for testing I am just storing the current iteration number 'ndx' in the array. I would like to be able to extract the result from any configuration by doing u_LUT(x,y,z).
From the code below I WANT:
u_LUT(-2,-1,-4) returns 1
u_LUT(-2,-1,-3.5) returns 2
u_LUT(-2,-1,-3) returns 3
...
u_LUT(-2,-1,4) returns 17
u_LUT(-2,-0.75,-4) returns 18
u_LUT(-2,-0.75,-3.5) returns 19
and so on, such that the result produced by the interpolant is for the correct configuration passed in as u_LUT(x,y,z).
But I cannot set up the griddedInterpolant to produce this behaviour. I feel I have to manipulate 'u' in some way to get it from the matlab linear indexing arrangement into the arrangement I need for the griddedInterpolant. Thanks in advance for any help.
clear
clc
% vectors of input paramters
% a calculation will be performed with every combination of these
x = -2:0.1:2;
y = -1:0.25:1;
z = -4:0.5:4;
inputs = {x, y, z};
% generate all combinations of inputs
input_configurations = allcomb(inputs{:});
num_configurations = size(input_configurations,1);
num_inputs = length(inputs);
sizes_of_inputs = ones(1, num_inputs);
for index = 1:num_inputs
sizes_of_inputs(index) = size(inputs{index},2);
end
% u stores the result of the calculation using x, y & z
u = ones(sizes_of_inputs);
for ndx = 1:num_configurations
% calculation performed here with x,y,z from
% input_configurations(ndx,:) - result stored in u
% u(ndx) = calculationCall(x,y,z)
u(ndx) = ndx;
end
u_LUT = griddedInterpolant(inputs, u, 'spline');

Accepted Answer

Nathan Van der Hoek
Nathan Van der Hoek on 3 Sep 2021
Edited: Nathan Van der Hoek on 5 Sep 2021
Edit: I discovered allcomb has the option to vary the parameters beginning with the left-most one rather than the right-most one if you pass it the option 'matlab'. This means when the result array ('u' above) is indexed via linear indexing, the results are going into the correct place.
I managed to reshape the data I originally had with:
u_rearranged = permute(reshape(u, flip(sizes_of_inputs)), num_inputs:-1:1);
But this is no longer necessary for me.

More Answers (1)

Bjorn Gustavsson
Bjorn Gustavsson on 3 Sep 2021
If you calculate all the combinations of points you dont need to go over the allcomb way, you could just as well run ndgrid at once. Then your code-snippet would become something like:
% vectors of input paramters
% a calculation will be performed with every combination of these
x = -2:0.1:2;
y = -1:0.25:1;
z = -4:0.5:4;
[X,Y,Z] = ndgrid(x,y,z);
% u stores the result of the calculation using x, y & z
u = ones(size(X));
for i1 = sizer(X,1):-1:1 % looping from the end makes it possible to dodge pre-allocation
for i2 = size(X,2):-1:1 % which is sometimes convenient, but not always possible
for i3 = size(X,3):-1:1
% calculation performed here with x,y,z from
% X(i1,i2,i3), Y(i1,i2,i3), Z(i1,i2,i3) - result stored in u
% u(i1,i2,i3) = calculationCall(x,y,z)
u(i1,i2,i3) = ndx;
end
end
end
u_LUT = griddedInterpolant(X,Y,Z, u, 'spline');
HTH
  2 Comments
Nathan Van der Hoek
Nathan Van der Hoek on 3 Sep 2021
I want my code to work for an arbitrary number of inputs. The way you've written it, if I want 3 more vectors to the ndgrid, I would need to create 3 more nested for loops. I am trying to avoid that.
Bjorn Gustavsson
Bjorn Gustavsson on 3 Sep 2021
Then use linear indexing:
for i1 = size(X(:),1):-1:1
U(i1) = sin(X(i1)+Y(i1)+Z(i1));
end
u_LUT = griddedInterpolant(X,Y,Z, reshape(U,size(X)), 'spline');

Sign in to comment.

Categories

Find more on Interpolation in Help Center and File Exchange

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!