Ask Your Question

How to extend ring homomorphism to polynomial ring (or its fraction field)

asked 2016-09-26 07:15:18 -0500

I have a homomorphism from a number field nf to the field of algebraic numbers QQbar:

nf, alpha, hom = QQbar(sqrt(2)).as_number_field_element()

I now work in the polynomial ring R over nf:

R.<x> = nf[]

f = x - alpha; f

How do I get a homomorphism from R to the polynomial ring over QQbar extending hom? For the moment, I can use


Same question about the fraction field of R, e.g.,

g = f/(x+1)

Is there a more elegant way than calling


So basically, I'd like to extend my homomorphism hom to the polynomial ring and its field of fractions.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2016-09-26 11:18:01 -0500

nbruin gravatar image

updated 2016-09-26 15:00:24 -0500

There are some tools to wrap things up a bit. Note that "map_coefficients" might still do funny things with the codomain parent: for instance, in your case I think you end up with polynomials over the Algebraic Real Field rather than QQbar.

   sage: from sage.structure.coerce_maps import CallableConvertMap
   sage: H=CallableConvertMap(RR,QbarX,lambda self,f:QbarX(f.map_coefficients(hom)))

Making a homomorphism between the fields of fractions could be done similarly. I think the tools for this kind of stuff could be made more convenient and/or be documented in a more discoverable way.

In your particular case there might be a shortcut. It's not as general as good tools to naturally extend ring homomorphisms to modules and algebras over these bases. Given that your number field comes from QQbar, it should perhaps be constructed with an embedding into it as well. We can hack our way around that a little bit by registering the embedding ourselves (since this modifies the coercion graph at a node that might already have been used, it could lead to inconsistencies, so we have to take some extra steps to neutralize safety precautions. Furthermore, it modifies the behaviour of a possibly globally unique parent, so it's really a hack at this point. Embeddings should be supplied upon construction, not added later):

sage: nf, alpha, hom = QQbar(sqrt(2)).as_number_field_element()
sage: nf._unset_coercions_used()
sage: nf.register_embedding(hom)
sage: nfX.<x>=nf[]
sage: QbarX.<x>=QQbar[]
sage: 1/nfX.0 - QbarX.0
(-x^2 + 1)/x
sage: parent(1/nfX.0 - QbarX.0)
Fraction Field of Univariate Polynomial Ring in x over Algebraic Field
sage: QbarX.coerce_map_from(nfX)

Ring morphism:
  From: Univariate Polynomial Ring in x over Number Field in a with defining polynomial y^2 - 2
  To:   Univariate Polynomial Ring in x over Algebraic Field
  Defn: Induced from base ring by
        Composite map:
          From: Number Field in a with defining polynomial y^2 - 2
          To:   Algebraic Field
          Defn:   Ring morphism:
                  From: Number Field in a with defining polynomial y^2 - 2
                  To:   Algebraic Real Field
                  Defn: a |--> 1.414213562373095?
                  Conversion map:
                  From: Algebraic Real Field
                  To:   Algebraic Field

Sage does have quite good tools available for discovering/constructing these kinds of induced maps, but unfortunately they are only available for registered coercion maps. It would be great if the same tools would also be usable with an explicitly given, non-standard set of homomorphisms for the construction of new maps.

edit flag offensive delete link more


Thank you, the shortcut was exactly what I need.

Clemens Heuberger gravatar imageClemens Heuberger ( 2016-09-26 22:28:23 -0500 )edit

It worked once, but then my code came accross another example and UniqueRepresentation gave me problems. So I ended up avoiding as_number_field_element alltogether and replacing it by

alpha_qqbar = QQbar(sqrt(2))
nf = NumberField(alpha_qqbar.minpoly(), 'alpha', embedding=alpha_qqbar)
hom = nf.coerce_embedding()
x1 = polygen(nf, 'x')
x2 = polygen(QQbar, 'x')
1/x1 - 1/x2
Clemens Heuberger gravatar imageClemens Heuberger ( 2016-09-27 01:24:43 -0500 )edit

Good example for why we need a to be a little careful with the UniqueRepresentation thing. In this case, I think as_number_field_element can be patched to return the number field as you construct it. Also: the method is called as_*_element, so the first returned value should be the element, not the parent!

nbruin gravatar imagenbruin ( 2016-09-27 09:17:56 -0500 )edit

I now have performance problems with my above solution:

R.<x> = AA[]
v = QQbar.polynomial_root(AA.common_polynomial(x^5 - 2), CIF(RIF(RR(0.35496731310463009), RR(0.35496731310463014)), RIF(RR(1.0924770557774537), RR(1.0924770557774539))))
rho = 1/60*v^4 + 1/30*v^3 + 1/60*v^2 + 1/30*v + 1/15
mp = rho.minpoly()
%time NumberField(mp, 'rho', embedding=rho)
CPU times: user 1min 5s, sys: 64 ms, total: 1min 5s
Wall time: 1min 5s
Number Field in rho with defining polynomial x^5 - 1/3*x^4 + 1/30*x^3 - 1/600*x^2 + 1/24000*x - 1/2400000

Any ideas?

Clemens Heuberger gravatar imageClemens Heuberger ( 2016-10-03 06:59:24 -0500 )edit

I think QQbar is designed to have performance problems, so to a large extent this is a feature. Apparently, there are no attempts to simplify the algebraic data on roots, so your description of "rho" is just horrible. You could improve it by hand:

sage: rho0=[v[0] for v in mp.roots(QQbar) if v[0]==rho][0]
sage: %time NumberField(mp, 'rho', embedding=rho0)
CPU times: user 11.5 ms, sys: 1.06 ms, total: 12.6 ms
Wall time: 11.5 ms
Number Field in rho with defining polynomial x^5 - 1/3*x^4 + 1/30*x^3 - 1/600*x^2 + 1/24000*x - 1/2400000
nbruin gravatar imagenbruin ( 2016-10-07 19:02:33 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools


Asked: 2016-09-26 07:15:18 -0500

Seen: 116 times

Last updated: Sep 26 '16