为什么numpy行列式在给定分数矩阵时不返回分数?

时间:2015-03-21 11:13:53

标签: python numpy matrix rational-number

我想对有理矩阵进行操作。我使用模块numpyfractions

这是我的代码:

import numpy as np
from fractions import Fraction

m=np.matrix([[Fraction(1, 6), Fraction(8, 7)], [Fraction(1, 2), Fraction(3, 2)]])
print(np.linalg.det(m))
# Gives -0.321428571429

print(m[0,0]*m[1,1] - m[0,1]*m[1,0])
# Gives -9/28

由于计算行列式只需要用高斯算法进行合理运算。方法,有理矩阵的行列式是合理的。

所以我的问题是:为什么numpy会返回一个浮点而不是一个Fraction?我怎样才能得到理性的决定因素?

请注意,此矩阵上的其他操作会提供合理的输出(例如m.trace())。

2 个答案:

答案 0 :(得分:5)

NumPy通过LAPACK中的下部上分解例程计算矩阵的行列式。此例程只能处理浮点数。

在计算矩阵的行列式之前,linalg.det检查它具有的值的类型,然后建立应该使用对名为_commonType()的函数的调用运行的内部循环的类型。此函数将循环设置为double或complex-double值。

以下是处理检查的函数linalg.det的Python部分:

def det(a):
    a = asarray(a) # convert matrix to NumPy array
    _assertNoEmpty2d(a)
    _assertRankAtLeast2(a)
    _assertNdSquareness(a)
    t, result_t = _commonType(a) # input/output types established here
    signature = 'D->D' if isComplexType(t) else 'd->d' # signature 'float->float' chosen 
    return _umath_linalg.det(a, signature=signature).astype(result_t) 

在对矩阵的形状进行检查并确定类型之后,return行将数组中的值传递给上下分解的LAPACK实现,并返回一个float。

尝试使用我们自己的类型签名绕过此类型检查会引发错误,指出没有为对象类型定义此类循环:

>>> np.linalg._umath_linalg.det(a, signature='O->O') # 'O' is 'object'
TypeError: No loop matching the specified signature was found for ufunc det

这意味着使用Fraction时不能将det类型保留为返回类型。

trace()等其他函数不会与det进行相同的类型检查,并且对象类型可能会持续存在。 trace只需通过调用Fraction对象的__add__方法对对角线进行求和,因此可以将Fraction对象保留为返回类型。

如果要将行列式计算为有理数,可以调查SymPy。诸如计算决定因素之类的矩阵运算记录在here

答案 1 :(得分:1)

在我看来,这不是一个容易解决的问题,可能会限制np.linalg依赖于lapack的大部分操作。查看numpy.linalg的源代码,似乎在调用任何lapack例程之前调用了一个名为_commonType的例程。这会尝试为输入数组中包含的数据找到合适的类型,但如果它无法确定类型,则会假定类型为double。在传递给lapack例程之前,数组是对结果类型的强制转换。这很可能已经完成,因为几乎不可能处理可以通过的每种类型。

我从未使用过Fraction软件包,所以我无法为您提供可行的解决方案来回到Fraction个对象的矩阵。我建议打电话给m.astype(Fraction),但这似乎也没有。

  • 列表项