我正试着用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()
调用放在一个 as_mutable()
,而不是猜测,而是这些错误表明我想出了正确的策略是什么 . 有没有人有任何指针?
我已经阅读了Immutable Matrices上的文档页面,但我仍然可以使用一些帮助来理解它们与标准可变矩阵的差异在这里是如何重要的,以及为什么某些操作(例如sympy.exp)在这些不同的类之间进行转换 .
1 回答
我声称这是Sympy中的一个错误:
在Python中,你可以overload the multiplication operator from both sides .
A*B
可以在内部通过调用A.__mul__(B)
或B.__rmul__(A)
来处理 . Python首先调用A.__mul__
,如果此方法不存在或返回NotImplemented
,则Python会自动尝试B.__rmul__
. SymPy使用名为call_highest_priority的装饰器来决定使用哪两个实现 . 它查找所涉及的类的_op_priority
并以更高的优先级调用实现的功能 . 您的案例中的优先级为v
和I
为11,I_
为10.01,因此首选I
. 此外,I
使用的__mul__
的基本实现缺少装饰器 .长话短说,
I*v
最终总是调用I.__mul__
,__mul__
无法处理MatrixSymbol
但是也不会返回NotImplemented
.v.__rmul__(I)
按预期工作 .正确的解决方法是捕获
matrices.py
中的AttributeError
并返回NotImplemented
,即然后Python会自动回退到
__rmul__
. hack'ish修复将是调整_op_priority
. 无论哪种方式,你都应该提交错误报告:如果错误是设计错误的(也就是说,如果你不小心尝试了不应该工作的东西),那么错误信息会这样说 .