MATLAB: how to apply function componentwise - matlab

Say I have a function calculateStuff(x) that takes in a scalar as parameter and returns a scalar.
Say I have a vector X and I want to apply calculateStuff on every component in X, and get a vector of the results in return and store it in a new vector Y.
Clearly Y=calculateStuff(X) is illegal, is there a way I can do this besides looping?

You have three options:
modify calculateStuff so that it can take arrays and return arrays
write a loop
use arrayfun to hide the loop: Y = arrayfun(#calculateStuff,X)

Most Matlab operations will let you input a matrix and return a matrix. You should be able to re-write calculateStuff() to take a matrix and return a matrix. That is generally MUCH faster than using a for loop. Loops in Matlab are very expensive time-wise.
The sorts of things you need to look at are "dot" versions of normal operations. For example instead of
y = z * x;
do
y = z .* x;
The first will do a matrix multiplication, which is probably not what you want when vectorizing code. The second does an element-by-element multiplication of z and x.
See here and search for "The dot operations".

Related

Matlab 3D matrix multiplication

In Matlab, I have two m-by-n matrices X and Y, with n>m.
I need to define a 3D m-by-m-by-n matrix Z whose components can be computed as
for i=2:m
for j=i+1:m
for k=1:n
Z(i,j,k) = (Y(j-1,k)-Y(i-1,k))*X(j-1,k);
end
end
end
As these nested loops require a long computational time, I have been looking for a way to define the matrix Z using matrices multiplication, but I have not managed so far. Any suggestion?
You can simply remove the inner loop (over k) by writing
Z(i,j,:) = (Y(j-1,:)-Y(i-1,:)).*X(j-1,:);
Note the .* element-wise multiplication. You can then proceed to remove additional loops in a similar manner.
But note that, most likely, your loop is slow because you don't preallocate the output array. Do this before the loop:
Z = zeros(m,m,n);
You can also gain a bit of speed by reversing the loop order, such that the first index is iterated over in the innermost loop, and the last index is iterated over in the outermost loop. This accesses the matrix data in memory order, making your cache more efficient.

Matlab function won't plot

Trying to plot a function on matlab, however the graph comes out completely empty
X = linspace(-2,2);
Y = (10*exp(X./10) - 7)/(exp(X.*(33/10)));
plot(X,Y);
You need to use element-wise operation for division:
Y = (10*exp(X./10) - 7)./(exp(X.*(33/10)));
Plotting will work fine then. The problem now is that Y is a one-element array.
I want to add here that, the only operation that should be element-wise operation is the division in the middle. The other operations don't need the '.' as the division of array by scalar as no other meaning. So, it should better be written like this:
Y = (10*exp(X/10) - 7)./(exp(X*(33/10)));
Just a few points to add on to #hesham_EE's excellent answer:
For beginners, it's best to only use * when you are doing matrix multiplication. For arithmetic and/or element-wise operations, stick with .*
It is helpful in debugging to print the output of each row of computation, i.e. omit the semicolon. This allows you to check your syntax. In this case, you would have noticed that Y was not what you had intended it to be.

MATLAB: Efficient (vectorized) way to apply function on two matrices?

I have two matrices X and Y, both of order mxn. I want to create a new matrix O of order mxm such that each i,j th entry in this new matrix is computed by applying a function to ith and jth row of X and Y respectively. In my case m = 10000 and n = 500. I tried using a loop but it takes forever. Is there an efficient way to do it?
I am targeting two functions dot product -- dot(row_i, row_j) and exp(-1*norm(row_i-row_j)). But I was wondering if there is a general way so that I can plugin any function.
Solution #1
For the first case, it looks like you can simply use matrix multiplication after transposing Y -
X*Y'
If you are dealing with complex numbers -
conj(X*ctranspose(Y))
Solution #2
For the second case, you need to do a little more work. You need to use bsxfun with permute to re-arrange dimensions and employ the raw form of norm calculations and finally squeeze to get a 2D array output -
squeeze(exp(-1*sqrt(sum(bsxfun(#minus,X,permute(Y,[3 2 1])).^2,2)))
If you would like to avoid squeeze, you can use two permute's -
exp(-1*sqrt(sum(bsxfun(#minus,permute(X,[1 3 2]),permute(Y,[3 1 2])).^2,3)))
I would also advise you to look into this problem - Efficiently compute pairwise squared Euclidean distance in Matlab.
In conclusion, there isn't a common most efficient way that could be employed for every function to ith and jth row of X. If you are still hell bent on that, you can use anonymous function handles with bsxfun, but I am afraid it won't be the most efficient technique.
For the second part, you could also use pdist2:
result = exp(-pdist2(X,Y));

Matlab vectorization of cartesian product

Let's say I have two arrays X and Y and I need a matrix M(i, j) = some_func(X(i), Y(j)). How can I get that without using loops?
The best answer is to use bsxfun, IF it is an option. According to the help for bsxfun, it will work on any general dyadic function, as long as:
FUNC can also be a handle to any binary element-wise function not listed
above. A binary element-wise function in the form of C = FUNC(A,B)
accepts arrays A and B of arbitrary but equal size and returns output
of the same size. Each element in the output array C is the result
of an operation on the corresponding elements of A and B only. FUNC must
also support scalar expansion, such that if A or B is a scalar, C is the
result of applying the scalar to every element in the other input array.
If your function accepts only scalar input, then loops are the simple alternative.
It's difficult to answer your vague question, and it ultimately depends on your function. What you can do is use meshgrid and then perform your operation, typically with use of the dot operator
e.g.
x = 1:5;
y = 1:3;
[X,Y] = meshgrid (x,y)
M = X.^Y;

closed loop optimization in MATLAB

I would like to vectorize the following loop:
for I=1:N
x = f(x);
end
with f being a custom function, i.e. an anonymous function.
Is there a command like arrayfun that allows this?
edit: May be vectorization is the wrong word here, and rather optimization should be used.
I don't check the code, but maybe:
x = arrayfun(#(y) f(x), 1:N);
With arrayfun you can take each element of the vector you passed as parameter. In the example above, y refers to each element of the vector 1:N, which also represents the index of the for loop you posted as example. In your for loop you do not use the index so you can do the same in the arrayfun and iterate over a vector doing what you want inside: f(x). Finally you can assign the output to x. Possibly, with the arrayfun way you retrieve an output x of length N with the result of each f(x) in the iterations. With the for loop you overwrite in each iteration the value of x.
Hope you help and sorry for my english.