From ffa1e99aa944fb14c7a297a467b5d83f97bcc25b Mon Sep 17 00:00:00 2001 From: Brent Baccala Date: Wed, 16 May 2018 20:09:50 -0400 Subject: [PATCH] Trac #25377: add 'same_field' option to number_field_elements_from_algebraics() --- src/sage/rings/qqbar.py | 51 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index cdb2388b312..07c011c3510 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -1924,7 +1924,7 @@ def conjugate_shrink(v): return v.real() return v -def number_field_elements_from_algebraics(numbers, minimal=False): +def number_field_elements_from_algebraics(numbers, minimal=False, same_field=False): r""" Given a sequence of elements of either ``AA`` or ``QQbar`` (or a mixture), computes a number field containing all of these @@ -1935,6 +1935,13 @@ def number_field_elements_from_algebraics(numbers, minimal=False): This may not return the smallest such number field, unless ``minimal=True`` is specified. + If ``same_field=True`` is specified, and all of the elements are + from the same field (either ``AA`` or ``QQbar``), the generated + homomorphism will map back to that field. Otherwise, if all specified + elements are real, the homomorphism might map back to ``AA`` + (and will, if ``minimal=True`` is specified), even if the + elements were in ``QQbar``. + Also, a single number can be passed, rather than a sequence; and any values which are not elements of ``AA`` or ``QQbar`` will automatically be coerced to ``QQbar`` @@ -1960,6 +1967,8 @@ def number_field_elements_from_algebraics(numbers, minimal=False): 1.414213562373095? sage: rt3 = AA(sqrt(3)); rt3 1.732050807568878? + sage: rt3a = QQbar(sqrt(3)); rt3a + 1.732050807568878? sage: qqI = QQbar.zeta(4); qqI I sage: z3 = QQbar.zeta(3); z3 @@ -1981,6 +1990,22 @@ def number_field_elements_from_algebraics(numbers, minimal=False): To: Algebraic Real Field Defn: a |--> 0.5176380902050415?) + ``rt3a`` is a real number in ``QQbar``. Ordinarily, we'd get a homomorphism + to ``AA`` (because all elements are real), but if we specify ``same_field=True``, + we'll get a homomorphism back to ``QQbar``:: + + sage: number_field_elements_from_algebraics(rt3a) + (Number Field in a with defining polynomial y^2 - 3, a, Ring morphism: + From: Number Field in a with defining polynomial y^2 - 3 + To: Algebraic Real Field + Defn: a |--> 1.732050807568878?) + + sage: number_field_elements_from_algebraics(rt3a, same_field=True) + (Number Field in a with defining polynomial y^2 - 3, a, Ring morphism: + From: Number Field in a with defining polynomial y^2 - 3 + To: Algebraic Field + Defn: a |--> 1.732050807568878?) + We've created ``rt2b`` in such a way that \sage doesn't initially know that it's in a degree-2 extension of `\QQ`:: @@ -2059,9 +2084,12 @@ def number_field_elements_from_algebraics(numbers, minimal=False): Note that for the first example, where \sage doesn't realize that the number is real, we get a homomorphism to ``QQbar``; but with - ``minimal=True``, we get a homomorphism to ``AA``. Also note - that the exact answer depends on a Pari function that gives - different answers for 32-bit and 64-bit machines:: + ``minimal=True``, we get a homomorphism to ``AA``. If we specify + both ``minimal=True`` and ``same_field=True``, we get a second + degree extension (minimal) that maps back to ``QQbar``. + + Also note that the exact answer depends on a Pari function that + gives different answers for 32-bit and 64-bit machines:: sage: number_field_elements_from_algebraics(rt2c) (Number Field in a with defining polynomial y^4 + 2*y^2 + 4, 1/2*a^3, Ring morphism: @@ -2073,6 +2101,11 @@ def number_field_elements_from_algebraics(numbers, minimal=False): From: Number Field in a with defining polynomial y^2 - 2 To: Algebraic Real Field Defn: a |--> 1.414213562373095?) + sage: number_field_elements_from_algebraics(rt2c, minimal=True, same_field=True) + (Number Field in a with defining polynomial y^2 - 2, a, Ring morphism: + From: Number Field in a with defining polynomial y^2 - 2 + To: Algebraic Field + Defn: a |--> 1.414213562373095?) """ gen = qq_generator @@ -2085,6 +2118,11 @@ def number_field_elements_from_algebraics(numbers, minimal=False): numbers = [numbers] single_number = True + if any([isinstance(_, AlgebraicNumber) for _ in numbers]): + algebraic_field = QQbar + else: + algebraic_field = AA + def mk_algebraic(x): if isinstance(x, AlgebraicNumber_base): return x @@ -2104,7 +2142,10 @@ def mk_algebraic(x): if single_number: nums = nums[0] - hom = fld.hom([gen.root_as_algebraic()]) + if same_field: + hom = fld.hom([gen.root_as_algebraic()], codomain=algebraic_field) + else: + hom = fld.hom([gen.root_as_algebraic()]) return (fld, nums, hom)