spdiags() in MATLAB into Python

坚强是说给别人听的谎言 提交于 2019-12-11 08:33:19

问题


I am trying to translate a MATLAB implementation into a Python 3 implementation. I've found a function, spdiags(), that I do not understand, and am also not sure how to translate it into Python 3.

The MATLAB documentation on the function is here: http://www.mathworks.com/help/matlab/ref/spdiags.html

The Scipy documentation on an identically named function is here: http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.spdiags.html

What does the MATLAB function do, and is there a Python implementation of the same return available?


回答1:


In Octave (MATLAB alternative), the example in its documentation:

octave:7> x = spdiags (reshape (1:12, 4, 3), [-1 0 1], 5, 4);
octave:8> full(x)  # display as a full or dense matrix
ans =    
    5   10    0    0
    1    6   11    0
    0    2    7   12
    0    0    3    8
    0    0    0    4

The actual values that are stored in x are:

x =
Compressed Column Sparse (rows = 5, cols = 4, nnz = 11 [55%])
  (1, 1) ->  5
  (2, 1) ->  1
  (1, 2) ->  10
  (2, 2) ->  6
  (3, 2) ->  2
  (2, 3) ->  11
  (3, 3) ->  7
  (4, 3) ->  3
  (3, 4) ->  12
  (4, 4) ->  8
  (5, 4) ->  4

The equivalent scipy.sparse expression:

In [294]: x = sparse.spdiags(np.arange(1,13).reshape(3,4), [-1, 0, 1], 5, 4)
In [295]: x.A   # display as normal numpy array
Out[295]: 
array([[ 5, 10,  0,  0],
       [ 1,  6, 11,  0],
       [ 0,  2,  7, 12],
       [ 0,  0,  3,  8],
       [ 0,  0,  0,  4]])

In [296]: x
Out[296]: 
<5x4 sparse matrix of type '<class 'numpy.int32'>'
    with 11 stored elements (3 diagonals) in DIAgonal format>

This use the dia format, but it easy to transfrom to csc (equivalent to the Octave format) with x.tocsc().

To see the same coordinates and values, we can use the dok format (a dictionary subclass):

In [299]: dict(x.todok())
Out[299]: 
{(0, 1): 10,
 (1, 2): 11,
 (3, 2): 3,
 (0, 0): 5,
 (3, 3): 8,
 (2, 1): 2,
 (2, 3): 12,
 (4, 3): 4,
 (2, 2): 7,
 (1, 0): 1,
 (1, 1): 6}

Same values, adjusting for the 0 based indexing.

In both cases, the diagonal values come from a matrix:

octave:10> reshape(1:12, 4, 3)
ans =
    1    5    9
    2    6   10
    3    7   11
    4    8   12

In [302]: np.arange(1,13).reshape(3,4)
Out[302]: 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

Octave/MATLAB arrange values by column, numpy by row, hence the different reshape. The numpy matrix is the transpose of the MATLAB equivalent.

Note that 9 has been omitted from both (4 items mapped on to a 3 element diagonal).

The other argument is a list of diagonals to set, [-1,0,1], and final shape (5,4).

Most of the differences in arguments have to do the basic differences between MATLAB and numpy. The other difference is that MATLAB has only one sparse matrix representation, scipy has a half dozen.




回答2:


Well, this answer can only scratch the surface, but:

For matrices, there's different storage formats. Of course, there's the most intuitive "row after row" and "column after column" formats, but there's also formats for matrices with only a few non-zero entries, which of course save a lot of memory (and might save a lot of CPU) if used correctly.

So, these diagonal sparse matrices are such a case of a specially stored matrix in matlab; If you don't care about the computational advantages, just use diag, which is functionally 100% equivalent (but doesn't generate sparse matrices).

The existence of sparse matrix storage is a Matlab feature, and scipy does in fact (I'm actually surprised by that) have that feature, too. So use the scipy method if it fits your needs!



来源:https://stackoverflow.com/questions/31900043/spdiags-in-matlab-into-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!