# radical expression for algebraic number

What is the easiest way to turn an algebraic number (i.e. an element of QQbar) into a symbolic expression involving radicals? I know that this is only possible if the degree of the minimal polynomial does not exceed 4, but for those cases I'd have hoped to find an easy solution, but haven't found one yet.

Example of where this would be useful:

sage: M = Matrix([[1,2],[3,4]])
sage: M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring


Simply applying gram_schmidt over ZZ will fail:

sage: M.gram_schmidt(True)
TypeError: QR decomposition unable to compute square roots in Rational Field


Changing to the symbolic ring won't help either:

sage: M.change_ring(SR).gram_schmidt(True)
NotImplementedError: Gram-Scmidt orthogonalization not implemented
for matrices over inexact rings, except for RDF and CDF


Changing to the algebraic numbers lets me compute the matrix, but reading the result is kind of hard.

sage: N = M.change_ring(QQbar).gram_schmidt(True)
sage: N
[ 0.4472135954999580?  0.8944271909999159?]
[ 0.8944271909999159? -0.4472135954999580?]


But all the numbers in there are actually simple square roots, as the minimal polynomials will show.

sage: N.apply_map(lambda x: x.minpoly())
[x^2 - 1/5 x^2 - 4/5]
[x^2 - 4/5 x^2 - 1/5]


So I wrote my own function to convert real algebraic numbers of degree two to symbolic expressions.

sage: def AA2SR(x):
....:     x = AA(x)
....:     p = x.minpoly()
....:     if p.degree() < 2:
....:         return SR(QQ(x))
....:     if p.degree() > 2:
....:         raise TypeError("Cannot handle degrees > 2")
....:     c, b, a = p.coeffs()
....:     y = (-b+sqrt(b*b-4*a*c))/(2*a)
....:     if x == AA(y):
....:         return y
....:     y = (-b-sqrt(b*b-4*a*c))/(2*a)
....:     assert x == AA(y)
....:     return y
....:
sage: M.change_ring(QQbar).gram_schmidt(True).apply_map(AA2SR)
[  sqrt(1/5) 2*sqrt(1/5)]
[2*sqrt(1/5)  -sqrt(1/5)]


But pasting that code into every sage session where I might need it feels rather ugly. I would have hoped that there is some easier way to achieve what I'm doing here. Is there?

edit retag close merge delete

Sort by » oldest newest most voted

If you want the Gram-Schmidt basis you could compute it and then normalize by hand. This is suboptimal though.

sage: M = Matrix([[1,2],[3,4]])
sage: [v.normalized() for v in M.gram_schmidt().rows()]
[(1/5*sqrt(5), 2/5*sqrt(5)), (2*sqrt(1/5), -sqrt(1/5))]

more