Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Choice of the name of primitive elements for subfields of QQbar #36749

Merged
merged 9 commits into from
Dec 14, 2023
57 changes: 34 additions & 23 deletions src/sage/rings/qqbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2504,7 +2504,10 @@ def conjugate_shrink(v):
return v.real()
return v

def number_field_elements_from_algebraics(numbers, minimal=False, same_field=False, embedded=False, prec=53):

def number_field_elements_from_algebraics(numbers, minimal=False,
same_field=False,
embedded=False, name='a', prec=53):
r"""
Given a sequence of elements of either ``AA`` or ``QQbar``
(or a mixture), computes a number field containing all of these
Expand All @@ -2514,18 +2517,20 @@ def number_field_elements_from_algebraics(numbers, minimal=False, same_field=Fal

INPUT:

- ``numbers`` -- a number or list of numbers.
- ``numbers`` -- a number or list of numbers

- ``minimal`` -- Boolean (default: ``False``). Whether to minimize the
degree of the extension.
degree of the extension

- ``same_field`` -- Boolean (default: ``False``). See below.
- ``same_field`` -- Boolean (default: ``False``). See below

- ``embedded`` -- Boolean (default: ``False``). Whether to make the
NumberField embedded.
NumberField embedded

- ``name`` -- string (default: ``'a'``); name of the primitive element

- ``prec`` -- integer (default: ``53``). The number of bit of precision
to guarantee finding real roots.
to guarantee finding real roots

OUTPUT:

Expand Down Expand Up @@ -2559,12 +2564,12 @@ def number_field_elements_from_algebraics(numbers, minimal=False, same_field=Fal
sage: x = polygen(QQ)
sage: p = x^3 + x^2 + x + 17
sage: rts = p.roots(ring=QQbar, multiplicities=False)
sage: splitting = number_field_elements_from_algebraics(rts)[0]; splitting
Number Field in a with defining polynomial y^6 - 40*y^4 - 22*y^3 + 873*y^2 + 1386*y + 594
sage: splitting = number_field_elements_from_algebraics(rts, name='b')[0]; splitting
Number Field in b with defining polynomial y^6 - 40*y^4 - 22*y^3 + 873*y^2 + 1386*y + 594
sage: p.roots(ring=splitting)
[(361/29286*a^5 - 19/3254*a^4 - 14359/29286*a^3 + 401/29286*a^2 + 18183/1627*a + 15930/1627, 1),
(49/117144*a^5 - 179/39048*a^4 - 3247/117144*a^3 + 22553/117144*a^2 + 1744/4881*a - 17195/6508, 1),
(-1493/117144*a^5 + 407/39048*a^4 + 60683/117144*a^3 - 24157/117144*a^2 - 56293/4881*a - 53033/6508, 1)]
[(361/29286*b^5 - 19/3254*b^4 - 14359/29286*b^3 + 401/29286*b^2 + 18183/1627*b + 15930/1627, 1),
(49/117144*b^5 - 179/39048*b^4 - 3247/117144*b^3 + 22553/117144*b^2 + 1744/4881*b - 17195/6508, 1),
(-1493/117144*b^5 + 407/39048*b^4 + 60683/117144*b^3 - 24157/117144*b^2 - 56293/4881*b - 53033/6508, 1)]

sage: # needs sage.symbolic
sage: rt2 = AA(sqrt(2)); rt2
Expand Down Expand Up @@ -2840,7 +2845,7 @@ def mk_algebraic(x):
# the number comes from a complex algebraic number field
embedded_rt = v.interval_fast(RealIntervalField(prec))
root = ANRoot(v.minpoly(), embedded_rt)
real_nf = NumberField(v.minpoly(),'a')
real_nf = NumberField(v.minpoly(), 'a')
new_ef = AlgebraicGenerator(real_nf, root)
real_numbers += [new_ef.root_as_algebraic()]
else:
Expand All @@ -2851,7 +2856,7 @@ def mk_algebraic(x):
for v in numbers:
if minimal:
v.simplify()
gen = gen.union(v._exact_field())
gen = gen.union(v._exact_field(), name=name)

fld = gen._field
nums = [gen(v._exact_value()) for v in numbers]
Expand All @@ -2861,7 +2866,7 @@ def mk_algebraic(x):

if fld is not QQ and embedded:
# creates the embedded field
embedded_field = NumberField(fld.defining_polynomial(),fld.variable_name(),embedding=exact_generator)
embedded_field = NumberField(fld.defining_polynomial(), fld.variable_name(), embedding=exact_generator)

# embeds the numbers
inter_hom = fld.hom([embedded_field.gen(0)])
Expand Down Expand Up @@ -3145,8 +3150,8 @@ def _repr_(self):
if self._trivial:
return 'Trivial generator'
else:
return '%s with a in %s' % (self._field,
self._root._interval_fast(53))
return '%s with %s in %s' % (self._field, self._field.gen(),
self._root._interval_fast(53))

def root_as_algebraic(self):
r"""
Expand Down Expand Up @@ -3265,11 +3270,17 @@ def _interval_fast(self, prec):
"""
return self._root._interval_fast(prec)

def union(self, other):
r""" Given generators ``alpha`` and ``beta``,
``alpha.union(beta)`` gives a generator for the number field
def union(self, other, name='a'):
r"""
Given generators ``self``, `\alpha`, and ``other``, `\beta`,
``self.union(other)`` gives a generator for the number field
`\QQ[\alpha][\beta]`.

INPUT:

- ``other`` -- an algebraic number
- ``name`` -- string (default: ``'a'``); a name for the primitive element

EXAMPLES::

sage: from sage.rings.qqbar import ANRoot, AlgebraicGenerator, qq_generator
Expand All @@ -3289,8 +3300,8 @@ def union(self, other):
True
sage: qq_generator.union(gen3) is gen3
True
sage: gen2.union(gen3)
Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a in -1.931851652578137?
sage: gen2.union(gen3, name='b')
Number Field in b with defining polynomial y^4 - 4*y^2 + 1 with b in -1.931851652578137?
"""
if self._trivial:
return other
Expand Down Expand Up @@ -3340,7 +3351,7 @@ def find_fn(p, prec):

red_back_x = QQx(red_back)

new_nf = NumberField(red_pol, name='a', check=False)
new_nf = NumberField(red_pol, name=name, check=False)

self_pol_sage = QQx(self_pol.lift())

Expand Down Expand Up @@ -8780,7 +8791,7 @@ def _init_qqbar():
EXAMPLES::

sage: sage.rings.qqbar.QQbar_I_generator # indirect doctest
Number Field in I with defining polynomial x^2 + 1 with I = 1*I with a in 1*I
Number Field in I with defining polynomial x^2 + 1 with I = 1*I with I in 1*I
"""
global ZZX_x, AA_0, QQbar_I, AA_hash_offset, QQbar_hash_offset, QQbar_I_generator, QQbar_I_nf
global QQ_0, QQ_1, QQ_1_2, QQ_1_4, RR_1_10
Expand Down
Loading