【问题标题】:python determinant of a large matrix大矩阵的python行列式
【发布时间】:2015-05-30 11:48:53
【问题描述】:

我有一个线性方程组,例如 MX=N。 M 是一个 21x21 矩阵,其中许多元素为零。当我尝试用X = np.linalg.solve(M, N) 解决这个系统时,它给了我这个错误:

numpy.linalg.linalg.LinAlgError: Singular matrix

这里的问题是np.linalg.det(M)返回的值是0.0。 我尝试了两种不同的方法来生成M 矩阵,此时我遇到了一个奇怪的行为:

i) M 的非零元素是在代码的其他地方计算的。所有这些元素都是浮点数并表示为m_1, m_2, ... , m_21。起初,我尝试了以下代码以生成M

M = np.zeros([21,21])
M[0,0] = m_1
M[0,1] = m_2
M[1,0] = m_3
M[1,4] = m_2
M[2,2] = m_2
M[2,3] = m_1
M[3,3] = m_3
M[3,5] = m_2
M[4,4] = m_4
M[4,5] = m_5
M[5,8] = m_6
M[5,13] = m_7
M[6,9] = m_6
M[6,14] = m_7
M[7,11] = m_6
M[7,12] = m_7
M[8,8] = m_8
M[8,9] = m_9
M[8,11] = m_10
M[9,6] = m_11
M[9,8] = m_12
M[9,20] = m_13
M[10,5] = m_11
M[10,10] = m_12
M[10,19] = m_13
M[11,19] = m_14
M[11,20] = m_15
M[12,8] = m_15
M[12,10] = m_14
M[13,16] = m_4
M[13,17] = m_17
M[14,7] = m_15
M[14,17] = m_16
M[15,16] = m_18
M[15,18] = m_7
M[16,17] = m_19
M[16,18] = m_20
M[17,4] = m_14
M[17,16] = m_16
M[18,11] = m_12
M[18,15] = m_13
M[19,12] = m_20
M[19,15] = m_21
M[20,7] = m_19
M[20,13] = m_20
M[20,20] = m_21

np.linalg.det(M) 计算的这个矩阵的行列式为零。

ii) 然后我将非零元素 (m_1, ... , m_21) 替换为相应的数值,看看行列式是否会改变。这是代码:

 M = np.matrix([[-88.89714245, 33.72326786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #1
                [-139.63175129, 0, 0, 0, 33.72326786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],#2
                [0,0,33.72326786, -88.89714245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #3
                [0, 0, 0, -139.63175129, 0, 33.72326786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],#4
                [0, 0, 0, 0, 98.58344885, 55.0147276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #5
                [0, 0, 0, 0, 0, 0, 0, 0, 114.92510983, 0, 0, 0, 0, 66.13785145, 0, 0, 0, 0, 0, 0, 0], #6
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 114.92510983, 0, 0, 0, 0, 66.13785145, 0, 0, 0, 0, 0, 0], #7
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114.92510983, 66.13785145, 0, 0, 0, 0, 0, 0, 0, 0], #8
                [0, 0, 0, 0, 0, 0, 0, 0, 28.52149986, -96.35068993, 0, 67.82919006, 0, 0, 0, 0, 0, 0, 0, 0, 0], #9
                [0, 0, 0, 0, 0, 0, 83.66136319, 0, 95.15580459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -178.81716778], #10
                [0, 0, 0, 0, 0, 83.66136319, 0, 0, 0, 0, 95.15580459, 0, 0, 0, 0, 0, 0, 0, 0, -178.81716778, 0], #11
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89.26005554, 67.6481946], #12
                [0, 0, 0, 0, 0, 0, 0, 0, 67.6481946, 0, 89.26005554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #13
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,98.58344885, -153.59817645, 0, 0, 0], #14
                [0, 0, 0, 0, 0, 0, 0, 67.6481946, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156.90825014, 0, 0, 0], #15
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -181.06296128, 0,66.13785145, 0, 0], #16
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -153.11049424, 35.89577791, 0, 0], #17
                [0, 0, 0, 0, 89.26005554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -156.90825014, 0, 0, 0, 0], #18
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95.15580459, 0, 0, 0, -178.81716778, 0, 0, 0, 0, 0], #19
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35.89577791, 0, 0, 117.21471633, 0, 0, 0, 0, 0], #20
                [0, 0, 0, 0, 0, 0, 0, -153.11049424, 0, 0, 0, 0, 0, 35.89577791, 0, 0, 0, 0, 0, 0, 117.21471633]]) #21

在这种情况下,np.linalg.det(M) 返回 -9504863423.43。 我很确定行列式既不是 0.0 也不是 -9504863423.43,因为我用 MATLAB 和一些在线计算器计算了与 -3.8108e+019 相同的行列式。

我还尝试执行 LU 分解并使用 mpmath 计算行列式,但这些都不起作用。 为什么这两种情况可能会返回不同的值?以及如何正确计算行列式的任何想法?

我在 32 位 Win7 操作系统上使用 Python(x,y) 2.7.6.1。

【问题讨论】:

  • 你确定你写的矩阵没有错字吗?
  • Sympy 找到了 -9504928268.73573 的行列式(我发现与 numpy 的区别很奇怪,但它比 -3.8108e19 更接近您的结果)。
  • Mathematica 确认行列式为 -9.50486*10^9,我还复制了您的 numpy 计算。我认为完整的 numpy 矩阵很好。我不确定零行列式发生了什么,也许您以某种方式设置了 m?
  • 同样scipy.sparse.linal.eigs 确认了类似于-9504928268.73573 (k=20) 的结果。但我不确定算法实现是否不同。 (py3.7-64bit,我只有这个版本)

标签: python numpy matrix linear-algebra determinants


【解决方案1】:

最精确和自动化的方法是:

  1. 确保/设置矩阵以使用 dtype='float32'
  2. 那就做this

    M =  # Your matrix
    (sign, logdet) = np.linalg.slogdet(M)
    determinant = np.exp(logdet)
    

【讨论】:

  • 从测试中得出,np.float32 类型的行列式是4.33165e+18,而np.float64 的行列式是-9504863423.42953。使用np.linalg.slogdet 会返回相同的结果,但会丢失符号。恢复标志:np.exp(logdet) * sign.
猜你喜欢
  • 2017-02-02
  • 2011-05-19
  • 1970-01-01
  • 2021-10-05
  • 2011-03-02
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多