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,:,:))
Related
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));
I have to create a very big 3D matrix (such as: 500000x60x60). Is there any way to do this in matlab?
When I try
omega = zeros(500000,60,60,'single');
I get an out-of-memory error.
The sparse function is no option since it is only meant for 2D matrices. So is there any alternative to that for higher dimensional matrices?
Matlab only has support for sparse matrices (2D). For 3D tensors/arrays, you'll have to use a workaround. I can think of two:
linear indexing
cell arrays
Linear indexing
You can create a sparse vector like so:
A = spalloc(500000*60*60, 1, 100);
where the last entry (100) refers to the amount of non-zeros eventually to be assigned to A. If you know this amount beforehand it makes memory usage for A more efficient. If you don't know it beforehand just use some number close to it, it'll still work, but A can consume more memory in the end than it strictly needs to.
Then you can refer to elements as if it is a 3D array like so:
A(sub2ind(size(A), i,j,k))
where i, j and k are the indices to the 1st, 2nd and 3rd dimension, respectively.
Cell arrays
Create each 2D page in the 3D tensor/array as a cell array:
a = cellfun(#(x) spalloc(500000, 60, 100), cell(60,1), 'UniformOutput', false);
The same story goes for this last entry into spalloc. Then concatenate in 3D like so:
A = cat(3, a{:});
then you can refer to individual elements like so:
A{i,j,k}
where i, j and k are the indices to the 1st, 2nd and 3rd dimension, respectively.
Since your matrix is sparse, try to use ndsparse (N-dimensional sparse arrays FEX)
reshape function should change the shape of a matrix.
But if I try using it (it's also written in the manual) I discover that if I declare:
reshape(A,m,n);
Then A must have m lines and n columns.
If I try using reshape passing as arguments numbers different from these, I get an error.
So appearently, it does not reshape any matrix, it just does return the same matrix if I pass m and n as arguments, and return an error otherwise.
So if I have a 4x4 matrix and I want to make it smaller: 2x2, I can't.
It changes the shape, not the size of the array. To change the shape the number of elements must not change. So if you have 4x4 you can go to 8x2 or 2x8 or 16x1 etc. but not 2x2 (what do you expect to happen to the other elements?)
Reshape rearranges elements; if you do B = reshape(A, u) then logically B must have the same number of elements (note that size(B) == prod(u)) as A (length(B(:)) == length(A(:))). Otherwise, how would it know which elements to drop if A had more, or where would it get new ones if B had more?
One situation in which reshape is useful is when for some reason your square matrix was unrolled into a vector (perhaps by another function) and you simply need to arrange it back to its previous form.
When you want to get a smaller part of a matrix, use A(i1:i2, j1:j2). When you want to "tile" a matrix, use repmat(A, i, j).
As #thrope says, reshape changes the shape, not the number of elements. If you have a 4x4 matrix and you want the upper left 2x2 corner of it, use B=A(1:2,1:2) or the bottom right 2x2 corner, B=A(3:4,3:4).
I am doing my dissertation now. I stuck with a integral. My function is defined as
myfun =(exp(t*Q)*V*x)(j);
where Q and V are a matrix (n*n), x is a vector which elements are 1, then after calculation we get the j_th element of that vector then I need to integrate the function against t.
I want to use the quad in the matlab. However the point is that it will report the inner matrix is not the same size. Since A here is not a number ?....
How can I do this. Otherwise I could only write a loop against t itself, which is extremely slow.
Thanks
You can use SUBSREF for this (you still neet to loop over all j's, though):
myfunOfT = #(t)(subsref(exp(t*Q)*V*x,struct('type','()','subs',j);
This returns the value of the jth element of the array at time t.
Why create a matrix of 0's in Matlab? For example,
A=zeros(5,5);
for i = 1:5
A(i)=exp(i);
end
Following on from j_random_hacker's answer, it's much more efficient in MATLAB to pre-allocate an array rather than letting MATLAB expand it. MATLAB can expand arrays if you simply assign elements off the current "end" of the array, like so:
x = []
for ii=1:1e4
x(ii) = 1/ii;
end
That's really inefficient because at each step in the loop, MATLAB will re-allocate "x" to be one element larger than it was previously. The following is much faster:
x = zeros( 1, 1e4 );
for ii=1:1e4
x(ii) = 1/ii;
end
(Probably fastest still in this case is: x = 1./(1:1e4);, but the pre-allocation route is what you need when you can't resolve things to a vectorised operation)
This is identical to asking: Why create a variable with value 0?
Usually you would do this if you plan to accumulate a bunch of results together somehow. In this case, you have to start "somewhere".
Although it is possible to start out with an empty matrix and expand it by concatenating (adding) new elements, vector extension is highly inefficient in MATLAB because it requires new memory every time another element is concatenated. Preallocation establishes a matrix that's the right size in advance, then each zero element can be replaced with the correct value. This method is much more efficient, especially in programs involving looping.
This is helpful if you are going to work on large matrix. Or if you are going to work with sparse matrix. This is also helpful when you are using the same vector or matrix again and again.