How do you compose functions in matlab? - matlab

I would like to chain these two functions:
1. select the third dimension of a m x n x 3 matrix
2. flatten the matrix into a (m+n) x 1 vector
Something like: mat(:,:,1)(:) or (mat(:,:,1))(:)
But this is not the correct syntax.So how do I chain these two functions together without assigning some variable to the intermediate result mat(:,:,1) ?

You can't chain those two indexings in Matlab. But in this case you can substitute the second indexing by a reshape:
reshape(mat(:,:,1),[],1)
If the second indexing is more complicated than just flattening the matrix, the reshape trick will not be applicable in general. In that case there is a way to avoid using an intermediate variable, but it results in cumbersome and ugly code, so it's not recommended.

Related

MATLAB: element-wise multiplication of two matrices over one index?

I'm trying to figure out if there's a native way of obtaining a certain kind of element-wise product of two matrices in Matlab.
The product that I'm looking for takes two matrices, A and B say, and returns there product C, whose elements are given by
C(i,j,k) = A(i,j)*B(j,k)
Naturally, the number of columns of A is assumed be the same as the number of rows of B.
Right now, I'm using the following for-loop (assuming size(A,2)==size(B,1) is true). First, I initialize C:
C = zeros(size(A,1), size(A,2), size(B,2));
And then I perform element-wise multiplication via:
for i=1:size(A,2)
C(:,i,:) = A(:,i)*B(i,:);
end
So, my question is: Is there a native way to this sort of thing in Matlab?
You need to "shift" the first two dimensions of B into second and third dimensions respectively with permute and then use bsxfun with #times option to operate on A and the shifted dimension version of B -
C = bsxfun(#times,A,permute(B,[3 1 2]))

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));

automatic transpose of vectors for binary operations

I know there are alternatives exist. But just curious to know. When I perform some binary operations such as *,-,/,+ between two vectors of same size, some times the dimension does not match. For eg., for a*b a is of size (m,1) and b is also of size (m,1). or for a-b, the size of a,b is (m,1) and (1,m) respectively. Is there a way that matlab automatically matches dimension of vectors and performs the operation.
A simple approach is to use
a(:)-b(:)
instead of a-b. The linear indexing (:) turns everything into a column vector.
If one of the operands is in turn the result of an operation, for example b+c, you can't directly write a(:)-(b+c)(:) in Matlab. In that case you can use reshape, like this:
reshape(a,[],1) - reshape(b+c,[],1)
This works because reshape(...,[],1), like (:), converts its argument into a column; but now that argument can be the result of an operation.

MATLAB submatrix

MATLAB question:
I have an array A(2,2,2) that is three-dimensional. I would like to define a 2x2 array as a subarray of A, as follows:
B = A(1,:,:).
That is, we are simply projecting on the first component. But matlab will now treat this 2x2 matrix as a 1x2x2 array instead, so that I can't do certain things (like multiply by another 2x2 matrix).
How do I get B as a 2x2 subarray of A?
If you think about a skyscraper, your A(1,:,:) is taking the first floor out and this operation inevitably happens across the 3rd dimension.
You can use reshape(), squeeze() or permute() to get rid of the singleton dimension:
reshape(A(1,:,:),2,2)
squeeze(A(1,:,:))
permute(A(1,:,:),[2,3,1])
squeeze() pretty much does all the job by itself, however it is not an inbuilt function and in fact uses reshape(). The other two alternatives are expected to be faster.
You'd want to use the function squeeze which removes the singleton dimensions:
B = squeeze(A(1,:,:))

summing all elements in matlab without using colon operator

I want to sum all elements of matrix in Matlab. If I had a matrix called A, then I can sum all elements by calling
sum(A(:));
But I would like to sum elements returning from a function like this:
sum(gammaln(A)) % where gammaln is the logarithm of gamma function
Of course I can do this in two steps:
B = gammaln(A);
sum(B(:));
But here I create a B matrix, which I don't need at all. And also I can do it this way:
sum(sum(gammaln(A)))
But, the number of sum's will be equal to the dimension of my matrix. It looks ugly, and the matrix dimension may change.
I'm curious if there is any way of doing this.
use reshape instead of (:) operator:
sum(reshape(gammaln(A),[],1))