为什么 sympy 认为只有实变量的函数很复杂?
Why does sympy think that a function of only real variables is complex?
我一直在努力让 sympy 为我简化这个复杂的代数表达式:
其中 Delta、Gamma、t 和 hbar 是实数。我用来生成这个表达式的代码是:
from __future__ import division
from pylab import *
from sympy import *
def main():
d, g, t = symbols("Delta Gamma t", real=True)
hbar = symbols("hbar", positive=True, real=True)
dg = sqrt(d**2 + g**2)
S = simplify(Matrix([[(dg - g) / d, -(g + dg)/d], [1, 1]]))
D = simplify(Matrix([[exp(I * t * dg / hbar), 0], [0, exp(-I * t * dg / hbar)]]))
Sinverse = simplify(Matrix([[d / (2*dg), (g / dg + 1)/2], [-d / (2 * dg), 1/2 - g / (2*dg)]]))
U = simplify(S * D * Sinverse)
initial = Matrix([[1], [0]])
later = simplify(U * initial)
P1 = simplify(abs(later[0])**2)
preview(P1)
if __name__=="__main__":
main()
由于我不明白的原因,sympy 拒绝承认相位的大小为 1(即我们可以消除绝对值符号内表达式最右侧的乘法指数)。我测试了如果我们有一个非常简单的绝对值符号指数,sympy 是否会简化这种情况。好像不是:
>>> from pylab import *
>>> from sympy import *
>>> t = symbols("t", real=True)
>>> z = exp(t*I)
>>> abs(z).simplify()
Abs(exp(I*t))
我已经尝试了两种补救措施来解决这个问题,但都没有奏效:
(1) 用参数乘以参数的共轭复数替换绝对值符号的平方。当我将 main()
函数的结尾改为:
...
P1 = simplify(later[0] * later[0].conjugate())
preview(P1)
我得到了更丑陋的表情:
这确实修复了上面虚构的场景:
>>> from pylab import *
>>> from sympy import *
>>> t = symbols("t", real=True)
>>> z = exp(t*I)
>>> abs(z).simplify()
Abs(exp(I*t))
>>> z * z.conjugate()
1
(2)用关键字complex=True
展开量级,再进行化简。这个方法也解决了虚构的场景:
>>> from pylab import *
>>> from sympy import *
>>> t = symbols("t", real=True)
>>> z = exp(t*I)
>>> abs(z).simplify()
Abs(exp(I*t))
>>> abs(z).expand(complex=True).simplify()
1
然而,对于我的实际表达来说,它滑稽地失败了。当我调整 main()
函数以使用此方法时:
...
P1 = (abs(later[0])**2).expand(complex=True).simplify()
preview(P1)
程序崩溃。当我取消 .simplify()
并将 preview
更改为 print
时,我得到了 613.8 kB 的文本输出!查看输出文件的第一页和最后一页,它实际上看起来像是一个非常巨大的表达式(即我不认为这是一些愚蠢的长错误消息或类似的东西)。难怪当我试图简化它时程序崩溃了:)
我不知道第二种方法出了什么问题,但是看第一种方法的输出,sympy 似乎没有意识到实变量平方和的平方根也是实数。我应该怎么做才能解决这个问题?是否需要将一些参数传递给某个函数以告诉它 Gamma 和 Delta 的平方和的平方根是实数?
任何帮助将不胜感激!
看来开发版的 SymPy(即将发布 1.0)可以做这样的简化:
In [1]: t = Symbol('t', real=True)
In [2]: abs(exp(-t*I))
Out[2]: 1
对于你的例子,我得到
In [13]: P1
Out[13]:
2
│ _________│
│ ╱ 2 2 │
│ 2⋅ⅈ⋅t⋅╲╱ Δ + Γ │
│ _________ ⎛ _________⎞ ──────────────────│
│ ╱ 2 2 ⎜ ╱ 2 2 ⎟ h̅ │
-│Γ + ╲╱ Δ + Γ - ⎝Γ - ╲╱ Δ + Γ ⎠⋅ℯ │
──────────────────────────────────────────────────────────────
2 2
4⋅Δ + 4⋅Γ
不过我查了一下,最新的稳定版 (0.7.6.1) 并没有这样做,所以你要么需要等待 1.0,要么使用 git version。
我一直在努力让 sympy 为我简化这个复杂的代数表达式:
其中 Delta、Gamma、t 和 hbar 是实数。我用来生成这个表达式的代码是:
from __future__ import division
from pylab import *
from sympy import *
def main():
d, g, t = symbols("Delta Gamma t", real=True)
hbar = symbols("hbar", positive=True, real=True)
dg = sqrt(d**2 + g**2)
S = simplify(Matrix([[(dg - g) / d, -(g + dg)/d], [1, 1]]))
D = simplify(Matrix([[exp(I * t * dg / hbar), 0], [0, exp(-I * t * dg / hbar)]]))
Sinverse = simplify(Matrix([[d / (2*dg), (g / dg + 1)/2], [-d / (2 * dg), 1/2 - g / (2*dg)]]))
U = simplify(S * D * Sinverse)
initial = Matrix([[1], [0]])
later = simplify(U * initial)
P1 = simplify(abs(later[0])**2)
preview(P1)
if __name__=="__main__":
main()
由于我不明白的原因,sympy 拒绝承认相位的大小为 1(即我们可以消除绝对值符号内表达式最右侧的乘法指数)。我测试了如果我们有一个非常简单的绝对值符号指数,sympy 是否会简化这种情况。好像不是:
>>> from pylab import *
>>> from sympy import *
>>> t = symbols("t", real=True)
>>> z = exp(t*I)
>>> abs(z).simplify()
Abs(exp(I*t))
我已经尝试了两种补救措施来解决这个问题,但都没有奏效:
(1) 用参数乘以参数的共轭复数替换绝对值符号的平方。当我将 main()
函数的结尾改为:
...
P1 = simplify(later[0] * later[0].conjugate())
preview(P1)
我得到了更丑陋的表情:
这确实修复了上面虚构的场景:
>>> from pylab import *
>>> from sympy import *
>>> t = symbols("t", real=True)
>>> z = exp(t*I)
>>> abs(z).simplify()
Abs(exp(I*t))
>>> z * z.conjugate()
1
(2)用关键字complex=True
展开量级,再进行化简。这个方法也解决了虚构的场景:
>>> from pylab import *
>>> from sympy import *
>>> t = symbols("t", real=True)
>>> z = exp(t*I)
>>> abs(z).simplify()
Abs(exp(I*t))
>>> abs(z).expand(complex=True).simplify()
1
然而,对于我的实际表达来说,它滑稽地失败了。当我调整 main()
函数以使用此方法时:
...
P1 = (abs(later[0])**2).expand(complex=True).simplify()
preview(P1)
程序崩溃。当我取消 .simplify()
并将 preview
更改为 print
时,我得到了 613.8 kB 的文本输出!查看输出文件的第一页和最后一页,它实际上看起来像是一个非常巨大的表达式(即我不认为这是一些愚蠢的长错误消息或类似的东西)。难怪当我试图简化它时程序崩溃了:)
我不知道第二种方法出了什么问题,但是看第一种方法的输出,sympy 似乎没有意识到实变量平方和的平方根也是实数。我应该怎么做才能解决这个问题?是否需要将一些参数传递给某个函数以告诉它 Gamma 和 Delta 的平方和的平方根是实数?
任何帮助将不胜感激!
看来开发版的 SymPy(即将发布 1.0)可以做这样的简化:
In [1]: t = Symbol('t', real=True)
In [2]: abs(exp(-t*I))
Out[2]: 1
对于你的例子,我得到
In [13]: P1
Out[13]:
2
│ _________│
│ ╱ 2 2 │
│ 2⋅ⅈ⋅t⋅╲╱ Δ + Γ │
│ _________ ⎛ _________⎞ ──────────────────│
│ ╱ 2 2 ⎜ ╱ 2 2 ⎟ h̅ │
-│Γ + ╲╱ Δ + Γ - ⎝Γ - ╲╱ Δ + Γ ⎠⋅ℯ │
──────────────────────────────────────────────────────────────
2 2
4⋅Δ + 4⋅Γ
不过我查了一下,最新的稳定版 (0.7.6.1) 并没有这样做,所以你要么需要等待 1.0,要么使用 git version。