Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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)[0]
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)[0]
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)[0]
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)[0].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?

click to hide/show revision 2
Rewrapped to avoid scroll bars

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)[0]
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)[0]
NotImplementedError: Gram-Scmidt orthogonalization not implemented implemented
for matrices
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)[0]
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)[0].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?