Skip to content Skip to sidebar Skip to footer

Create Sparse Circulant Matrix In Python

I want to create a large (say 10^5 x 10^5) sparse circulant matrix in Python. It has 4 elements per row at positions [i,i+1], [i,i+2], [i,i+N-2], [i,i+N-1], where I have assumed pe

Solution 1:

To create a dense circulant matrix, you can use scipy.linalg.circulant. For example,

In [210]: from scipy.linalg import circulant

In [211]: N = 7

In [212]: vals = np.array([2.0/3, -1.0/12, 1.0/12, -2.0/3])

In [213]: offsets = np.array([1, 2, N-2, N-1])

In [214]: col0 = np.zeros(N)

In [215]: col0[offsets] = -vals

In [216]: c = circulant(col0)

In [217]: c
Out[217]: 
array([[ 0.    ,  0.6667, -0.0833,  0.    ,  0.    ,  0.0833, -0.6667],
       [-0.6667,  0.    ,  0.6667, -0.0833,  0.    ,  0.    ,  0.0833],
       [ 0.0833, -0.6667,  0.    ,  0.6667, -0.0833,  0.    ,  0.    ],
       [ 0.    ,  0.0833, -0.6667,  0.    ,  0.6667, -0.0833,  0.    ],
       [ 0.    ,  0.    ,  0.0833, -0.6667,  0.    ,  0.6667, -0.0833],
       [-0.0833,  0.    ,  0.    ,  0.0833, -0.6667,  0.    ,  0.6667],
       [ 0.6667, -0.0833,  0.    ,  0.    ,  0.0833, -0.6667,  0.    ]])

As you point out, for large N, that requires a lot of memory and most of the values are zero. To create a scipy sparse matrix, you can use scipy.sparse.diags. We have to create offsets (and corresponding values) for the diagonals above and below the main diagonal:

In [218]: from scipy import sparse

In [219]: N = 7

In [220]: vals = np.array([2.0/3, -1.0/12, 1.0/12, -2.0/3])

In [221]: offsets = np.array([1, 2, N-2, N-1])

In [222]: dupvals = np.concatenate((vals, vals[::-1]))

In [223]: dupoffsets = np.concatenate((offsets, -offsets))

In [224]: a = sparse.diags(dupvals, dupoffsets, shape=(N, N))

In [225]: a.toarray()
Out[225]: 
array([[ 0.    ,  0.6667, -0.0833,  0.    ,  0.    ,  0.0833, -0.6667],
       [-0.6667,  0.    ,  0.6667, -0.0833,  0.    ,  0.    ,  0.0833],
       [ 0.0833, -0.6667,  0.    ,  0.6667, -0.0833,  0.    ,  0.    ],
       [ 0.    ,  0.0833, -0.6667,  0.    ,  0.6667, -0.0833,  0.    ],
       [ 0.    ,  0.    ,  0.0833, -0.6667,  0.    ,  0.6667, -0.0833],
       [-0.0833,  0.    ,  0.    ,  0.0833, -0.6667,  0.    ,  0.6667],
       [ 0.6667, -0.0833,  0.    ,  0.    ,  0.0833, -0.6667,  0.    ]])

The matrix is stored in the "diagonal" format:

In [226]: a
Out[226]: 
<7x7 sparse matrix of type'<class 'numpy.float64'>'with28 stored elements (8 diagonals) in DIAgonal format>

You can use the conversion methods of the sparse matrix to convert it to a different sparse format. For example, the following results in a matrix in CSR format:

In [227]: a.tocsr()
Out[227]: 
<7x7 sparse matrix of type'<class 'numpy.float64'>'with28 stored elements in Compressed Sparse Row format>

Post a Comment for "Create Sparse Circulant Matrix In Python"