如何简化 Sympy 中包含复指数的表达式

How to simplify expressions containing complex exponentials in Sympy

在我正在处理的一个项目中,我正在处理包含复指数的表达式,例如下面的表达式,我的目标是尽可能简化它:

from sympy import Rational, exp, I, pi, pretty, cos, sin

E = Rational(1,20) + (Rational(1,4) + exp(2*I*pi/5)/4)*exp(-4*I*pi/5)/5 + exp(-2*I*pi/5)/20 + (exp(4*I*pi/5)/4 + exp(2*I*pi/5)/4)*exp(2*I*pi/5)/5 + (exp(-2*I*pi/5)/4 + exp(-4*I*pi/5)/4)*exp(4*I*pi/5)/5 + (exp(-4*I*pi/5)/4 + exp(4*I*pi/5)/4)*exp(-2*I*pi/5)/5

print(pretty(E))

     ⎛     2⋅ⅈ⋅π⎞                       ⎛ 4⋅ⅈ⋅π    2⋅ⅈ⋅π⎞          ⎛ -2⋅ⅈ⋅π     -4⋅ⅈ⋅π ⎞          ⎛ -4⋅ⅈ⋅π     4⋅ⅈ⋅π⎞         
     ⎜     ─────⎟  -4⋅ⅈ⋅π               ⎜ ─────    ─────⎟  2⋅ⅈ⋅π   ⎜ ───────    ───────⎟  4⋅ⅈ⋅π   ⎜ ───────    ─────⎟  -2⋅ⅈ⋅π 
     ⎜       5  ⎟  ───────    -2⋅ⅈ⋅π    ⎜   5        5  ⎟  ─────   ⎜    5          5   ⎟  ─────   ⎜    5         5  ⎟  ───────
     ⎜1   ℯ     ⎟     5       ───────   ⎜ℯ        ℯ     ⎟    5     ⎜ℯ          ℯ       ⎟    5     ⎜ℯ          ℯ     ⎟     5   
     ⎜─ + ──────⎟⋅ℯ              5      ⎜────── + ──────⎟⋅ℯ        ⎜──────── + ────────⎟⋅ℯ        ⎜──────── + ──────⎟⋅ℯ       
1    ⎝4     4   ⎠            ℯ          ⎝  4        4   ⎠          ⎝   4          4    ⎠          ⎝   4         4   ⎠         
── + ───────────────────── + ──────── + ──────────────────────── + ──────────────────────────── + ────────────────────────────
20             5                20                 5                            5                              5              

我设法对其进行了一些简化(主要是通过使用 https://docs.sympy.org/latest/modules/simplify/simplify.html 中描述的不同函数反复试验):

E.rewrite(cos).expand().simplify()
-sqrt(-10 - 2*sqrt(5))/64 - sqrt(-10 + 2*sqrt(5))/64 + sqrt(-50 + 10*sqrt(5))/320 + 3*sqrt(-50 - 10*sqrt(5))/320

print(pretty(_))
    ____________     ____________     _____________       _____________
  ╲╱ -10 - 2⋅√5    ╲╱ -10 + 2⋅√5    ╲╱ -50 + 10⋅√5    3⋅╲╱ -50 - 10⋅√5 
- ────────────── - ────────────── + ─────────────── + ─────────────────
        64               64               320                320       

然而,生成的表达式仍然可以进一步简化,实际上完全消失了——问题是如何在 Sympy 中 do/show 这个。我试过使用 sqrtdenest 来“取消嵌套”平方根,但到目前为止没有成功。

同样,另一个与第一个表达式非常相似的表达式简化为

print(pretty(-cos(pi/7)/7 - sin(pi/14)/7 + Rational(1,14) + sin(3*pi/14)/7))

     ⎛π⎞      ⎛π ⎞           ⎛3⋅π⎞
  cos⎜─⎟   sin⎜──⎟        sin⎜───⎟
     ⎝7⎠      ⎝14⎠   1       ⎝ 14⎠
- ────── - ─────── + ── + ────────
    7         7      14      7    

同样,这个表达式消失了,尽管我在 Sympy 中还没有达到这一点。欢迎任何关于如何进行的指示。

首先,对于这种情况最简单的检查是使用近似数值评估:

In [2]: E.evalf()
Out[2]: -0.e-130 - 0.e-132⋅ⅈ

这强烈表明结果为零。

这由 nsimplify 函数内部使用:

In [3]: nsimplify(E)
Out[3]: 0

另一种无需近似即可验证表达式为零的方法是计算其最小多项式:

In [4]: minpoly(E)
Out[4]: x

E 必须是该多项式的根并且它只有一个根(零):

In [5]: roots(_)
Out[5]: {0: 1}

这个表达式对于正常的操作来说似乎特别笨拙,所以许多可能的简化它的方法似乎都不起作用。不过这个确实如此:

In [25]: E.expand().rewrite(cos)
Out[25]: 0

我认为大多数化简方法的主要难点在于三角函数的自动求值:

In [34]: exp(2*I*pi/5).rewrite(cos)
Out[34]: 
                 ________
  1   √5        ╱ √5   5 
- ─ + ── + ⅈ⋅  ╱  ── + ─ 
  4   4      ╲╱   8    8 

如果我们使用符号代替数字,那么我们可以防止:

In [65]: En = E.subs(exp(2*I*pi/5), exp(n*I*pi/5))

In [66]: En.rewrite(cos).simplify().subs(n, 2)
Out[66]: 0