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

sympy: 'Transpose' object has no attribute tolist

我正在尝试使用 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'

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

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

我注意到的一件事是两个单位矩阵不同 类:

>>> I.__class__
sympy.matrices.immutable.ImmutableMatrix
>>> I_.__class__
sympy.matrices.dense.MutableDenseMatrix

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

>>> I.as_mutable() * v
v

是否总是需要在整个线性代数计算过程中进行 as_mutable() 调用?我猜不是,相反,这些错误表明我使用了错误的策略来解决我的问题,但我无法弄清楚正确的策略是什么。有人有什么指点吗?

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

我声称这是 Sympy 中的错误:

在 Python 中,您可以 overload the multiplication operator from both sides. A*B may internally be handled by either calling A.__mul__(B), or B.__rmul__(A). Python first calls A.__mul__, and if this method does not exist or returns NotImplemented, then Python tries B.__rmul__ automatically. SymPy instead uses a decorator called call_highest_priority 决定使用两种实现中的哪一种。它查找涉及类的_op_priority,并调用具有更高优先级的实现函数。在您的案例中,vI 的优先级为 11,I_ 的优先级为 10.01,因此 I 是首选。此外,I 使用的 __mul__ 的基本实现缺少装饰器。

长话短说,I*v 最终总是调用 I.__mul__,并且 __mul__ 无法处理 MatrixSymbol 但 return NotImplemented 任何一个。 v.__rmul__(I) 按预期工作。

正确的解决方法是在 matrices.py 和 return NotImplemented 中捕获 AttributeError,即

try:
    blst = B.T.tolist()
except AttributeError:
    return NotImplemented

Python 然后会自动回退到 __rmul__。骇人听闻的解决办法是调整 _op_priority。无论哪种方式,您都应该提交错误报告:如果错误是设计使然的(也就是说,如果您不小心尝试了一些不应该工作的东西),那么错误消息会这样说。