Reputation: 23
I recently encountered a problem with SympPy that I can't fix ; I'm a beginner with the library and I've spent quite some time looking for a solution on the web, without finding one, which is why I came here.
Here's the problem : I have an output from a javascript web app that gives me the expression (x**2)**(1/3)
instead of x**(2/3)
. "No problem", I thought, "SymPy's going to parse that"... except not. If I compare, I get that result:
>>> sympify("(x**2)**(1/3)") == sympify("x**(2/3)")
False
I ran some tests, and I only get that with exponents in sympified expressions. Example:
>>> (x**(1/3))**2 == x**(2/3)
True
Even weirder, if I invert the two exponents, I get a correct result:
>>> sympify("(x**(1/3))**2") == sympify("x**(2/3)")
True
I tried using simplify
and extend
, but it's not working either. The only way I could get a good result is by using eval
, but that requires to first create a symbol "x", which is something I cannot do, because I can't know exactly which symbols are going to be used in the expressions.
So here's the question : is that a bug in SymPy, or am I doing something wrong?
Please excuse me if the issue is well known and I couldn't find anything about it by myself.
Upvotes: 2
Views: 481
Reputation: 91470
As pointed out on the SymPy issue, this is intentional. These two expressions are not equal for general complex x
. Take for instance x = -1
, ((-1)**2)**(1/3) == 1**(1/3) == 1
, whereas (-1)**(2/3) = -1/2 + sqrt(3)/2*I
. See http://docs.sympy.org/0.7.3/tutorial/simplification.html#powers for more information. SymPy will only simplify such exponents if it knows that it is true for the full domain.
In particular, this is true if x
is nonnegative. (x**a)**b == x**(a*b)
is also true if b
is an integer, which is why your other tests worked.
If you want to force simplify this, there are two main options. One (the best option), is to just assume that x
is nonegative, or positive.
>>> x = symbols('x', positive=True)
>>> (x**2)**(S(1)/3)
x**(2/3)
If you want to replace your symbols with positive versions after parsing from a string, you can use posify
:
>>> posify((x**2)**(S(1)/3))
(_x**(2/3), {_x: x})
Or you can use the locals
argument to sympify
to manually set {'x': Symbol('x', positive=True}
.
Another way, if this doesn't fully suit your needs, is to force simplify it with powdenest
:
>>> x = symbols('x') # No assumptions on x
>>> (x**2)**(S(1)/3)
(x**2)**(1/3)
>>> powdenest((x**2)**(S(1)/3), force=True)
x**(2/3)
If you do this, you need to be careful, because you are applying identities that are not always true, so you can end up with mathematically incorrect results.
Upvotes: 1
Reputation: 2082
It's a bug in sympy.
There is not a correct expand for a hierarchy of exponentials (see https://github.com/sympy/sympy/blob/master/sympy/core/power.py#L445)
Upvotes: 0