Eliminate terrible for loop, code optimisation, data attached

1 view (last 30 days)
The problem:
I have 3 (very large) grids of data.... x y z, where x and y are variables that determine 'performance' z.
There are multiple sets of x y z..... so, x1 y1 z1, x2 y2 z2, x3 y3 z3....
y values are set by the user.... The x value combinations are calculated from other code. They are all possible combinations that can make a user-specified total (xtotal)
My goal is to find z values for known x and y... and repeat for different sets of x values. Added a picture to illustrate what I'm aiming to do - get the values from the red elements:
I have managed to create a for loop that achieves this - however it is SLOW. I am sure there is a more efficient way to do this using grids but have struggled.
Working code and data is attached, the time-consuming (10+ seconds!) loop in there is:
Outputs=zeros(size(xvals),length(xvals))
for i=1:size(indz)
x1loc=find(x1(1,:)==xvals(i,1))
Outputs(i,1)=z1(y1loc,x1loc)
x2loc=find(x2(1,:)==xvals(i,2))
Outputs(i,2)=z2(y2loc,x2loc)
x3loc=find(x3(1,:)==xvals(i,3))
Outputs(i,3)=z3(y3loc,x3loc)
end
Fairly sure there will be some way to optimise this using grids, or some other matlab trick I'm less familiar with... Stuck!

Answers (2)

Matt J
Matt J on 10 Dec 2014
Edited: Matt J on 10 Dec 2014
No need to loop at all (nor to use the FIND command). Just do
x1loc = ( x1(1,:)==xvals(:,1).' );
Outputs(:,1)=z1(y1loc,x1loc);
and similarly with x2loc and x3loc.
  1 Comment
Mat
Mat on 10 Dec 2014
I was about to say wow, this must surely be the most extreme example of overcomplicating things! However this doesn't work...
>> x1loc = ( x1(1,:)==xvals(:,1).' );
??? Error using ==> eq
Matrix dimensions must agree.
x1 is vector of 25 different values. xvals often has around 150 values, many repeat values because, for example, if x1=100 and xtotal=200, then x2 and x2 can equal 20-80, 30-70, 40-60.... etc.
x1 and xvals are not likely to have matching dimensions. Don't think it can work this way...?

Sign in to comment.


Matt J
Matt J on 10 Dec 2014
Edited: Matt J on 10 Dec 2014
How about
F1=griddedInterpolant(x1,y1,z1,'nearest');
Output(:,1)=F1({xvals,y1loc});
It might also be worth conserving memory by making x1,y1 into grid vectors instead of a Full Grid, as explained in the documentation for griddedInterpolant .
  2 Comments
Mat
Mat on 10 Dec 2014
I had a quick try and this doesn't work either (Undefined function or method 'griddedInterpolant' for input arguments of type 'double'.)
Haven't fiddled around with it because I'd like to avoid functions not supported by matlab coder (e.g griddedInterpolant).
In the script, I modify the inputs so that they fit the nearest value that already exist on the existing grid, so not sure how interpolation would help here.
Matt J
Matt J on 10 Dec 2014
Edited: Matt J on 10 Dec 2014
I had a quick try and this doesn't work either (Undefined function or method 'griddedInterpolant' for input arguments of type 'double'.)
You seem to have a pretty old version of MATLAB. You could use interp2 instead. It is supported by the Matlab Coder.
In the script, I modify the inputs so that they fit the nearest value that already exist on the existing grid, so not sure how interpolation would help here.
That's the same as nearest-neighbor interpolation.

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!