How to simplify an expression for a complex constant using sympy?
Asked Answered
I

2

9

I have done some calculations in sympy, and the result is in the end a set of constants. One of them is inserted directly into the snippet below:

from sympy import *
expr = (18**(Rational(1, 3))/(6*(3 + sqrt(3)*I)**(Rational(1, 3)))
        + 12**(Rational(1, 3))*(3 + sqrt(3)*I)**(Rational(1, 3))/12)
print(expr.evalf())
print(expr.simplify())

This returns

0.56857902130163 + 0.e-22*I
18**(1/3)/(6*(3 + sqrt(3)*I)**(1/3)) + (36 + 12*sqrt(3)*I)**(1/3)/12

so the expression appears to be a real number, yet sympy cannot simplify it further. With pen and paper, I have simplified this to

cos(pi/18) / sqrt(3)

which agrees with the numerical value returned by evalf().

I have tried many of the different simplification functions, but none seem to be able to reduce the expression any further. Using substitutions like

expr.subs(3 + sqrt(3)*I, sqrt(12) * exp(I*pi/6))

improves the expression, but still sympy is unable to conclude that it is real. Using Euler's formula for substitution,

expr.subs(3 + sqrt(3)*I, sqrt(12) * (cos(pi/6) + I*sin(pi/6)))

sympy is finally able to conclude that the expression is real, but the expression itself explodes in size when printed (even if I attempt simplify after the substitution).

Is there a better way to try to reduce this? I have many similar expressions for complex constants that I would like to know for sure are real (or not).

Initiatory answered 20/8, 2015 at 7:30 Comment(0)
V
5

For the expression you gave, the command

(expr.conjugate().conjugate() - expr.conjugate()).simplify()

returns 0, which signifies that expr is real. (Double application of conjugation returns to the original value, but it gets expanded along the way, which enables subsequent simplification.) In general, the above formula returns the imaginary part multiplied by 2i.

To find the real part of the expression, you can use a similar trick: add it to its conjugate and simplify (and divide by 2):

((expr.conjugate().conjugate()+expr.conjugate())/2).simplify()

returns sqrt(3)*cos(pi/18)/3.

Visit answered 21/8, 2015 at 5:22 Comment(1)
This works well for the expression I gave as an example. Even simpler is expr.conjugate().conjugate().simplify().trigsimp(), which manages to output the result directly. However, for more complicated expressions this conjugate method does not work all that well, but it's still useful.Initiatory
A
5

The method as_real_imag often helps to simplify a complex number, even though it's not listed among the Simplification methods. In your example,

expr.as_real_imag()

returns (sqrt(3)*cos(pi/18)/3, 0)

If a complex number is desired (rather than a tuple as above), one should not just call complex on this tuple, since this would create an object of Python complex class, involving numeric evaluation. Instead, I'd write

pair = expr.as_real_imag()
result = pair[0] + pair[1]*I
Assignat answered 25/12, 2016 at 21:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.