英文:
Symbolic simplification of algebraic expressions composed of complex numbers
问题
对于表达式 expr1
和 expr2
,您观察到 simplify
函数的输出不同,尽管这两个表达式在代数上是相等的。要使 simplify
对 expr1
和 expr2
的结果相同,您可以使用 powsimp
函数,如下所示:
from sympy import *
expr1 = 3*(2 - 11*I)**Rational(1, 3)*(2 + 11*I)**Rational(2, 3)
expr2 = 3*((2 - 11*I)*(2 + 11*I))**Rational(1, 3)*(2 + 11*I)**Rational(1, 3)
expr1 = powsimp(expr1)
expr2 = powsimp(expr2)
print("expr1 = {0}".format(expr1))
print("expr2 = {0}\n".format(expr2))
print("simplify(expr1) = {0}".format(simplify(expr1)))
print("simplify(expr2) = {0}\n".format(simplify(expr2))
print("expand(expr1) = {0}".format(expand(expr1)))
print("expand(expr2) = {0}\n".format(expand(expr2))
print("expr1.equals(expr2) = {0}".format(expr1.equals(expr2)))
这将使用 powsimp
函数将幂次表达式进行简化,使 expr1
和 expr2
的简化结果相同。
希望这有助于解决您的问题。
英文:
I have a question concerning the symbolic simplification of algebraic expressions composed of complex numbers. I have executed the following Python script:
from sympy import *
expr1 = 3*(2 - 11*I)**Rational(1, 3)*(2 + 11*I)**Rational(2, 3)
expr2 = 3*((2 - 11*I)*(2 + 11*I))**Rational(1, 3)*(2 + 11*I)**Rational(1, 3)
print("expr1 = {0}".format(expr1))
print("expr2 = {0}\n".format(expr2))
print("simplify(expr1) = {0}".format(simplify(expr1)))
print("simplify(expr2) = {0}\n".format(simplify(expr2)))
print("expand(expr1) = {0}".format(expand(expr1)))
print("expand(expr2) = {0}\n".format(expand(expr2)))
print("expr1.equals(expr2) = {0}".format(expr1.equals(expr2)))
The output is:
expr1 = 3*(2 - 11*I)**(1/3)*(2 + 11*I)**(2/3)
expr2 = 3*((2 - 11*I)*(2 + 11*I))**(1/3)*(2 + 11*I)**(1/3)
simplify(expr1) = 3*(2 - 11*I)**(1/3)*(2 + 11*I)**(2/3)
simplify(expr2) = 15*(2 + 11*I)**(1/3)
expand(expr1) = 3*(2 - 11*I)**(1/3)*(2 + 11*I)**(2/3)
expand(expr2) = 15*(2 + 11*I)**(1/3)
expr1.equals(expr2) = True
My questions is why the simplifications does not work for expr1
but
works for expr2
thoug the expressions are algebraically equal.
What has to be done to get the same result from simplify
for expr1
as for expr2
?
Thanks in advance for your replys.
Kind regards
Klaus
答案1
得分: 1
你可以使用最小多项式将代数数放入规范表示:
In [30]: x = symbols('x')
In [31]: p1 = minpoly(expr1, x, polys=True)
In [32]: p2 = minpoly(expr2, x, polys=True)
In [33]: p1
Out[33]: Poly(x**2 - 60*x + 1125, x, domain='QQ')
In [34]: p2
Out[34]: Poly(x**2 - 60*x + 1125, x, domain='QQ')
In [35]: [r for r in p1.all_roots() if p1.same_root(r, expr1)]
Out[35]: [30 + 15⋅ⅈ]
In [36]: [r for r in p2.all_roots() if p2.same_root(r, expr2)]
Out[36]: [30 + 15⋅ⅈ]
这种方法对于通过代数运算表示代数数的任何两个表达式都应该适用:它们要么给出完全相同的结果,要么它们是不同的数。
英文:
You can use the minimal polynomial to place algebraic numbers into a canonical representation:
In [30]: x = symbols('x')
In [31]: p1 = minpoly(expr1, x, polys=True)
In [32]: p2 = minpoly(expr2, x, polys=True)
In [33]: p1
Out[33]: Poly(x**2 - 60*x + 1125, x, domain='QQ')
In [34]: p2
Out[34]: Poly(x**2 - 60*x + 1125, x, domain='QQ')
In [35]: [r for r in p1.all_roots() if p1.same_root(r, expr1)]
Out[35]: [30 + 15⋅ⅈ]
In [36]: [r for r in p2.all_roots() if p2.same_root(r, expr2)]
Out[36]: [30 + 15⋅ⅈ]
This method should work for any two expressions representing algebraic numbers through algebraic operations: either they give the precise same result or they are distinct numbers.
答案2
得分: 0
这段代码中,主要是讨论SymPy库中的根式处理和表达式相等性的问题。以下是其中的翻译部分:
- 对于
expr1
,它在“名义上”有效,因为当在根式中的乘积展开时,得到的立方根为125,而这被报告为5。但SymPy试图谨慎地将根式合并在一个公共指数下,这不是通常有效的操作(例如,root(-1, 3)*root(-1,3) != root(1, 3)
,因为使用了根的主值)。但如果你希望底数在一个公共指数下合并,你可以使用powsimp
强制执行:
from sympy.abc import x, y
from sympy import powsimp, root
powsimp(root(x,3)*root(y,3), force=True)
这将得到 (x*y)**(1/3)
。
- 但这仅在指数相同时有效,如果指数不同,例如:
powsimp(root(x,3)*root(y,3)**2, force=True)
这将得到 x**(1/3)*y**(2/3)
。
-
作者提到了使用
equals
来比较两个表达式是否相同。通过解expr1 - expr2
,可以找到与之相同的表达式。 -
最后,作者使用
numer
、together
、powsimp
和expand
来展示两个表达式相等。最终证明了这两个表达式是相同的。
希望这有助于理解代码中的内容。
英文:
It works (but nominally) for expr1
because when the product in the radical is expanded you get the cube root of 125 which is reported as 5. But SymPy tries to be careful about putting radicals together under a common exponent, an operation that is not generally valid (e.g. root(-1, 3)*root(-1,3) != root(1, 3)
because the principle values are used for the roots. But if you want the bases to combine under a common exponent, you can force it to happen with powsimp
:
>>> from sympy.abc import x, y
>>> from sympy import powsimp, root, solve, numer, together
>>> powsimp(root(x,3)*root(y,3), force=True)
(x*y)**(1/3)
But that only works if the exponents are the same:
>>> powsimp(root(x,3)*root(y,3)**2, force=True)
x**(1/3)*y**(2/3)
As you saw, equals
was able to show that the two expressions were the same. One way this could be done is to solve for root(2 + 11*I, 3)
and see if any of the resulting expression are the same:
>>> solve(expr1 - expr2, root(2 + 11*I,3))
[0, 5/(2 - 11*I)**(1/3)]
We can check the non-zero candidate:
>>> numer(together(_[1]-root(2+11*I,3)))
-(2 - 11*I)**(1/3)*(2 + 11*I)**(1/3) + 5
>>> powsimp(_, force=True)
5 - ((2 - 11*I)*(2 + 11*I))**(1/3)
>>> expand(_)
0
So we have shown (with force) that the expression was the same as that for which we solved. (And, as Oscar showed while I was writing this, minpoly
is a nice candidate when it works: e.g. minpoly(expr1-expr2) -> x
which means expr1 == expr2
.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论