sympy:'Transpose'对象没有属性tolist

Pat*_*osh 8 python matrix symbolic-math sympy

我试图用sympy做一些符号矩阵计算.我的目标是获得一些矩阵计算结果的符号表示.我遇到了一些问题,我已经将这个问题归结为这个简单的例子,其中我尝试评估指数矩阵的取幂结果并将其乘以任意向量.

>>> import sympy
>>> v = sympy.MatrixSymbol('v', 2, 1)
>>> Z = sympy.zeros(2, 2)  # create 2x2 zero matrix
>>> I = sympy.exp(Z)  # exponentiate zero matrix to get identity matrix
>>> I * v
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "sympy/matrices/matrices.py", line 507, in __mul__
    blst = B.T.tolist()
AttributeError: 'Transpose' object has no attribute 'tolist'
Run Code Online (Sandbox Code Playgroud)

相反,如果我直接创建单位矩阵然后乘以v,那么就没有问题:

>>> I_ = sympy.eye(2)  # directly create the identity matrix
>>> I_ == I  # check the two matrices are equal
True
>>> I_ * v
v
Run Code Online (Sandbox Code Playgroud)

我注意到的一件事是两个身份矩阵属于不同的类:

>>> I.__class__
sympy.matrices.immutable.ImmutableMatrix
>>> I_.__class__
sympy.matrices.dense.MutableDenseMatrix
Run Code Online (Sandbox Code Playgroud)

我还发现调用该as_mutable()方法提供了一种解决方法.

>>> I.as_mutable() * v
v
Run Code Online (Sandbox Code Playgroud)

是否总是需要as_mutable()在一个线性代数计算中调用?我猜不是,而是这些错误表明我使用了错误的策略来解决我的问题,但我无法弄清楚正确的策略是什么.有没有人有任何指针?

我已经阅读了不可变矩阵的文档页面,但我仍然可以使用一些帮助来理解它们与标准可变矩阵的差异在这里是如何重要的,以及为什么某些操作(例如sympy.exp)在这些不同的类之间进行转换.

Phi*_*lip 4

我认为这是 Sympy 中的一个错误:

在Python中,您可以从两侧重载乘法运算符A*B可以通过调用A.__mul__(B)、 或进行内部处理B.__rmul__(A)。Python首先调用A.__mul__,如果该方法不存在或返回NotImplemented,则Python会B.__rmul__自动尝试。相反,SymPy 使用名为call_highest_priority 的装饰器来决定使用两种实现中的哪一个。它查找_op_priority相关类的 并调用具有更高优先级的实现函数。您的情况的优先级是 11vI10.01 I_,因此I是首选。__mul__此外,使用的的基本实现I缺少装饰器。

长话短说,I*v最终总是调用I.__mul__,并且__mul__无法处理MatrixSymbols 但也不返回NotImplementedv.__rmul__(I)按预期工作。

正确的解决方法是捕获AttributeErrorinmatrices.py和 return NotImplemented,即

try:
    blst = B.T.tolist()
except AttributeError:
    return NotImplemented
Run Code Online (Sandbox Code Playgroud)

然后 Python 会自动回退到__rmul__. 黑客式的修复方法是调整_op_priority. 无论哪种方式,您都应该提交错误报告:如果错误是设计造成的(也就是说,如果您不小心尝试了一些不应该起作用的东西),那么错误消息会这样说。