创建大对角稀疏矩阵

时间:2015-03-15 21:58:00

标签: python scipy

我有一个缩放参数x和一些矩阵A。我需要创建的是sparse矩阵,以便

A是一个方阵:

A_00, A_01, A_02, A_03
A_10, A_11, A_12, A_13
A_20, A_21, A_22, A_23
A_30, A_31, A_32, A_33

x是一个整数。然后我希望在x中的元素之间创建0s多个A,并删除对角矩阵。也就是说,对于上面的x=3A,我的期望的结果将是:

0, 0, 0, A_01, 0, 0, A_02, 0, 0, A_03, 0, 0,
0, 0, 0, 0, A_01, 0, 0, A_02, 0, 0, A_03, 0,
0, 0, 0, 0, 0, A_01, 0, 0, A_02, 0, 0, A_03,
A_10, 0, 0, 0, 0, 0, A_12, 0, 0, A_13, 0, 0,
0, A_10, 0, 0, 0, 0, 0, A_12, 0, 0, A_13, 0,
0, 0, A_10, 0, 0, 0, 0, 0, A_12, 0, 0, A_13, 
A_20, 0, 0, A_21, 0, 0, 0, 0, 0, A_23, 0, 0,
0, A_20, 0, 0, A_21, 0, 0, 0, 0, 0, A_23, 0, 
0, 0, A_20, 0, 0, 0, A_21, 0, 0, 0, 0, A_23,
A_30, 0, 0, A_31, 0, 0, A_32, 0, 0, 0, 0, 0,
0, A_30, 0, 0, A_31, 0, 0, A_32, 0, 0, 0, 0,
0, 0, A_30, 0, 0, A_31, 0, 0, A_32, 0, 0, 0,

我需要这个作为稀疏矩阵。目前,我正在尝试使用kroneckernp.repeat创建对角元素,然后使用scipy.sparse.diags创建矩阵。

但也许有更高效和/或更清洁的方式?如果它使算法更具可读性,那么透明度会提高(达到一定程度)效率。这部分是一个数学问题,但也许我想要的输出是一些kronecker产品的结果?

2 个答案:

答案 0 :(得分:1)

我不知道这是否比你的解决方案更好,但看起来非常简单:

import numpy as np

A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]], dtype='int')

def sparsify(A, expandFactor):
    newShape = map(lambda d:expandFactor*d, A.shape)
    B = np.zeros(newShape, dtype='int')
    # Repeatedly assign A to B skipping over expandFactor indices, with a different offset each time.
    for offset in range(expandFactor):
        B[offset::expandFactor,offset::expandFactor] = A       
    # Set diagonal of matrix to zero:
    B[range(newShape[0]), range(newShape[1])] = 0
    return B

输出:

>>> sparsify(A, 3)
array([[0, 0, 0, 2, 0, 0, 3, 0, 0],
       [0, 0, 0, 0, 2, 0, 0, 3, 0],
       [0, 0, 0, 0, 0, 2, 0, 0, 3],
       [4, 0, 0, 0, 0, 0, 6, 0, 0],
       [0, 4, 0, 0, 0, 0, 0, 6, 0],
       [0, 0, 4, 0, 0, 0, 0, 0, 6],
       [7, 0, 0, 8, 0, 0, 0, 0, 0],
       [0, 7, 0, 0, 8, 0, 0, 0, 0],
       [0, 0, 7, 0, 0, 8, 0, 0, 0]])

答案 1 :(得分:1)

我注意到,我确实几乎将输出写为

np.kron(A, np.identity(x))

所以,这就是我现在正在做的事情(如果还有更高效/更清洁的东西,那么期待它):

>>> A = np.arange(1, 10).reshape((3,3))
#`fill_diagonal` overwrites with reference. Create some `B` matrix to not mess with `A`:
>>> B = A.copy()
>>> np.fill_diagonal(B, 0)
>>> sparseA = sparse.csc_matrix(B)
>>> sparseA.toarray()
array([[0, 2, 3],
       [4, 0, 6],
       [7, 8, 0]])
>>> x = 3
>>> sparseE = sparse.identity(x)
>>> result = sparse.kron(sparseA, sparseE)
>>> result.todense()
matrix([[ 0.,  0.,  0.,  2.,  0.,  0.,  3.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  2.,  0.,  0.,  3.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  2.,  0.,  0.,  3.],
        [ 4.,  0.,  0.,  0.,  0.,  0.,  6.,  0.,  0.],
        [ 0.,  4.,  0.,  0.,  0.,  0.,  0.,  6.,  0.],
        [ 0.,  0.,  4.,  0.,  0.,  0.,  0.,  0.,  6.],
        [ 7.,  0.,  0.,  8.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  7.,  0.,  0.,  8.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  7.,  0.,  0.,  8.,  0.,  0.,  0.]])