块三对角矩阵蟒蛇

时间:2011-04-30 15:52:57

标签: python matrix numpy

我想从三个numpy.ndarray开始创建一个块三对角矩阵。 在python中有没有(直接)方法呢?

提前谢谢!

干杯

8 个答案:

答案 0 :(得分:23)

使用“常规”numpy数组,使用numpy.diag

def tridiag(a, b, c, k1=-1, k2=0, k3=1):
    return np.diag(a, k1) + np.diag(b, k2) + np.diag(c, k3)

a = [1, 1]; b = [2, 2, 2]; c = [3, 3]
A = tridiag(a, b, c)

答案 1 :(得分:7)

你也可以通过花哨的索引编写“常规”numpy数组:

import numpy as np
data = np.zeros((10,10))
data[np.arange(5), np.arange(5)+2] = [5, 6, 7, 8, 9]
data[np.arange(3)+4, np.arange(3)] = [1, 2, 3]
print data

(如果您想要更加简洁,可以将np.arange的这些来电替换为np.r_。例如,而不是data[np.arange(3)+4, np.arange(3)],请使用data[np.r_[:3]+4, np.r_[:3]]

这会产生:

[[0 0 5 0 0 0 0 0 0 0]
 [0 0 0 6 0 0 0 0 0 0]
 [0 0 0 0 7 0 0 0 0 0]
 [0 0 0 0 0 8 0 0 0 0]
 [1 0 0 0 0 0 9 0 0 0]
 [0 2 0 0 0 0 0 0 0 0]
 [0 0 3 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

但是,如果您打算使用稀疏矩阵,请查看scipy.sparse.spdiags。 (请注意,如果您将数据放入具有正值的对角线位置(例如示例中位置4中的3),则需要假数据添加到行值上。)

作为一个简单的例子:

import numpy as np
import scipy as sp
import scipy.sparse

diag_rows = np.array([[1, 1, 1, 1, 1, 1, 1],
                      [2, 2, 2, 2, 2, 2, 2],
                      [0, 0, 0, 0, 3, 3, 3]])
positions = [-3, 0, 4]
print sp.sparse.spdiags(diag_rows, positions, 10, 10).todense()

这会产生:

[[2 0 0 0 3 0 0 0 0 0]
 [0 2 0 0 0 3 0 0 0 0]
 [0 0 2 0 0 0 3 0 0 0]
 [1 0 0 2 0 0 0 0 0 0]
 [0 1 0 0 2 0 0 0 0 0]
 [0 0 1 0 0 2 0 0 0 0]
 [0 0 0 1 0 0 2 0 0 0]
 [0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0]
 [0 0 0 0 0 0 1 0 0 0]]

答案 2 :(得分:6)

使用函数scipy.sparse.diags

示例:

from scipy.sparse import diags
import numpy as np
#
n = 10
k = np.array([np.ones(n-1),-2*np.ones(n),np.ones(n-1)])
offset = [-1,0,1]
A = diags(k,offset).toarray()

返回:

array([[-2.,  1.,  0.,  0.,  0.],
       [ 1., -2.,  1.,  0.,  0.],
       [ 0.,  1., -2.,  1.,  0.],
       [ 0.,  0.,  1., -2.,  1.],
       [ 0.,  0.,  0.,  1., -2.]])

答案 3 :(得分:3)

@TheCorwoodRep 的答案实际上可以在一行中完成。无需单独的功能。

np.eye(3,3,k=-1) + np.eye(3,3)*2 + np.eye(3,3,k=1)*3

这会产生:

array([[ 2.,  3.,  0.],
       [ 1.,  2.,  3.],
       [ 0.,  1.,  2.]])

答案 4 :(得分:1)

我对@CorwoodRep答案的回答。我只是发布它,因为我做了一些更改,使其更加模块化,以便它可以适用于不同的矩阵顺序,也可以更改k1k2k3的值,即决定对角线出现的位置将自动处理溢出。在调用函数时,您可以指定对角线上应显示的值。

import numpy as np
def tridiag(T,x,y,z,k1=-1, k2=0, k3=1):
    a = [x]*(T-abs(k1)); b = [y]*(T-abs(k2)); c = [z]*(T-abs(k3))
    return np.diag(a, k1) + np.diag(b, k2) + np.diag(c, k3)

D=tridiag(10,-1,2,-1)

答案 5 :(得分:0)

由于三对角矩阵是使用稀疏包的稀疏矩阵可能是一个不错的选择,请参阅http://pysparse.sourceforge.net/spmatrix.html#matlab-implementation,有一些例子和MATLAB的比较甚至......

答案 6 :(得分:0)

无论好坏,所有其他答案似乎都回答了关于三对角矩阵而不是三对角矩阵。

我不认为对三对角矩阵有原生支持,所以我编写了自己的代码。我在主对角线上有零,我的矩阵是对称的。

这是我的代码。

n1 = 784
n2 = 256
n3 = 128
n4 = 10
M1 = np.ones((n1,n2))
M2 = np.ones((n2,n3))
M3 = np.ones((n3, n4))

def blockTri(Ms):
    #Takes in a list of matrices (not square) and returns a tridiagonal block matrix with zeros on the diagonal
    count = 0
    idx = []
    for M in Ms:
        #print(M.shape)
        count += M.shape[0]
        idx.append(count)
    count += Ms[-1].shape[-1]
    mat = np.zeros((count,count))
    count = 0
    for i, M in enumerate(Ms):
        mat[count:count+M.shape[0],idx[i]:idx[i]+M.shape[1]] = M
        count = count + M.shape[0]
    mat = mat + mat.T    
    return mat

M = blockTri([M1, M2, M3])

希望这可以帮助未来的人们寻找阻止三对角矩阵。

答案 7 :(得分:0)

要从三个单独的块中构建一个块状三对角矩阵(并将这些块重复N次),一种解决方案可以是:

import numpy as np
from scipy.linalg import block_diag

def tridiag(c, u, d, N): 
    # c, u, d are center, upper and lower blocks, repeat N times
    cc = block_diag(*([c]*N)) 
    shift = c.shape[1]
    uu = block_diag(*([u]*N)) 
    uu = np.hstack((np.zeros((uu.shape[0], shift)), uu[:,:-shift]))
    dd = block_diag(*([d]*N)) 
    dd = np.hstack((dd[:,shift:],np.zeros((uu.shape[0], shift))))
    return cc+uu+dd

例如:

c=np.matrix([[1,2],[3,4]])
u = np.matrix([[5,6],[7,8]])
d = -1*u
N=4
H = tridiag(c,u,d,N)
print(H)

给出答案

[[ 1.  2.  5.  6.  0.  0.  0.  0.]
 [ 3.  4.  7.  8.  0.  0.  0.  0.]
 [-5. -6.  1.  2.  5.  6.  0.  0.]
 [-7. -8.  3.  4.  7.  8.  0.  0.]
 [ 0.  0. -5. -6.  1.  2.  5.  6.]
 [ 0.  0. -7. -8.  3.  4.  7.  8.]
 [ 0.  0.  0.  0. -5. -6.  1.  2.]
 [ 0.  0.  0.  0. -7. -8.  3.  4.]]