2

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?

Galen
  • 1,128
  • 1
  • 14
  • 31

3 Answers3

5

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.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
1

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!

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
1

I have a solution for that, its really easy try this and you will get the same answer from MATLAB and python, by python u have sometimes to change the Format of the Inputs.

so try this:

sparse.spdiags(your_Array.T, diags, m, n)
Warcupine
  • 4,460
  • 3
  • 15
  • 24