有办法让Python在500位小数精度下执行矩阵求逆吗?

huangapple go评论80阅读模式
英文:

Is there a way for python to perform a matrix inversion at 500 decimal precision

问题

有一个对输出精度敏感的算法。特别是,论文要求执行一个500位小数精度的实数矩阵求逆运算。我想写一个Python脚本来检查结果。然而,在NumPy中使用的最大浮点数据类型是np.float128,而decimal包似乎没有矩阵求逆函数。

我找到了这篇帖子https://stackoverflow.com/questions/32685280/matrix-inverse-with-decimal-type-numpy,它介绍了将decimal作为NumPy函数中的对象。但我在Stack Exchange上看到了关于Python将对象传递为float(32)对象的评论,这是由于%运算符的原因。

Python是否有一种方法可以以500位小数精度执行矩阵求逆运算?

英文:

There's an algorithm sensitive to the precision of the output. Especially, the paper required a real matrix inverse to be performed at 500 decimals precision. I wanted to write a script to check the result with python. However, the largest float data type used in numpy was np.float128, and the deicmal package does not seem to have a matrix inverse function.

I found the post https://stackoverflow.com/questions/32685280/matrix-inverse-with-decimal-type-numpy which introduce the decimal as an object in the numpy's function. But I saw comments on stack exchange that python transfer the object as float(32) object because of the % operators.

Is there a way for python to perform a matrix inversion at 500 decimal precision?

答案1

得分: 1

根据https://mpmath.org/doc/current/matrices.html#advanced-methods,我导入了mpmath,并创建了一个(3,3)的矩阵:

A = mpmath.matrix([[1,3,4],[0,1,2],[3,0,1]])

并计算了它的逆矩阵:

A**-1

numpy 中的等效操作:

M = np.array([[1,3,4],[0,1,2],[3,0,1]])
np.linalg.inv(M)

以及比较的运行时间:

timeit np.linalg.inv(M)
timeit A**-1

在这个示例中,dps(显示精度)设置为30(默认值为15,类似于float64):

mpmath.mp.dps

有时用户担心逆矩阵与数组的点乘不完全产生单位矩阵,但请注意接近零的项非常小:

Out[295] @ M

以及30位小数精度:

Out[291] * A
英文:

Following https://mpmath.org/doc/current/matrices.html#advanced-methods,
I imported mpmath, and created (3,3) matrix:

In [289]: A =mpmath.matrix([[1,3,4],[0,1,2],[3,0,1]])

In [290]: A
Out[290]: 
matrix(
[['1.0', '3.0', '4.0'],
 ['0.0', '1.0', '2.0'],
 ['3.0', '0.0', '1.0']])

And calculated its inverse:

In [291]: A**-1
Out[291]: 
matrix(
[['0.142857142857142857142857142857', '-0.428571428571428571428571428571', '0.285714285714285714285714285714'],
 ['0.857142857142857142857142857143', '-1.57142857142857142857142857143', '-0.285714285714285714285714285714'],
 ['-0.428571428571428571428571428571', '1.28571428571428571428571428571', '0.142857142857142857142857142857']])

The equivalent numpy operation:

In [293]: M = np.array([[1,3,4],[0,1,2],[3,0,1]])
In [294]: M
Out[294]: 
array([[1, 3, 4],
       [0, 1, 2],
       [3, 0, 1]])
In [295]: np.linalg.inv(M)
Out[295]: 
array([[ 0.14285714, -0.42857143,  0.28571429],
       [ 0.85714286, -1.57142857, -0.28571429],
       [-0.42857143,  1.28571429,  0.14285714]])

And the comparative times:

In [296]: timeit np.linalg.inv(M)
17.2 µs ± 31 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

In [297]: timeit A**-1
1.19 ms ± 1.26 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In this case I have the dps (display precision) set at 30 (the default is 15, similar to a float64

In [298]: mpmath.mp.dps
Out[298]: 30

SO posters often worry about the dot of inverse with array doesn't quite produce the identity matrix. But notice how small the near 0 terms are:

In [299]: Out[295]@M
Out[299]: 
array([[ 1.00000000e+00, -5.55111512e-17, -5.55111512e-17],
       [ 1.11022302e-16,  1.00000000e+00,  3.88578059e-16],
       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])

And to 30 dps:

In [301]: Out[291]*A
Out[301]: 
matrix(
[['1.0', '-7.22223729145213444895991728469e-35', '-4.81482486096808963263994485646e-35'],
 ['1.44444745829042688979198345694e-34', '1.0', '3.37037740267766274284796139952e-34'],
 ['-2.40741243048404481631997242823e-35', '9.62964972193617926527988971292e-35', '1.0']])

huangapple
  • 本文由 发表于 2023年3月7日 07:48:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75656846.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定