Create sparse matrix with zig-zag diagonal
6 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Is there a way to shift every column c by (c-1)*n rows down, where n is size(A,1) in the following example, without a loop and without excessive memory usage? So to get
A = [
a11 a12 a13 a14 ...
a21 a22 a23 a24 ...
... ... ... ... ...
]
to read
B = [
a11 0 0 0 ...
a21 0 0 0 ...
... ... ... ... ...
0 a12 0 0 ...
0 a22 0 0 ...
... ... ... ... ...
0 0 a13 0 ...
0 0 a23 0 ...
... ... ... ... ...
0 0 0 a14 ...
0 0 0 a24 ...
... ... ... ... ...
]
I tried diag and sparse with no luck so far. I need Matrix A in an operation X=J\A afterwards. It is crucial that the zero elements do not consume memory as A can have up to 20e6 columns and probably 10 rows.
Thanks in advance.
0 comentarios
Respuesta aceptada
Cedric
el 3 de Feb. de 2013
Editada: Cedric
el 3 de Feb. de 2013
You could use sparse(), building appropriate vectors of indices and values, e.g.:
nCol = size(A, 2) ;
nRow = nCol * size(A, 1) ;
I = (1:nRow).' ;
J = reshape(repmat(1:nCol, size(A, 1), 1), [], 1) ;
B = sparse(I, J, A(:), nRow, nCol) ;
(that you can write in two lines actually, but I wanted to keep it clear)
3 comentarios
Cedric
el 3 de Feb. de 2013
Editada: Cedric
el 4 de Feb. de 2013
Well, one way to use sparse() is to provide 5 args: a vector or row indices, a vector of column indices, a vector of values, the number of rows and the number of columns. Here we build these "things", using one "trick" that simplifies a bit the problem: we create the vector of values using linear indexing on A (in this case, it means lining up columns of A and reading that as a vector). Example:
>> A = [1, 2, 3; 4, 5, 6]
A =
1 2 3
4 5 6
>> A(:)
ans =
1
4
2
5
3
6
Knowing that we will pass A(:) to sparse() as a vector of values, we have to build appropriate vectors of row and column indices..
Looking at what you depicted, row indices will just increase linearly, so we build I as 1:nRow, transposed so it is a column vector (same dim. as A(:)).
For column indices, it is a little more tricky as it will be something like
1 1 1 ... 2 2 2 ... etc, with the number of each integer being the number of rows of A. We can obtain this by creating a matrix
1 2 3 4 ...
1 2 3 4 ...
. . . .
. . . .
that we ultimately index linearly. This matrix is actually the vertical repetition of (1:nCol) a number of times that matches the number of rows of A. You obtain that with repmat(). Example:
>> repmat(1:4, 3, 1)
ans =
1 2 3 4
1 2 3 4
1 2 3 4
Now I could have written
...
J = repmat(1:nCol, size(A, 1), 1)) ;
B = sparse(I, J(:), A(:), nRow, nCol) ;
and avoid the reshape, but you would have had I given as a vector, and J as a matrix indexed linearly, which I thought would have brought confusion. The reshape transforms the output of repmat() into a column vector (last arg = 1). As reshape() is flexible, it allows to specify only one size (the other is left to an empty array), and computes the other. The reshape does therefore essentially what J(:) would have done.
Más respuestas (1)
Ver también
Categorías
Más información sobre Creating and Concatenating Matrices en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!