Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Morphisms between number fields
This module provides classes to represent ring homomorphisms between number fields (i.e. field embeddings). """
from sage.misc.cachefunc import cached_method
from sage.rings.homset import RingHomset_generic from sage.rings.morphism import RingHomomorphism_im_gens, RingHomomorphism from sage.rings.integer import Integer from sage.rings.finite_rings.integer_mod_ring import Zmod from sage.structure.sequence import Sequence from sage.structure.richcmp import richcmp
class NumberFieldHomset(RingHomset_generic): """ Set of homomorphisms with domain a given number field.
TESTS::
sage: H = Hom(QuadraticField(-1, 'a'), QuadraticField(-1, 'b')) sage: TestSuite(H).run() Failure in _test_category: ... The following tests failed: _test_elements """ def __init__(self, R, S, category=None): """ TESTS:
Check that :trac:`23647` is fixed::
sage: K.<a, b> = NumberField([x^2 - 2, x^2 - 3]) sage: e, u, v, w = End(K) sage: e.abs_hom().parent().category() Category of homsets of number fields sage: (v*v).abs_hom().parent().category() Category of homsets of number fields """
def __call__(self, im_gens, check=True): """ Create the homomorphism sending the generators to ``im_gens``.
EXAMPLES::
sage: H = Hom(QuadraticField(-1, 'a'), QuadraticField(-1, 'b')) sage: phi = H([H.domain().gen()]); phi # indirect doctest Ring morphism: From: Number Field in a with defining polynomial x^2 + 1 To: Number Field in b with defining polynomial x^2 + 1 Defn: a |--> b """
def _coerce_impl(self, x): r""" Canonical coercion of ``x`` into this homset. The only things that coerce canonically into self are elements of self and of homsets equal to self.
EXAMPLES::
sage: H1 = End(QuadraticField(-1, 'a')) sage: H1.coerce(loads(dumps(H1[1]))) # indirect doctest Ring endomorphism of Number Field in a with defining polynomial x^2 + 1 Defn: a |--> -a
TESTS:
We can move morphisms between categories::
sage: f = H1.an_element() sage: g = End(H1.domain(), category=Rings())(f) sage: f == End(H1.domain(), category=NumberFields())(g) True """ (x.domain() == self.domain() and x.codomain() == self.codomain() and # This would be the better check, however it returns False currently: # self.homset_category().is_full_subcategory(x.category_for()) # So we check instead that this is a morphism anywhere between # Rings and NumberFields where the hom spaces do not change. NumberFields().is_subcategory(self.homset_category()) and self.homset_category().is_subcategory(Rings()) and NumberFields().is_subcategory(x.category_for()) and x.category_for().is_subcategory(Rings()))): raise TypeError
def _an_element_(self): r""" Return an element of this set of embeddings.
EXAMPLES::
sage: H = Hom(QuadraticField(-1, 'a'), QuadraticField(-1, 'b')) sage: H.an_element() # indirect doctest Ring morphism: From: Number Field in a with defining polynomial x^2 + 1 To: Number Field in b with defining polynomial x^2 + 1 Defn: a |--> b
sage: H = Hom(QuadraticField(-1, 'a'), QuadraticField(-2, 'b')) sage: H.an_element() Traceback (most recent call last): ... EmptySetError: There is no morphism from Number Field in a with defining polynomial x^2 + 1 to Number Field in b with defining polynomial x^2 + 2 """ else: self.domain(), self.codomain()))
def _repr_(self): r""" String representation of this homset.
EXAMPLES::
sage: repr(Hom(QuadraticField(-1, 'a'), QuadraticField(-1, 'b'))) # indirect doctest 'Set of field embeddings from Number Field in a with defining polynomial x^2 + 1 to Number Field in b with defining polynomial x^2 + 1' sage: repr(Hom(QuadraticField(-1, 'a'), QuadraticField(-1, 'a'))) # indirect doctest 'Automorphism group of Number Field in a with defining polynomial x^2 + 1' """ else:
def order(self): """ Return the order of this set of field homomorphism.
EXAMPLES::
sage: k.<a> = NumberField(x^2 + 1) sage: End(k) Automorphism group of Number Field in a with defining polynomial x^2 + 1 sage: End(k).order() 2 sage: k.<a> = NumberField(x^3 + 2) sage: End(k).order() 1
sage: K.<a> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: End(K).order() 6 """
cardinality = order
@cached_method def list(self): """ Return a list of all the elements of self.
EXAMPLES::
sage: K.<a> = NumberField(x^3 - 3*x + 1) sage: End(K).list() [ Ring endomorphism of Number Field in a with defining polynomial x^3 - 3*x + 1 Defn: a |--> a, Ring endomorphism of Number Field in a with defining polynomial x^3 - 3*x + 1 Defn: a |--> a^2 - 2, Ring endomorphism of Number Field in a with defining polynomial x^3 - 3*x + 1 Defn: a |--> -a^2 - a + 2 ] sage: Hom(K, CyclotomicField(9))[0] # indirect doctest Ring morphism: From: Number Field in a with defining polynomial x^3 - 3*x + 1 To: Cyclotomic Field of order 9 and degree 6 Defn: a |--> -zeta9^4 + zeta9^2 - zeta9
An example where the codomain is a relative extension::
sage: K.<a> = NumberField(x^3 - 2) sage: L.<b> = K.extension(x^2 + 3) sage: Hom(K, L).list() [ Ring morphism: From: Number Field in a with defining polynomial x^3 - 2 To: Number Field in b with defining polynomial x^2 + 3 over its base field Defn: a |--> a, Ring morphism: From: Number Field in a with defining polynomial x^3 - 2 To: Number Field in b with defining polynomial x^2 + 3 over its base field Defn: a |--> -1/2*a*b - 1/2*a, Ring morphism: From: Number Field in a with defining polynomial x^3 - 2 To: Number Field in b with defining polynomial x^2 + 3 over its base field Defn: a |--> 1/2*a*b - 1/2*a ] """ else: v = []
def __getitem__(self, n): r""" Return the ``n``th element of ``self.list()``.
EXAMPLES::
sage: End(CyclotomicField(37))[3] # indirect doctest Ring endomorphism of Cyclotomic Field of order 37 and degree 36 Defn: zeta37 |--> zeta37^4 """
class NumberFieldHomomorphism_im_gens(RingHomomorphism_im_gens): def __invert__(self): r""" Return the inverse of an isomorphism of absolute number fields
EXAMPLES::
sage: K.<a> = NumberField(x^2 + 5) sage: tau1, tau2 = K.automorphisms(); tau1, tau2 (Ring endomorphism of Number Field in a with defining polynomial x^2 + 5 Defn: a |--> a, Ring endomorphism of Number Field in a with defining polynomial x^2 + 5 Defn: a |--> -a) sage: ~tau1 Ring endomorphism of Number Field in a with defining polynomial x^2 + 5 Defn: a |--> a sage: ~tau2 Ring endomorphism of Number Field in a with defining polynomial x^2 + 5 Defn: a |--> -a
sage: L.<z> = CyclotomicField(5) sage: tau1, tau2, tau3, tau4 = L.automorphisms() sage: (tau1, ~tau1) (Ring endomorphism of Cyclotomic Field of order 5 and degree 4 Defn: z |--> z, Ring endomorphism of Cyclotomic Field of order 5 and degree 4 Defn: z |--> z) sage: (tau2, ~tau2) (Ring endomorphism of Cyclotomic Field of order 5 and degree 4 Defn: z |--> z^2, Ring endomorphism of Cyclotomic Field of order 5 and degree 4 Defn: z |--> z^3) sage: (tau4, ~tau4) (Ring endomorphism of Cyclotomic Field of order 5 and degree 4 Defn: z |--> z^3, Ring endomorphism of Cyclotomic Field of order 5 and degree 4 Defn: z |--> z^2)
sage: M.<w> = NumberField(x^4 - 5*x + 5) sage: phi = M.hom([z - z^2]); phi Ring morphism: From: Number Field in w with defining polynomial x^4 - 5*x + 5 To: Cyclotomic Field of order 5 and degree 4 Defn: w |--> -z^2 + z sage: phi^-1 Ring morphism: From: Cyclotomic Field of order 5 and degree 4 To: Number Field in w with defining polynomial x^4 - 5*x + 5 Defn: z |--> 3/11*w^3 + 4/11*w^2 + 9/11*w - 14/11 """ raise TypeError("Can only invert isomorphisms")
def preimage(self, y): r""" Computes a preimage of `y` in the domain, provided one exists. Raises a ValueError if `y` has no preimage.
INPUT:
- `y` -- an element of the codomain of self.
OUTPUT:
Returns the preimage of `y` in the domain, if one exists. Raises a ValueError if `y` has no preimage.
EXAMPLES::
sage: K.<a> = NumberField(x^2 - 7) sage: L.<b> = NumberField(x^4 - 7) sage: f = K.embeddings(L)[0] sage: f.preimage(3*b^2 - 12/7) 3*a - 12/7 sage: f.preimage(b) Traceback (most recent call last): ... ValueError: Element 'b' is not in the image of this homomorphism.
::
sage: F.<b> = QuadraticField(23) sage: G.<a> = F.extension(x^3+5) sage: f = F.embeddings(G)[0] sage: f.preimage(a^3+2*b+3) 2*b - 2 """ # Throughout this method I am using the convention that self is a homomorphism from the number field K to the number field L # Therefore, I use the names K and L in place of domain and codomain
# try to get the cached transformation matrix and vector space isomorphisms if they exist # get the identifications of K and L with vector spaces over Q # construct the transformation matrix from K to L by making the columns be the image of the basis of V_K in V_L using the homomorphism
# get the coordinate vector of y, solve the linear system, pass to domain
class RelativeNumberFieldHomset(NumberFieldHomset): """ Set of homomorphisms with domain a given relative number field.
EXAMPLES:
We construct a homomorphism from a relative field by giving the image of a generator::
sage: L.<cuberoot2, zeta3> = CyclotomicField(3).extension(x^3 - 2) sage: phi = L.hom([cuberoot2 * zeta3]); phi Relative number field endomorphism of Number Field in cuberoot2 with defining polynomial x^3 - 2 over its base field Defn: cuberoot2 |--> zeta3*cuberoot2 zeta3 |--> zeta3 sage: phi(cuberoot2 + zeta3) zeta3*cuberoot2 + zeta3
In fact, this phi is a generator for the Kummer Galois group of this cyclic extension::
sage: phi(phi(cuberoot2 + zeta3)) (-zeta3 - 1)*cuberoot2 + zeta3 sage: phi(phi(phi(cuberoot2 + zeta3))) cuberoot2 + zeta3 """ def __call__(self, im_gen, base_hom=None, check=True): r""" Create a homomorphism in this homset from the given data, which can be:
- A homomorphism from this number field. - A homomorphism from the absolute number field corresponding to this relative number field. - An element (specifying the image of the generator) of a ring into which the base ring coerces. - A pair consisting of an element of a ring R and a homomorphism from the base ring to R.
EXAMPLES::
sage: K.<a> = NumberField(x^2 + 1) sage: L.<b> = K.extension(x^4 - 2) sage: E = End(L) sage: E(E[0]) # indirect doctest Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field Defn: b |--> b a |--> a sage: E(L.absolute_field('c').hom(b+a, L)) # indirect doctest Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field Defn: b |--> b a |--> -a sage: E(-b*a) # indirect doctest Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field Defn: b |--> -a*b a |--> a sage: E(-a*b, K.hom([-a])) # indirect doctest Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field Defn: b |--> -a*b a |--> -a
Using check=False, it is possible to construct homomorphisms into fields such as CC where calculations are only approximate.
sage: K.<a> = QuadraticField(-7) sage: f = K.hom([CC(sqrt(-7))], check=False) sage: x = polygen(K) sage: L.<b> = K.extension(x^2 - a - 5) sage: L.Hom(CC)(f(a + 5).sqrt(), f, check=False) Relative number field morphism: From: Number Field in b with defining polynomial x^2 - a - 5 over its base field To: Complex Field with 53 bits of precision Defn: b |--> 2.30833860703888 + 0.573085617291335*I a |--> -8.88178419700125e-16 + 2.64575131106459*I """ # Then it must be a homomorphism from the corresponding # absolute number field raise TypeError("domain of morphism must be absolute field of domain.") raise ValueError("domain of absolute homomorphism must be absolute field of domain.") raise ValueError("codomain of absolute homomorphism must be codomain of this homset.")
def _coerce_impl(self, x): r""" Canonically coerce ``x`` into this homset. This will only work if ``x`` is already in the homset.
EXAMPLES::
sage: L.<a, b> = NumberField([x^3 - x + 1, x^2 + 23]) sage: E = End(L) sage: E.coerce(loads(dumps(E[0]))) # indirect doctest Relative number field endomorphism of Number Field in a with defining polynomial x^3 - x + 1 over its base field Defn: a |--> a b |--> b """ raise TypeError if x.parent() == self: return RelativeNumberFieldHomomorphism_from_abs(self, x.abs_hom()) raise TypeError
def _from_im(self, im_gen, base_hom, check=True): """ Return the homomorphism that acts on the base as given and sends the generator of the domain to im_gen.
EXAMPLES::
sage: K.<a> = NumberField(x^2 + 23) sage: L.<b> = K.extension(x^3 - x + 1) sage: End(L)._from_im( -3/23*a*b^2 + (-9/46*a - 1/2)*b + 2/23*a, K.hom([-a], K)) Relative number field endomorphism of Number Field in b with defining polynomial x^3 - x + 1 over its base field Defn: b |--> -3/23*a*b^2 + (-9/46*a - 1/2)*b + 2/23*a a |--> -a """ # We just have to figure out where a goes to # under the morphism defined by im_gen and base_hom.
def default_base_hom(self): r""" Pick an embedding of the base field of self into the codomain of this homset. This is done in an essentially arbitrary way.
EXAMPLES::
sage: L.<a, b> = NumberField([x^3 - x + 1, x^2 + 23]) sage: M.<c> = NumberField(x^4 + 80*x^2 + 36) sage: Hom(L, M).default_base_hom() Ring morphism: From: Number Field in b with defining polynomial x^2 + 23 To: Number Field in c with defining polynomial x^4 + 80*x^2 + 36 Defn: b |--> 1/12*c^3 + 43/6*c """ raise ValueError("no way to map base field to codomain.")
def list(self): """ Return a list of all the elements of self (for which the domain is a relative number field).
EXAMPLES::
sage: K.<a, b> = NumberField([x^2 + x + 1, x^3 + 2]) sage: End(K).list() [ Relative number field endomorphism of Number Field in a with defining polynomial x^2 + x + 1 over its base field Defn: a |--> a b |--> b, ... Relative number field endomorphism of Number Field in a with defining polynomial x^2 + x + 1 over its base field Defn: a |--> a b |--> -b*a - b ]
An example with an absolute codomain::
sage: K.<a, b> = NumberField([x^2 - 3, x^2 + 2]) sage: Hom(K, CyclotomicField(24, 'z')).list() [ Relative number field morphism: From: Number Field in a with defining polynomial x^2 - 3 over its base field To: Cyclotomic Field of order 24 and degree 8 Defn: a |--> z^6 - 2*z^2 b |--> -z^5 - z^3 + z, ... Relative number field morphism: From: Number Field in a with defining polynomial x^2 - 3 over its base field To: Cyclotomic Field of order 24 and degree 8 Defn: a |--> -z^6 + 2*z^2 b |--> z^5 + z^3 - z ] """
class RelativeNumberFieldHomomorphism_from_abs(RingHomomorphism): r""" A homomorphism from a relative number field to some other ring, stored as a homomorphism from the corresponding absolute field. """
def __init__(self, parent, abs_hom): r""" EXAMPLES::
sage: K.<a, b> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: f = K.hom(-a*b - a, K); f Relative number field endomorphism of Number Field in a with defining polynomial x^3 + 2 over its base field Defn: a |--> (-b - 1)*a b |--> b sage: type(f) <class 'sage.rings.number_field.morphism.RelativeNumberFieldHomomorphism_from_abs'> """
def abs_hom(self): r""" Return the corresponding homomorphism from the absolute number field.
EXAMPLES::
sage: K.<a, b> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: K.hom(a, K).abs_hom() Ring morphism: From: Number Field in a with defining polynomial x^6 - 3*x^5 + 6*x^4 - 3*x^3 - 9*x + 9 To: Number Field in a with defining polynomial x^3 + 2 over its base field Defn: a |--> a - b """
def _repr_type(self): r""" A short string to identify the type of this homomorphism.
EXAMPLES::
sage: K.<a, b> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: K.hom(a, K)._repr_type() 'Relative number field' """
def im_gens(self): r""" Return the images of the generators under this map.
EXAMPLES::
sage: K.<a, b> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: K.hom(a, K).im_gens() [a, b] """
def _richcmp_(self, other, op): """ Compare
EXAMPLES::
sage: K.<a, b> = NumberField([x^2 - 2, x^2 - 3]) sage: e, u, v, w = End(K) sage: all([u^2 == e, u*v == w, u != e]) True """
def _repr_defn(self): r""" Return a string describing the images of the generators under this map.
EXAMPLES::
sage: K.<a, b> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: K.hom(a, K)._repr_defn() 'a |--> a\nb |--> b' """ i in range(D.ngens())])
def _call_(self, x): r""" Evaluate this map at the element ``x``. This is done by first converting ``x`` to an element of the absolute field and then evaluating ``self.abs_hom()`` on it.
EXAMPLES::
sage: K.<a, b> = NumberField( [x^3 + 2, x^2 + x + 1] ) sage: K.hom(a*b, K)(17 + 3*a + 2*b) # indirect doctest 3*b*a + 2*b + 17 """
class CyclotomicFieldHomset(NumberFieldHomset): """ Set of homomorphisms with domain a given cyclotomic field.
EXAMPLES::
sage: End(CyclotomicField(16)) Automorphism group of Cyclotomic Field of order 16 and degree 8 """ def __call__(self, im_gens, check=True): """ Create an element of this homset.
EXAMPLES::
sage: K.<z> = CyclotomicField(16) sage: E = End(K) sage: E(E[0]) # indirect doctest Ring endomorphism of Cyclotomic Field of order 16 and degree 8 Defn: z |--> z sage: E(z^5) # indirect doctest Ring endomorphism of Cyclotomic Field of order 16 and degree 8 Defn: z |--> z^5 sage: E(z^6) # indirect doctest Traceback (most recent call last): ... TypeError: images do not define a valid homomorphism """
def _coerce_impl(self, x): r""" Coerce ``x`` into self. This will only work if ``x`` is already in self.
EXAMPLES::
sage: E = End(CyclotomicField(16)) sage: E.coerce(E[0]) # indirect doctest Ring endomorphism of Cyclotomic Field of order 16 and degree 8 Defn: zeta16 |--> zeta16 sage: E.coerce(17) # indirect doctest Traceback (most recent call last): ... TypeError: no canonical coercion from Integer Ring to Automorphism group of Cyclotomic Field of order 16 and degree 8 """ if x.parent() == self: return CyclotomicFieldHomomorphism_im_gens(self, x.im_gens()) raise TypeError
def list(self): """ Return a list of all the elements of self (for which the domain is a cyclotomic field).
EXAMPLES::
sage: K.<z> = CyclotomicField(12) sage: G = End(K); G Automorphism group of Cyclotomic Field of order 12 and degree 4 sage: [g(z) for g in G] [z, z^3 - z, -z, -z^3 + z] sage: L.<a, b> = NumberField([x^2 + x + 1, x^4 + 1]) sage: L Number Field in a with defining polynomial x^2 + x + 1 over its base field sage: Hom(CyclotomicField(12), L)[3] Ring morphism: From: Cyclotomic Field of order 12 and degree 4 To: Number Field in a with defining polynomial x^2 + x + 1 over its base field Defn: zeta12 |--> -b^2*a sage: list(Hom(CyclotomicField(5), K)) [] sage: Hom(CyclotomicField(11), L).list() [] """
else: else:
class CyclotomicFieldHomomorphism_im_gens(NumberFieldHomomorphism_im_gens): pass |