如何简化 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
在我正在处理的一个项目中,我正在处理包含复指数的表达式,例如下面的表达式,我的目标是尽可能简化它:
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