inverse multiple 3x3 matrices in a big matrix in matlab - matlab

I have a big matrix, 3x3x151.
I was struggling to write a code to find the inverse of each 3x3 matrix and save it in a new matrix.
tried a for loop approach but got no where

This is precisely what pageinv was designed for. If you have R2022a or later, simply:
x = rand(3, 3, 151);
y = pageinv(x);
As the comments above point out, and as is fairly well known, the matrix inverse itself often isn't what you want. There's also pagemldivide if that's what you really want to do.

a quick solution is to split the matrix into cell arrays of 3x3 matrices, and then call cellfun, try this
a=rand(3,3,151);
b=squeeze(num2cell(a,[1,2]));
c=cellfun(#inv, b, 'UniformOutput', false) % inversions of 3x3 matrices
if you want to assemble those back to a matrix, you can call
cmat=reshape(cell2mat(cellfun(#(x) x(:), c', 'UniformOutput', false)), size(a))

Related

Multiplying a 3D Matrix with a 1D

I attempted to use the solution from this post: Multiply a 3D matrix with a 2D matrix, to vectorize the multiplication of a one dimensional with a three dimensional, but to no avail. Any help would be greatly appreciated!
for s = 1: s_length
for a = 1: a_length
for g = g_length
two_dim(s,a) = two_dim(s,a) + one_dim(g) * three_dim(s,a,g);
end
end
end
I think this does what you want.
two_dim = reshape(three_dim, [], size(three_dim,3))*one_dim(:);
two_dim = reshape(two_dim, size(three_dim,1), size(three_dim,2));
This works as follows:
First line reshapes your 3D array into a matrix, collapsing the first two dimensions into one. That way the operation you want is standard multiplication of the resulting matrix times a column vector.
Second line reshapes the result into matrix shape.
mtimes does not work with inputs with dimension larger than 2, so you have to find a way to do the multiplication by yourself. The solution of Luis Mendo is a nice solution; here is another one using bsxfun:
two_dim = two_dim + squeeze(sum(bsxfun(#times, three_dim, reshape(one_dim,[1 1 g_length])),3));
Here is how it works:
reshape makes the vector one_dim looking like a 3D array. This must be done because the multiplication between the vector and the 3D array is performed along the 3rd dimension, so Matlab need a hint on sizes.
bsxfun perfoms the element-wise multiplcation, so the result must be sumed up along the 3rd dimension (and squeezed to be compliant with a 2D matrix format)

Matlab - Create N sparse matrices and sum them

I have N kx1 sparse vectors and I need to multiply each of them by their transpose, creating N square matrices, which I then have to sum over. The desired output is a k by k matrix. I have tried doing this in a loop and using arrayfun, but both solutions are too slow. Perhaps one of you can come up with something faster. Below are specific details about the best solution I've come up with.
mdev_big is k by N sparse matrix, containing each of the N vectors.
fun_sigma_i = #(i) mdev_big(:,i)*mdev_big(:,i)';
sigma_i = arrayfun(fun_sigma_i,1:N,'UniformOutput',false);
sigma = sum(reshape(full([sigma_i{:}]),k,k,N),3);
The slow part of this process is making sigma_i full, but I cannot reshape it into a 3d array otherwise. I've also tried cat instead of reshape (slower), ndSparse instead of full (way slower), and making fun_sigma_i return a full matrix rather than a sparse one (slower).
Thanks for the help! ,

how to create a 3d sparse like matrix in octave

my Problem is difficult or too simple. So I've been using sparse to creat a matrix from different vectors (example here)
I use sparse(i,j,s,m,n) where i and j are allocations for particles i derived with floor etc.
(it is particle in cell simulation).
this is for 1D. I want to vectorize this problem for 2D and got the problem that i can't creat 3D sparse matrices in octave.
I'm really no pro with octave and i'm searching for a solution that i can put the values from s nicely into a matrix according to the i and j values.
for example: i got particle one in cell x=2 and y=2 than i want to have a matrix with value from particle one in (1,2,2,value). is there a way without much if's and for's?
At the moment is not possible to have N-dimensional sparse matrices in Octave. You can see this with the following example which tries to reshape a 3x9 sparse matrix into 3x3x3:
octave> sp = sparse (2, 6, 1, 3, 9)
sp =
Compressed Column Sparse (rows = 3, cols = 9, nnz = 1 [3.7%])
(2, 6) -> 1
octave> reshape (sp, [3 3 3])
warning: reshape: sparse reshape to N-d array smashes dims
ans =
Compressed Column Sparse (rows = 3, cols = 9, nnz = 1 [3.7%])
(2, 6) -> 1
What you can do is to have a cell array of sparse matrices. So for a particle at KxMxN you could have data{k} = sparse (M, N, value) and access it with data{k}(m,n). It's not ideal but depending on how you get your data organized you may make things more or less readable.
Sparse NDArray is not possible in either Octave nor Matlab. However, there is a class for Matlab which implements Sparse NDArray, although the performance will probably be not optimal, it will still probably be a lot better than using a cell array since it internally represents the sparse NDArray as a simple 2D sparse matrix:
http://www.mathworks.com/matlabcentral/fileexchange/29832-n-dimensional-sparse-arrays
Since v4, Octave now supports classdef. I did not try it yet, but even if it does not work yet, it will probably soon. And anyway, you can see how it was done in the script and make a non-class, all functional version by applying the same idea (using a 2D sparse matrix that you manipulate with custom functions to do whatever operations you want in a ND space).

Create a new matrix from indices

I have huge n×n matrix A, and the indices of its non-zero elements by a = find(A). I have obtained a new list a1 by deleting some elements from a. I want to have matrix A of indices in a1 without using loops. Any suggestions? Is there any function for this purpose?
Considering that your matrix is "huge" (and your question implies that it is mostly zeroes), perhaps it would be best if you represent it as a sparse matrix:
[ii, jj] = ind2sub(size(A), a1);
spA = sparse(ii, jj, A(a1), size(A, 1), size(A, 2));
There might be a significant speedup when operating on sparse matrices. If you need to obtain the full matrice back, use full:
newA = full(spA);
Use vector indexing. Without really knowing how "huge" is your matrix A, but assuming you can still handle it in one piece in matlab's memory, just:
B(size(A,1),size(A,2))=0;
B(a1)=A(a1);
Now B is the same as A with only the indexes given by a1.

Matlab 3d-matrix

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)