Search code examples
pythonmathsympy

Sympy roots function creating huge trigonometric expressions


I was trying to find the roots of this equation in python sympy: roots(-64*x**7 + 112*x**5 - 56*x**3 + 7*x) and I set a domain for the answer of this result, getting only one answer that

algebrically corresponds to approx. 0.433883739117558,

is equal to

sqrt(7/12 - (7^(2/3) (1 + i sqrt(3)))/(12 2^(2/3) (-1 + 3 i sqrt(3))^(1/3)) - 1/24 (1 - i sqrt(3)) (7/2 (-1 + 3 i sqrt(3)))^(1/3))

but sympy throws this expression at me:

sqrt(6)*(-56*sqrt(7)*cos(atan(3*sqrt(3))/3)**3 - 56*sqrt(7)*cos(atan(3*sqrt(3))/3)**3*cos(2*atan(3*sqrt(3))/3) - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3)*cos(atan(3*sqrt(3))/3)**2 - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3) - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)**3*sin(2*atan(3*sqrt(3))/3) + 28*sin(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3)**2 + 28*sin(atan(3*sqrt(3))/3)**2*sin(2*atan(3*sqrt(3))/3)**2 + 28*sin(atan(3*sqrt(3))/3)**2 + 56*sin(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3) + 196*sin(atan(3*sqrt(3))/3)**4 + 28*cos(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3)**2 + 28*sin(2*atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3)**2 + 28*cos(atan(3*sqrt(3))/3)**2 + 56*cos(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3) + 392*sin(atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3)**2 + 196*cos(atan(3*sqrt(3))/3)**4)**(1/4)*cos(atan(-2*sqrt(7)*sin(2*atan(3*sqrt(3))/3)*cos(atan(3*sqrt(3))/3)/(-2*sqrt(7)*cos(atan(3*sqrt(3))/3) - 2*sqrt(7)*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3) + 14*sin(atan(3*sqrt(3))/3)**2 + 14*cos(atan(3*sqrt(3))/3)**2) + 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3)/(-2*sqrt(7)*cos(atan(3*sqrt(3))/3) - 2*sqrt(7)*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3) + 14*sin(atan(3*sqrt(3))/3)**2 + 14*cos(atan(3*sqrt(3))/3)**2) + 2*sqrt(7)*sin(atan(3*sqrt(3))/3)/(-2*sqrt(7)*cos(atan(3*sqrt(3))/3) - 2*sqrt(7)*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3) + 14*sin(atan(3*sqrt(3))/3)**2 + 14*cos(atan(3*sqrt(3))/3)**2))/2)/12 + sqrt(6)*I*(-56*sqrt(7)*cos(atan(3*sqrt(3))/3)**3 - 56*sqrt(7)*cos(atan(3*sqrt(3))/3)**3*cos(2*atan(3*sqrt(3))/3) - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3)*cos(atan(3*sqrt(3))/3)**2 - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3) - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 56*sqrt(7)*sin(atan(3*sqrt(3))/3)**3*sin(2*atan(3*sqrt(3))/3) + 28*sin(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3)**2 + 28*sin(atan(3*sqrt(3))/3)**2*sin(2*atan(3*sqrt(3))/3)**2 + 28*sin(atan(3*sqrt(3))/3)**2 + 56*sin(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3) + 196*sin(atan(3*sqrt(3))/3)**4 + 28*cos(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3)**2 + 28*sin(2*atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3)**2 + 28*cos(atan(3*sqrt(3))/3)**2 + 56*cos(atan(3*sqrt(3))/3)**2*cos(2*atan(3*sqrt(3))/3) + 392*sin(atan(3*sqrt(3))/3)**2*cos(atan(3*sqrt(3))/3)**2 + 196*cos(atan(3*sqrt(3))/3)**4)**(1/4)*sin(atan(-2*sqrt(7)*sin(2*atan(3*sqrt(3))/3)*cos(atan(3*sqrt(3))/3)/(-2*sqrt(7)*cos(atan(3*sqrt(3))/3) - 2*sqrt(7)*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3) + 14*sin(atan(3*sqrt(3))/3)**2 + 14*cos(atan(3*sqrt(3))/3)**2) + 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3)/(-2*sqrt(7)*cos(atan(3*sqrt(3))/3) - 2*sqrt(7)*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3) + 14*sin(atan(3*sqrt(3))/3)**2 + 14*cos(atan(3*sqrt(3))/3)**2) + 2*sqrt(7)*sin(atan(3*sqrt(3))/3)/(-2*sqrt(7)*cos(atan(3*sqrt(3))/3) - 2*sqrt(7)*cos(atan(3*sqrt(3))/3)*cos(2*atan(3*sqrt(3))/3) - 2*sqrt(7)*sin(atan(3*sqrt(3))/3)*sin(2*atan(3*sqrt(3))/3) + 14*sin(atan(3*sqrt(3))/3)**2 + 14*cos(atan(3*sqrt(3))/3)**2))/2)/12

Which is correct, but extremely overcomplicated. I tried using symplify(), and other functions, but I couldn't come up with any way to fix this How do I solve this problem?

I also found it to be pretty common for sympy to solve an expression using trigonometric functions, present aswell with -1024*x11 + 2816*x9 - 2816*x7 + 1232*x5 - 220*x**3 + 11*x


Solution

  • You can turn off trig functions with trig=False to get only radical expressions. I tend to think that radical (or radical-trig) expressions are not useful if Cardano's formulae are involved though. It is usually better to avoid using roots since its purpose is to return such expressions (although it could be improved to return simpler expressions). Instead it is usually better to use factorisation and RootOf to represent roots.

    The best way to represent the roots of a polynomial like this is just using RootOf:

    In [23]: p = -64*x**7 + 112*x**5 - 56*x**3 + 7*x
    
    In [24]: for r in real_roots(p): print(r)
    CRootOf(64*x**6 - 112*x**4 + 56*x**2 - 7, 0)
    CRootOf(64*x**6 - 112*x**4 + 56*x**2 - 7, 1)
    CRootOf(64*x**6 - 112*x**4 + 56*x**2 - 7, 2)
    0
    CRootOf(64*x**6 - 112*x**4 + 56*x**2 - 7, 3)
    CRootOf(64*x**6 - 112*x**4 + 56*x**2 - 7, 4)
    CRootOf(64*x**6 - 112*x**4 + 56*x**2 - 7, 5)
    
    In [25]: [r.n(3) for r in real_roots(p)]
    Out[25]: [-0.975, -0.782, -0.434, 0, 0.434, 0.782, 0.975]
    

    You can wrap that up in a number symbol for nicer display e.g.:

    In [34]: a = real_roots(p)[4]
    
    In [35]: a.n()
    Out[35]: 0.433883739117558
    
    In [36]: alpha = AlgebraicNumber(a, alias="alpha")
    
    In [37]: alpha
    Out[37]: α
    
    In [38]: alpha.n()
    Out[38]: 0.433883739117558
    

    For this particular polynomial Q(alpha) is the splitting field so all roots can be found in terms of alpha:

    In [40]: print(p.factor(extension=alpha))
    -64*x*(x - alpha)*(x + alpha)*(x - 3*alpha + 4*alpha**3)*(x - 4*alpha**3 + 3*alpha)*(x - 5*alpha - 16*alpha**5 + 20*alpha**3)*(x - 20*alpha**3 + 16*alpha**5 + 5*alpha)
    
    In [45]: print(p.factor(extension=alpha).n(3))
    -64.0*x*(x - 0.975)*(x - 0.782)*(x - 0.434)*(x + 0.434)*(x + 0.782)*(x + 0.975)
    
    In [50]: print(ground_roots(p, domain=QQ.algebraic_field(alpha)))
    {0: 1, -20*alpha**3 + 16*alpha**5 + 5*alpha: 1, -3*alpha + 4*alpha**3: 1, alpha: 1, -alpha: 1, -4*alpha**3 + 3*alpha: 1, -5*alpha - 16*alpha**5 + 20*alpha**3: 1}