通过两种方式获取Sympy矩阵逆的分歧

0 投票
1 回答
24 浏览
提问于 2025-04-12 18:39

我正在尝试在 Sympy 中求一个简单数字矩阵的逆矩阵。我开始时有一个矩阵:

In [56]: A_MATRIX_M
Out[56]: 
⎡0.174683794941032   0.174688696013867   0.174688696013957   0.174683794941032   0.174688696013867   0.174688696013957 ⎤
⎢                                                                                                                      ⎥
⎢0.152985639387222   0.153053070078189   0.153053070078123   0.152985677401143   0.153053070078189   0.153053070078123 ⎥
⎢                                                                                                                      ⎥
⎢0.122289719307085    0.12255894161074    0.12255894161075   0.122289780080333    0.12255894161074    0.12255894161075 ⎥
⎢                                                                                                                      ⎥
⎢0.0888623464387251  0.0894599879866164  0.0894599879864983  0.0888623905998649  0.0894599879866165  0.0894599879864984⎥
⎢                                                                                                                      ⎥
⎢0.0584375462953993  0.0593271595778474  0.0593271595779078  0.0584375753365935  0.0593271595778473  0.0593271595779078⎥
⎢                                                                                                                      ⎥
⎣0.034711924284652   0.0356325950288525  0.035632595028856   0.0347119415351321  0.0356325950288525  0.035632595028856 ⎦

我可以通过 .inv() 来得到这个逆矩阵:

In [59]: A_M_INV.inv()
Out[59]: 
⎡-4.20862006694537e-38  -3.64678015602041e-38  -4.89393679687261e-39  -5.26008046298975e-38  -1.29781892788192e-38  1.12107780599699e-37 ⎤
⎢                                                                                                                                        ⎥
⎢-1.19250990841802e-38  -1.17838767512258e-38  -5.49930182641769e-39  -1.79347381150519e-38  -3.76673961453884e-39  3.67594291864767e-38 ⎥
⎢                                                                                                                                        ⎥
⎢1.27521806859415e-38   1.38241733868129e-38   1.33016305680983e-39   1.89098712400354e-38   7.63333345652249e-39   -4.07574230117266e-38⎥
⎢                                                                                                                                        ⎥
⎢-3.71566091342595e-39  -3.69178932808298e-39  -1.37147644288023e-39  -4.68481431180264e-39  -3.97158856857654e-39  8.39451101073365e-39 ⎥
⎢                                                                                                                                        ⎥
⎢1.47794212524182e-38   1.21859956435038e-38   7.46216287435121e-40   2.08223967916098e-38   8.25097707225834e-39   -4.0465253879286e-38 ⎥
⎢                                                                                                                                        ⎥
⎣-2.5158985894826e-39   -3.62021834376681e-39  -3.99023376900161e-40   -5.881653010039e-39   -3.44892577031322e-39  6.50635833262352e-39 ⎦

不过,我也应该能通过把伴随矩阵除以矩阵的行列式来得到逆矩阵。但是,这样得到的结果完全不同:

In [57]: A_M_INV = A_MATRIX_M.adjugate() / A_MATRIX_M.det()

In [58]: A_M_INV
Out[58]: 
⎡-1.03014934740997e+38  9.76285991918083e+37   -2.61712726811554e+38  -2.91755290755826e+38  2.02091254231468e+37   8.60970411767247e+37 ⎤
⎢                                                                                                                                        ⎥
⎢-1.0350460657459e+38   1.09196345494244e+38   1.65391718422458e+38   -4.62921116834264e+37  -4.10946591995717e+38  -2.93534695043802e+38⎥
⎢                                                                                                                                        ⎥
⎢3.44664755653471e+37   -1.86912642859017e+38  -8.76351586189679e+37  -2.26077970623935e+38  -1.67328014514703e+37  1.00789976403353e+38 ⎥
⎢                                                                                                                                        ⎥
⎢1.82916593489888e+37   -8.10152924803704e+37  -1.33638262519626e+38  2.88888937621382e+38   1.19814518627368e+38   -3.22157029803083e+38⎥
⎢                                                                                                                                        ⎥
⎢6.14049097203001e+37   2.94210971355518e+37   5.88396356342516e+37   -2.59752889211905e+38   1.036688778158e+38    1.24211877586664e+38 ⎥
⎢                                                                                                                                        ⎥
⎣-4.62263666898771e+37  2.94055576923073e+37   -1.04165393746291e+38  -2.89791317977202e+37  -5.86035000752247e+37  -1.95539341633241e+38⎦

这里有个例子,别人用这种方法来求逆矩阵:

为什么 sympy.Matrix.inv 这么慢?

为什么结果会不同呢?尝试用这个逆矩阵来解一个简单的方程时发现,两个结果似乎都不是正确的逆矩阵。我不太确定问题出在哪里,是因为矩阵的指数太大,或者描述矩阵时需要的精度不够吗?

提前谢谢你的帮助!

编辑:在 @Jared 的帮助下,我进一步调查,发现了这个问题:MATLAB 和 Python 的逆矩阵结果不同,现在我知道我的矩阵是病态的/基本上是奇异的,这使得它无法有一个明确的逆矩阵。

1 个回答

1

以下是我作为回答发布的评论:

首先,注意到你的“逆矩阵”其实就是一个零矩阵。我创建了你的矩阵并计算了行列式,结果大约是0。

import sympy as smp

A = smp.Matrix([[0.174683794941032, 0.174688696013867, 0.174688696013957, 0.174683794941032, 0.174688696013867, 0.174688696013957],
                [0.152985639387222, 0.153053070078189, 0.153053070078123, 0.152985677401143, 0.153053070078189, 0.153053070078123],
                [0.122289719307085, 0.12255894161074, 0.12255894161075, 0.122289780080333, 0.12255894161074, 0.12255894161075],
                [0.0888623464387251, 0.0894599879866164, 0.0894599879864983, 0.0888623905998649, 0.0894599879866165, 0.0894599879864984],
                [0.0584375462953993, 0.0593271595778474, 0.0593271595779078, 0.0584375753365935, 0.0593271595778473, 0.0593271595779078],
                [0.034711924284652, 0.0356325950288525, 0.035632595028856, 0.0347119415351321, 0.0356325950288525, 0.035632595028856]])

print(A.det())  # -9.86673942982700e-57

当你用第二种方法计算逆矩阵时,得到的数字很大,因为你在用一个很小的数字去除。你的矩阵条件不好,基本上是奇异的(也就是说,它没有逆矩阵)。

记住,在这种情况下,你处理的是浮点数,所以行列式的值,sympy计算得大约是0,就是0。我不太明白为什么sympy不认为这个矩阵是奇异的,还返回了一个逆矩阵(我不知道它内部做了什么检查)。sympy似乎认为它是可逆的(sympy在检查A.rank()时说它是满秩的),但结果似乎并不支持这个说法。

我们还可以检查矩阵的特征值。(特征值是通过Matrix.eigenvals()返回的字典的键。)

print(A.eigenvals()) # {0.633575259554063: 1, 4.07013965394438e-9: 1, -6.35328826990267e-17: 1, -2.95260889975432e-15: 1, -3.59523027736480e-14: 1, 0.000542688212375667: 1}

注意到其中有3个(可以说是4个)特征值基本上是0。一个矩阵必须有非零的特征值才能是可逆的。

这里有一个矩阵可逆的条件列表:https://mathworld.wolfram.com/InvertibleMatrixTheorem.html

撰写回答