加快SymPy中符号行列式的计算 [英] Speeding up computation of symbolic determinant in SymPy
问题描述
我有一个4x4矩阵A
,在每个条目中都有相当长但很简单的符号表达式.涉及大约30个不同的符号. 简单"是指仅使用加/减,乘/除和整数幂来组合这些符号. 长"是指如果我打印出矩阵,它将覆盖三到四个屏幕.
I have a 4x4 matrix A
with rather long but simple symbolic expressions in each of its entries. About 30 different symbols are involved. By "simple" I mean that these symbols are combined using only addition/subtraction, multiplication/division, and integer powers. By "long" I mean that if I print out the matrix, it covers three or four screens worth.
我需要这个矩阵的行列式.或者,更具体地说,我知道行列式是一个特定符号中的四阶多项式,并且我需要该多项式的系数. A.det()
在运行数小时后不会终止,因此我需要一种不同的方法.有任何想法吗?到目前为止,我已经尝试在A
的每个元素上抛出各种simplify
函数,但均未成功.
I need the determinant of this matrix. Or, to be more specific, I know that the determinant is a fourth-order polynomial in one particular symbol, and I need the coefficients of this polynomial. A.det()
does not terminate after hours and hours of running, so I need a different approach. Any ideas? So far I've tried to throw various simplify
functions at each element of A
without any success.
是否可以使用一些策略让SymPy知道表达式的简单结构,或者我知道结果是其中一个符号的多项式?
Is there some strategy I can employ to let SymPy be aware of the simple structure of my expressions, or that I know that the result is a polynomial in one of the symbols?
推荐答案
也许可以为4x4行列式创建通用表达式
Maybe it would work to create the general expression for a 4x4 determinant
In [30]: A = Matrix(4, 4, symbols('A:4:4'))
In [31]: A
Out[31]:
⎡A₀₀ A₀₁ A₀₂ A₀₃⎤
⎢ ⎥
⎢A₁₀ A₁₁ A₁₂ A₁₃⎥
⎢ ⎥
⎢A₂₀ A₂₁ A₂₂ A₂₃⎥
⎢ ⎥
⎣A₃₀ A₃₁ A₃₂ A₃₃⎦
In [32]: A.det()
Out[32]:
A₀₀⋅A₁₁⋅A₂₂⋅A₃₃ - A₀₀⋅A₁₁⋅A₂₃⋅A₃₂ - A₀₀⋅A₁₂⋅A₂₁⋅A₃₃ + A₀₀⋅A₁₂⋅A₂₃⋅A₃₁ + A₀₀⋅A₁₃⋅A₂₁⋅A₃₂ - A₀₀⋅A₁₃⋅A₂₂⋅A₃₁ - A₀₁⋅A₁₀⋅A₂₂⋅A₃₃ + A₀₁⋅A₁₀⋅A₂₃⋅A₃₂ + A₀₁⋅A₁₂⋅A₂₀⋅
A₃₃ - A₀₁⋅A₁₂⋅A₂₃⋅A₃₀ - A₀₁⋅A₁₃⋅A₂₀⋅A₃₂ + A₀₁⋅A₁₃⋅A₂₂⋅A₃₀ + A₀₂⋅A₁₀⋅A₂₁⋅A₃₃ - A₀₂⋅A₁₀⋅A₂₃⋅A₃₁ - A₀₂⋅A₁₁⋅A₂₀⋅A₃₃ + A₀₂⋅A₁₁⋅A₂₃⋅A₃₀ + A₀₂⋅A₁₃⋅A₂₀⋅A₃₁ - A₀₂⋅A₁
₃⋅A₂₁⋅A₃₀ - A₀₃⋅A₁₀⋅A₂₁⋅A₃₂ + A₀₃⋅A₁₀⋅A₂₂⋅A₃₁ + A₀₃⋅A₁₁⋅A₂₀⋅A₃₂ - A₀₃⋅A₁₁⋅A₂₂⋅A₃₀ - A₀₃⋅A₁₂⋅A₂₀⋅A₃₁ + A₀₃⋅A₁₂⋅A₂₁⋅A₃₀
,然后用类似的内容代替条目
and then substitute in the entries with something like
A.det().subs(zip(list(A), list(your_matrix)))
SymPy生成4x4行列式的速度很慢,但这是一个错误.您应在 https://github.com/sympy/sympy/issues/new.
SymPy being slow to generate a 4x4 determinant is a bug, though. You should report it at https://github.com/sympy/sympy/issues/new.
编辑(这不适合评论)
Matrix.det
似乎正在调用简化函数.对于3x3或更小的矩阵,行列式公式已明确写出,但对于较大的矩阵,使用Bareis算法进行计算.您可以看到简化函数(cancel
)在哪里被称为此处,这是计算的一部分,这是必需的,但最终却做了很多工作,因为它试图简化非常大的表达式.仅执行取消行列式本身的项所需的简化可能会更明智.为此,我打开了一个问题.
It looks like Matrix.det
is calling a simplification function. For matrices 3x3 and smaller, the determinant formula is written out explicitly, but for larger matrices, it is computed using the Bareis algorithm. You can see where the simplification function (cancel
) is called here, which is necesssary as part of the computation, but end up doing a lot of work because it tries to simplify your very large expressions. It would probably be smarter to only do the simplifications that are needed to cancel terms of the determinant itself. I opened an issue for this.
另一种加快速度的可能性(我不确定是否可行)将是选择其他行列式算法.选项为Matrix.det(method=alg)
,其中alg
是"bareis"
(默认值),"berkowitz"
或"det_LU"
之一.
Another possibility to speed this up, which I'm not sure will work or not, would be to select a different determinant algorithm. The options are Matrix.det(method=alg)
where alg
is one of "bareis"
(the default), "berkowitz"
, or "det_LU"
.
这篇关于加快SymPy中符号行列式的计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!