0
votes

just started with matlab, and vectorization, FF to problem:

What to do:

%n,t are vectors(1D arrays) EDIT: these are column vectors.
k=9;
i=1;
kv = 0.6*k:0.2*k:1.4*k;
[zs,zb] = size(k);
error1 = zeros(zs,1);
for k2 = kv
error1(i,1) = error_km(n,t,kv(i));
i= i+1;
end

where error_km is : (n and t are of same size)

function [ returnV] = error_km( n,t,k )
returnV = 0
    [a,b] = size(n);
    Nt = zeros();
    for i=2:a
        Nt(i,1) = (n(i-1,1)^-1 + k*(t(i,1)-t(i-1,1)))^-1;
        error1 = Nt(i,1) - n(i,1);
        returnV = returnV + error1*error1;
    end

The whole program takes about 3 to 4 minutes, for small test cases, i was able to make and understand simple vectorized alternatives for loops, but i am not able to make sense to vectorize this loop,

Any guidance?

UPDATE : in error_km, now i am using:

Nt = (n(1:a-1,1).^-1 + (diff(t(:,1))).*k).^-1 - n(2:a,1);
Nt = Nt.^2;
returnV = sum(Nt);

works good, but still in the main program i am forced to use a loop for iterating over kv, if i use kv(:) it passes the vector to function not a single value each time. used this in main : error1 = error_km(n,t,kv.*1);

is it possible to get rid of main loop also?

EDIT2, Soln :

To get rid of main loop just use arrayfun

2
What are the sizes of k, n and t initially? What is this code trying to do? - Squazic
^see if the edit provides more info, the code basically calculates error in observed and calculated value, n(observed value) and t(time) are 1D arrays read from file, both of same size - TarunG
EDIT: added more code, to make it clear - TarunG
Since the function error_km does not use Nt you could get away with not storing all values of Nt generated use Nt=... instead of Nt(i,1). Or preallocate Nt by changing Nt=zeros(); to Nt=zeros(a,1)`. I don't have an answer about vectorizing the code at this time. - Azim J
thanks for your suggestion, but Its just a code snippet, not the whole code ;) - TarunG

2 Answers

1
votes

In error_km you don't preallocate Nt. This step is important. You can learn more about why in this Matlab helpfile.

If you know the size of Nt you can set it in the call to zeros(). Otherwise you could restructure the loop:

function [ returnV] = error_km( n,t,k )
returnV = 0
    [a,b] = size(n);
    Nt = zeros();
    for i=a:-1:2
        Nt(i,1) = (n(i-1,1)^-1 + k*(t(i,1)-t(i-1,1)))^-1;
        error1 = Nt(i,1) - n(i,1);
        returnV = returnV + error1*error1;
    end
1
votes

Here are some parts of the answer you seek, I trust that you can figure the rest out. You can replace the expression:

t(i,1)-t(i-1,1)

with the (vectorised) expression

diff(t(:,1))

You can then replace your loop over i with the expressions:

Nt(a:-1:2,1) = (n(a-1:-1:1),1)^-1 + k*(diff(t(:,1))))^-1;
returnV = dot(Nt(:,1)-n(:,1),Nt(:,1)-n(:,1));

If I've read your code correctly and matched brackets properly that might be vectorised enough for your taste.

And as you've already been advised, you should preallocate Nt, in this case I would write:

Nt = zeros(size(n))