how to split a matrix by given criteria - arrays

I have a matrix
j=randn(3,17)
M=[1;10;6]
I want to split the j matrix by its first row and the consecutive 10 rows, and then the rest 6. As a result, I want to have three different matrices.
Assume I don't see the size of M, nor its content. In that sense, how can I automate splitting the j matrix according to the unknown size and content of M? I would like to avoid using nested for loops.

You may want to use mat2cell for splitting a matrix.
In your case,
J = randn(3,17)
M = [1;10;6]
C = mat2cell(J, size(J,1), M)
where C{1} to C{3} are your matrices.
By the way it's not a good practice to call a matrix j as it is already defined by matlab.

Related

How to Determine N of an M x N CSR Sparse Matrix

I have the CSR sparse matrix arrays representing an M x N matrix:
data
indoor
indices
My question is how do I determine the original dimension N. I understand that indptr has a M + 1 entries, so M is easily determined. But I can't see how to determine N, unless the matrix is square (M = N).
Any assistance would be much appreciated.
Kind regards
John
This heavily depends on the implementation of CRS/CCS. As you have noticed, it is only possible to directly extract the number of rows M when using CRS (or the number of columns N when using CCS) if the matrix has M * N entries. I'll try to answer this using the Eigen SparseMatrix implementation in C++ as you didn't specify for which language.
To initialize a sparse matrix with Eigen, you must first define a container of triplets (which contain information of the value, row and index of a coefficient):
std::vector<Eigen::Triplet<double>> coefficients;
buildProblem(coefficients); //fills the vector according to problem
Then you must declare the sparse matrix for which must include the dimension of the matrix:
Eigen::SparseMatrix<double> A(m,n);
A.setFromTriplets(coefficients.begin(), coefficients.end());
To retrieve the dimension, you can use these methods:
A.rows();
A.cols();
A.size(); // returns rows*cols
A.innerSize(); // returns minor dimension with respect to the storage order, i.e., the number of rows for a column-major matrix
A.outerSize(); // returns major dimension with respect to the storage order, i.e., the number of columns for a column-major matrix
A.nonZeros();

Efficiently transforming NxJ matrix into an N-long array with J numbers

I'm doing some Bayesian analysis using Stan and I'm trying to make my code more efficient.
In my Stan model string, I have a variable that is an NxJ matrix. It is declared this way to make use of quick matrix operations and assignments.
However, in the final modeling step (assigning a distribution), I need to transform this NxJ matrix into an N-long array that contains J real values in each of the array's elements.
In other words, I want the following transformation:
matrix[N,J] x;
vector[J] y[N];
for (i in 1:N)
for (j in 1:J)
y[i][j] = x[i,j]
Is there any way to do this in a vectorized way without for loops?
Thank you!!!!
No. Loops are very fast in Stan. The only reason to vectorize for speed is if there are derivatives involved. You could shorten it a bit to
for (n in 1:N)
y[n] = x[n]';
but it wouldn't be any more efficient.
I should qualify this by saying that there is one inefficiency here, which is lack of memory locality. If the matrices are large, they'll be slow to traverse by row because internally they are stored column-major.

Vectorizing access to a slice of a three-dimensional matrix in MATLAB

I have a three-dimensional matrix of these sizes, approximately
A = rand(20, 1000, 20);
where the first and third dimensions are always the same length. I want to zero the elements in a main diagonal slice. This does what I mean
for ii = 1:size(A, 1)
A(ii, :, ii) = 0;
end
Is there a vectorized or otherwise faster way to do this? This code runs about 100,000 times, with these approximate sizes, but not the exact same sizes each time.
You can use logical indexing for multible tailing dimensions while using subscript indexing for all previous dimensions individually. This way you can easily do the operation on an 1000 20 20 matrix. To apply this to your matrix, permute is required which might be slow:
n=size(A,3)
A=permute(A,[2,1,3]);
A(:,diag(true(n,1)))=0;
A=permute(A,[2,1,3]);
If it would be possible to permanently swap the dimensions of A in your code and avoid the permute, this would lead to the fastest solution.
Alternatively you can use repmat to expand the index to the dimensions of A
ix=repmat(reshape(diag(true(n,1)),n,1,n),[1,size(A,2),1])
A(ix)=0
For matrices of the same size you could keep ix. Not having access to MATLAB right now, I don't know which solution is faster.
You can use bsxfun to build a linear index of the elements to be zeroed:
ind = bsxfun(#plus, (0:size(A,2)-1).'*size(A,1), 1:size(A,1)*size(A,2)+1:numel(A) );
A(ind) = 0;

Matlab: creating 3D arrays as a function of 2D arrays

I want to create 3d arrays that are functions of 2d arrays and apply matrix operations on each of the 2D arrays. Right now I am using for loop to create a series of 2d arrays, as in the code below:
for i=1:50
F = [1 0 0; 0 i/10 0; 0 0 1];
B=F*F';
end
Is there a way to do this without the for loop? I tried things such as:
F(2,2) = 0:0.1:5;
and:
f=1:0.1:5;
F=[1 0 0; 0 f 0; 0 0 1];
to create them without the loop, but both give errors of dimension inconsistency.
I also want to perform matrix operations on F in my code, such as
B=F*F';
and want to plot certain components of F as a function of something else. Is it possible to completely eliminate the for loop in such a case?
If I understand what you want correctly, you want 50 2D matrices stacked into a 3D matrix where the middle entry varies from 1/10 to 50/10 = 5 in steps of 1/10. You almost have it correct. What you would need to do is first create a 3D matrix stack, then assign a 3D vector to the middle entry.
Something like this would do:
N = 50;
F = repmat(eye(3,3), [1 1 N]);
F(2,2,:) = (1:N)/10; %// This is 1/10 to 5 in steps of 1/10... or 0.1:0.1:5
First pre-allocate a matrix F that is the identity matrix for all slices, then replace the middle row and middle column of each slice with i/10 for i = 1, 2, ..., 50.
Therefore, to get the ith slice, simply do:
out = F(:,:,i);
Minor Note
I noticed that what you want to do in the end is a matrix multiplication of the 3D matrices. That operation is not defined in MATLAB nor anywhere in a linear algebra context. If you want to multiply each 2D slice independently, you'd be better off using a for loop. Doing this vectorized with native operations isn't supported in this context.
To do it in a loop, you'd do something like this for each slice:
B = zeros(size(F));
for ii = 1 : size(B,3)
B(:,:,ii) = F(:,:,ii)*F(:,:,ii).';
end
... however, examining the properties of your matrix, the only thing that varies is the middle entry. If you perform a matrix multiplication, all of the entries per slice are going to be the same... except for the middle, where the entry is simply itself squared. It doesn't matter if you multiple one slice by the transpose of the other. The transpose of the identity is still the identity.
If your matrices are going to be like this, you can just perform an element-wise multiplication with itself:
B = F.*F;
This will not work if F is anything else but what you have above.
Creating the matrix would be easy:
N = 50;
S = cell(1,N);
S(:) = {eye(3,3)};
F = cat(3, S{:});
F(2,2,:) = (1:N)/10;
Another (faster) way would be:
N = 50;
F = zeros(3,3,N);
F(1,1,:) = 1;
F(2,2,:) = (1:N)/10;
F(3,3,:) = 1;
You then can get the 3rd matrix (for example) by:
F(:,:,3)

Extracting a block out of a multidimensional matrix

Consider the multi-dimensional matrix A where size(A) has the identical even elements N. How should one find the matrix B with size(B)=size(A)/2 such that:
B(1,1,...,1)=A(1,1,...,1),
B(1,1,...,2)=A(1,1,...,2),
...
B(N/2,N/2,...,N/2)=A(N/2,N/2,...,N/2).
I generally don't like arrayfun (or loopy functions), but if the number of dimensions is not in the thousands, then this should be just fine:
Nv = size(A)/2;
S = arrayfun(#(x){1:x},Nv);
B = A(S{:});
Should work with different sized dimensions too. Just decide how you want to deal with dimensions where mod(size(A),2)~=0.

Resources