# checking whether the polynomial has a rational root

Hello there,

I have a polynomial $f$ which has all its roots purely imaginary, that is, if $f(z)=0$, then $z=ix$ for some real number $x$. I'm using the following command to check all the roots.

f.roots(ring=CC)

Now I define $g(x) = f(ix)$. Then, all the roots of $g(x)$ are real. I want to print only the rational roots of $g$. So I tried:

g.roots(ring=QQ)

But I'm getting the following error:

Unable to coerce I to a rational

How to fix this?

edit retag close merge delete

1

Try

[x for x in g.roots() if x in QQ]

1

@the 1diot : do not use CC, which is a(pseudo-)ring of numerical approximations to complexes (and therefore "inexact"), but QQbar, representation of agorithms allowing to compute an algebraic number to arbitrary precision, and therefore considered as an "exact" representation of algebraics. Contemplate :

sage: CC
Complex Field with 53 bits of precision
sage: CC.is_exact()
False
sage: QQbar
Algebraic Field
sage: QQbar.is_exact()
True


@achresz : you should transform your comment in an answer, that the Idiot can accept, in order to mark this question as answered for the benefit of future ask.sagemath.org(per-)users...

Since in the question f(x) and g(x) are not defined I can't check if my "answer" is correct.

@achrzesz : you can illustrate your answer with an example, without attempting to solve the 1diot's problem :

sage: f(x) = ((x-I)^2*(x-sqrt(2)*I)*(x-3/2*I)^3).expand() ; f(x)
x^6 - I*sqrt(2)*x^5 - 13/2*I*x^5 - 13/2*sqrt(2)*x^4 - 67/4*x^4 + 67/4*I*sqrt(2)*x^3 + 171/8*I*x^3 + 171/8*sqrt(2)*x^2 + 27/2*x^2 - 27/2*I*sqrt(2)*x - 27/8*I*x - 27/8*sqrt(2)
sage: g(x)=f(I*x) ; g
x |--> -x^6 + sqrt(2)*x^5 + 13/2*x^5 - 13/2*sqrt(2)*x^4 - 67/4*x^4 + 67/4*sqrt(2)*x^3 + 171/8*x^3 - 171/8*sqrt(2)*x^2 - 27/2*x^2 + 27/2*sqrt(2)*x + 27/8*x - 27/8*sqrt(2 ...
(more)

Sort by » oldest newest most voted

Here is the "same" answer, using a ring of polynomials. So the pythonic variable x below is representing the indeterminate of a polynomial ring $R$. We have to introduce this polynomial, in my case the ring of coefficients is $\Bbb Q$, the ring of rational numbers, but also other (exact) rings may be used. So $R=\Bbb Q[x]$. We ask sage to give us all roots of a sample polynomial $f$, these live in $\bar{\Bbb Q}$, check which ones are in $i\Bbb Q$ among them, and print them. (If $f$ has all roots in $i\Bbb Q$, we show them all.)

Our sample polynomial is: \begin{aligned} f &= 4 \, x^{12} + 4 \, x^{11} + 33 \, x^{10} + 49 \, x^{9} + 138 \, x^{8} + 254 \, x^{7} \\ &+ 473 \, x^{6} + 689 \, x^{5} + 971 \, x^{4} + 912 \, x^{3} + 859 \, x^{2} + 432 \, x + 252 \ . \end{aligned} The code declares $R=\Bbb Q[x]$, and $f$ first,

R.<x> = PolynomialRing(QQ)    # or simply QQ[]
f = ( 4*x^12 + 4*x^11 + 33*x^10 + 49*x^9 + 138*x^8 + 254*x^7
+ 473*x^6 + 689*x^5 + 971*x^4 + 912*x^3 + 859*x^2 + 432*x + 252 )


and asks for the roots with real part zero, and imaginary part in QQ$=\Bbb Q$:

for r in f.roots(ring=QQbar, multiplicities=False):
if r.real() == 0 and r.imag() in QQ:
print(f'Found root r = {r} with rational imaginary part {QQ(r/i)}')


Results:

Found root r = -2*I with rational imaginary part -2
Found root r = -1.5000000000000000?*I with rational imaginary part -3/2
Found root r = -1*I with rational imaginary part -1
Found root r = 1*I with rational imaginary part 1
Found root r = 1.5000000000000000?*I with rational imaginary part 3/2
Found root r = 2*I with rational imaginary part 2


In this approach, the step of passing from $f$ to $g$ is no longer needed. But can be done. We could introduce $\Bbb Q(j)$, $j=\sqrt{-1}$, instead of $\Bbb Q$ as the base field for the coefficients. And while computing the roots we can ask directly for the roots in this ring. For instance:

K.<j> = QuadraticField(-1)    # so j is sqrt(-1)
RK.<X> = PolynomialRing(K)    # or simply K[]
g = f(j*X)


Then:

sage: [ r for r in g.roots(multiplicities=False) if r in QQ ]
[2, 3/2, 1, -1, -3/2, -2]
sage: [ r for r in f.roots(ring=K, multiplicities=False) if r*j in QQ ]
[2*j, 3/2*j, j, -j, -3/2*j, -2*j]

more

z=var('z')
f=(z-1/2*I)*(z-pi*I)*(z-sqrt(2)*I)
g=f(z=z*I)
[x for x in g.roots() if x in QQ]


[1/2]

more