-Selmer groups of number fields¶
This file contains code to compute
is a number field is a finite set of primes of is a prime number
For
where
The main function here is pSelmerGroup(). This will not
normally be used by users, who instead will access it through a method
of the NumberField class.
AUTHORS:
John Cremona (2005-2021)
- sage.rings.number_field.selmer_group.basis_for_p_cokernel(S, C, p)[source]¶
Return a basis for the group of ideals supported on
S(mod -th-powers) whose class in the class groupCis a -th power, together with a function which takes theS-exponents of such an ideal and returns its coordinates on this basis.INPUT:
S– list of prime ideals in a number fieldKC– (class group) the ideal class group ofKp– prime number
OUTPUT:
(tuple) (
b,f) wherebis a list of ideals which is a basis for the group of ideals supported onS(modulo -th powers) whose ideal class is a -th power;fis a function which takes such an ideal and returns its coordinates with respect to this basis.
EXAMPLES:
sage: from sage.rings.number_field.selmer_group import basis_for_p_cokernel sage: x = polygen(ZZ, 'x') sage: K.<a> = NumberField(x^2 - x + 58) sage: S = K.ideal(30).support(); S [Fractional ideal (2, a), Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (5, a + 1), Fractional ideal (5, a + 3)] sage: C = K.class_group() sage: C.gens_orders() (6, 2) sage: [C(P).exponents() for P in S] [(5, 0), (1, 0), (3, 1), (1, 1), (5, 1)] sage: b, f = basis_for_p_cokernel(S, C, 2); b [Fractional ideal (2), Fractional ideal (15, a + 13), Fractional ideal (5)] sage: b, f = basis_for_p_cokernel(S, C, 3); b [Fractional ideal (50, a + 18), Fractional ideal (10, a + 3), Fractional ideal (3, a + 1), Fractional ideal (5)] sage: b, f = basis_for_p_cokernel(S, C, 5); b [Fractional ideal (2, a), Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (5, a + 1), Fractional ideal (5, a + 3)]
>>> from sage.all import * >>> from sage.rings.number_field.selmer_group import basis_for_p_cokernel >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(2) - x + Integer(58), names=('a',)); (a,) = K._first_ngens(1) >>> S = K.ideal(Integer(30)).support(); S [Fractional ideal (2, a), Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (5, a + 1), Fractional ideal (5, a + 3)] >>> C = K.class_group() >>> C.gens_orders() (6, 2) >>> [C(P).exponents() for P in S] [(5, 0), (1, 0), (3, 1), (1, 1), (5, 1)] >>> b, f = basis_for_p_cokernel(S, C, Integer(2)); b [Fractional ideal (2), Fractional ideal (15, a + 13), Fractional ideal (5)] >>> b, f = basis_for_p_cokernel(S, C, Integer(3)); b [Fractional ideal (50, a + 18), Fractional ideal (10, a + 3), Fractional ideal (3, a + 1), Fractional ideal (5)] >>> b, f = basis_for_p_cokernel(S, C, Integer(5)); b [Fractional ideal (2, a), Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (5, a + 1), Fractional ideal (5, a + 3)]
from sage.rings.number_field.selmer_group import basis_for_p_cokernel x = polygen(ZZ, 'x') K.<a> = NumberField(x^2 - x + 58) S = K.ideal(30).support(); S C = K.class_group() C.gens_orders() [C(P).exponents() for P in S] b, f = basis_for_p_cokernel(S, C, 2); b b, f = basis_for_p_cokernel(S, C, 3); b b, f = basis_for_p_cokernel(S, C, 5); b
- sage.rings.number_field.selmer_group.coords_in_U_mod_p(u, U, p)[source]¶
Return coordinates of a unit
uwith respect to a basis of the -cotorsion of the unit groupU.INPUT:
u– (algebraic unit) a unit in a number fieldKU– (unit group) the unit group ofKp– prime number
OUTPUT:
The coordinates of the unit
in the -cotorsion group .ALGORITHM:
Take the coordinate vector of
with respect to the generators of the unit group, drop the coordinate of the roots of unity factor if it is prime to , and reduce the vector mod .EXAMPLES:
sage: from sage.rings.number_field.selmer_group import coords_in_U_mod_p sage: x = polygen(ZZ, 'x') sage: K.<a> = NumberField(x^4 - 5*x^2 + 1) sage: U = K.unit_group() sage: U Unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial x^4 - 5*x^2 + 1 sage: u0, u1, u2, u3 = U.gens_values() sage: u = u1*u2^2*u3^3 sage: coords_in_U_mod_p(u,U,2) [0, 1, 0, 1] sage: coords_in_U_mod_p(u,U,3) [1, 2, 0] sage: u*=u0 sage: coords_in_U_mod_p(u,U,2) [1, 1, 0, 1] sage: coords_in_U_mod_p(u,U,3) [1, 2, 0]
>>> from sage.all import * >>> from sage.rings.number_field.selmer_group import coords_in_U_mod_p >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(4) - Integer(5)*x**Integer(2) + Integer(1), names=('a',)); (a,) = K._first_ngens(1) >>> U = K.unit_group() >>> U Unit group with structure C2 x Z x Z x Z of Number Field in a with defining polynomial x^4 - 5*x^2 + 1 >>> u0, u1, u2, u3 = U.gens_values() >>> u = u1*u2**Integer(2)*u3**Integer(3) >>> coords_in_U_mod_p(u,U,Integer(2)) [0, 1, 0, 1] >>> coords_in_U_mod_p(u,U,Integer(3)) [1, 2, 0] >>> u*=u0 >>> coords_in_U_mod_p(u,U,Integer(2)) [1, 1, 0, 1] >>> coords_in_U_mod_p(u,U,Integer(3)) [1, 2, 0]
from sage.rings.number_field.selmer_group import coords_in_U_mod_p x = polygen(ZZ, 'x') K.<a> = NumberField(x^4 - 5*x^2 + 1) U = K.unit_group() U u0, u1, u2, u3 = U.gens_values() u = u1*u2^2*u3^3 coords_in_U_mod_p(u,U,2) coords_in_U_mod_p(u,U,3) u*=u0 coords_in_U_mod_p(u,U,2) coords_in_U_mod_p(u,U,3)
- sage.rings.number_field.selmer_group.pSelmerGroup(K, S, p, proof=None, debug=False)[source]¶
Return the
-Selmer group of the number field with respect to the prime ideals inS.INPUT:
K– a number field orS– list of prime ideals in , or prime numbers when isp– a prime numberproof– ifTrue, compute the class group provably correctly. Default isTrue. Callproof.number_field()to change this default globally.debug– boolean (default:False); debug flag
OUTPUT:
(tuple)
KSp,KSp_gens,from_KSp,to_KSpwhereKSpis an abstract vector space over isomorphic to ;KSp_gensis a list of elements of generating ;from_KSpis a function fromKSpto implementing the isomorphism from the abstract to as a subgroup of ;to_KSPis a partial function from toKSp, defined on elements whose image in lies in , mapping them via the inverse isomorphism to the abstract vector spaceKSp.
ALGORITHM:
The list of generators of
is the concatenation of three sublists, calledalphalist,betalistandulistin the code. Onlyalphalistdepends on the primes in .ulistis a basis for where is the unit group. This is the list of fundamental units, including the generator of the group of roots of unity if its order is divisible by . These have valuation at all primes.betalistis a list of the generators of the -th powers of ideals which generate the -torsion in the class group (so is empty if the class number is prime to ). These have valuation divisible by at all primes.alphalistis a list of generators for each ideal in a basis of those ideals supported on (modulo -th powers of ideals) which are -th powers in the class group. We find such that is principal and take a generator of it, for each in a generating set. As a special case, if all the ideals in are principal thenalphalistis a list of their generators.
The map from the abstract space to
is easy: we just take the product of the generators to powers given by the coefficient vector. No attempt is made to reduce the resulting product modulo -th powers.The reverse map is more complicated. Given
:write the principal ideal
in the form with supported by and -th power free. If this fails, then does not represent an element of and an error is raised.set
to be the group of ideals spanned by mod -th powers, and the subgroup of which maps to in .Convert
to an element of , hence find the coordinates of with respect to the generators inalphalist.after dividing out by
, now (with a different and ). Write the ideal class , whose -th power is trivial, in terms of the generators of ; then , where the coefficients of with respect to generators of give the coordinates of the result with respect to the generators inbetalist.after dividing out by
, and by , we now have , so is a unit, which can be expressed in terms of the unit generators.
EXAMPLES:
Over
the unit contribution is trivial unless and the class group is trivial:sage: from sage.rings.number_field.selmer_group import pSelmerGroup sage: QS2, gens, fromQS2, toQS2 = pSelmerGroup(QQ, [2,3], 2) sage: QS2 Vector space of dimension 3 over Finite Field of size 2 sage: gens [2, 3, -1] sage: a = fromQS2([1,1,1]); a.factor() -1 * 2 * 3 sage: toQS2(-6) (1, 1, 1) sage: QS3, gens, fromQS3, toQS3 = pSelmerGroup(QQ, [2,13], 3) sage: QS3 Vector space of dimension 2 over Finite Field of size 3 sage: gens [2, 13] sage: a = fromQS3([5,4]); a.factor() 2^5 * 13^4 sage: toQS3(a) (2, 1) sage: toQS3(a) == QS3([5,4]) True
>>> from sage.all import * >>> from sage.rings.number_field.selmer_group import pSelmerGroup >>> QS2, gens, fromQS2, toQS2 = pSelmerGroup(QQ, [Integer(2),Integer(3)], Integer(2)) >>> QS2 Vector space of dimension 3 over Finite Field of size 2 >>> gens [2, 3, -1] >>> a = fromQS2([Integer(1),Integer(1),Integer(1)]); a.factor() -1 * 2 * 3 >>> toQS2(-Integer(6)) (1, 1, 1) >>> QS3, gens, fromQS3, toQS3 = pSelmerGroup(QQ, [Integer(2),Integer(13)], Integer(3)) >>> QS3 Vector space of dimension 2 over Finite Field of size 3 >>> gens [2, 13] >>> a = fromQS3([Integer(5),Integer(4)]); a.factor() 2^5 * 13^4 >>> toQS3(a) (2, 1) >>> toQS3(a) == QS3([Integer(5),Integer(4)]) True
from sage.rings.number_field.selmer_group import pSelmerGroup QS2, gens, fromQS2, toQS2 = pSelmerGroup(QQ, [2,3], 2) QS2 gens a = fromQS2([1,1,1]); a.factor() toQS2(-6) QS3, gens, fromQS3, toQS3 = pSelmerGroup(QQ, [2,13], 3) QS3 gens a = fromQS3([5,4]); a.factor() toQS3(a) toQS3(a) == QS3([5,4])
A real quadratic field with class number 2, where the fundamental unit is a generator, and the class group provides another generator when
:sage: K.<a> = QuadraticField(-5) sage: K.class_number() 2 sage: P2 = K.ideal(2, -a+1) sage: P3 = K.ideal(3, a+1) sage: P5 = K.ideal(a) sage: KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, [P2, P3, P5], 2) sage: KS2 Vector space of dimension 4 over Finite Field of size 2 sage: gens [a + 1, a, 2, -1]
>>> from sage.all import * >>> K = QuadraticField(-Integer(5), names=('a',)); (a,) = K._first_ngens(1) >>> K.class_number() 2 >>> P2 = K.ideal(Integer(2), -a+Integer(1)) >>> P3 = K.ideal(Integer(3), a+Integer(1)) >>> P5 = K.ideal(a) >>> KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, [P2, P3, P5], Integer(2)) >>> KS2 Vector space of dimension 4 over Finite Field of size 2 >>> gens [a + 1, a, 2, -1]
K.<a> = QuadraticField(-5) K.class_number() P2 = K.ideal(2, -a+1) P3 = K.ideal(3, a+1) P5 = K.ideal(a) KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, [P2, P3, P5], 2) KS2 gens
Each generator must have even valuation at primes not in
:sage: [K.ideal(g).factor() for g in gens] [(Fractional ideal (2, a + 1)) * (Fractional ideal (3, a + 1)), Fractional ideal (-a), (Fractional ideal (2, a + 1))^2, 1] sage: toKS2(10) (0, 0, 1, 1) sage: fromKS2([0,0,1,1]) -2 sage: K(10/(-2)).is_square() True sage: KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, [P2, P3, P5], 3) sage: KS3 Vector space of dimension 3 over Finite Field of size 3 sage: gens [1/2, 1/4*a + 1/4, a]
>>> from sage.all import * >>> [K.ideal(g).factor() for g in gens] [(Fractional ideal (2, a + 1)) * (Fractional ideal (3, a + 1)), Fractional ideal (-a), (Fractional ideal (2, a + 1))^2, 1] >>> toKS2(Integer(10)) (0, 0, 1, 1) >>> fromKS2([Integer(0),Integer(0),Integer(1),Integer(1)]) -2 >>> K(Integer(10)/(-Integer(2))).is_square() True >>> KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, [P2, P3, P5], Integer(3)) >>> KS3 Vector space of dimension 3 over Finite Field of size 3 >>> gens [1/2, 1/4*a + 1/4, a]
[K.ideal(g).factor() for g in gens] toKS2(10) fromKS2([0,0,1,1]) K(10/(-2)).is_square() KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, [P2, P3, P5], 3) KS3 gens
The
toandfrommaps are inverses of each other:sage: K.<a> = QuadraticField(-5) sage: S = K.ideal(30).support() sage: KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, S, 2) sage: KS2 Vector space of dimension 5 over Finite Field of size 2 sage: assert all(toKS2(fromKS2(v))==v for v in KS2) sage: KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, S, 3) sage: KS3 Vector space of dimension 4 over Finite Field of size 3 sage: assert all(toKS3(fromKS3(v))==v for v in KS3)
>>> from sage.all import * >>> K = QuadraticField(-Integer(5), names=('a',)); (a,) = K._first_ngens(1) >>> S = K.ideal(Integer(30)).support() >>> KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, S, Integer(2)) >>> KS2 Vector space of dimension 5 over Finite Field of size 2 >>> assert all(toKS2(fromKS2(v))==v for v in KS2) >>> KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, S, Integer(3)) >>> KS3 Vector space of dimension 4 over Finite Field of size 3 >>> assert all(toKS3(fromKS3(v))==v for v in KS3)
K.<a> = QuadraticField(-5) S = K.ideal(30).support() KS2, gens, fromKS2, toKS2 = pSelmerGroup(K, S, 2) KS2 assert all(toKS2(fromKS2(v))==v for v in KS2) KS3, gens, fromKS3, toKS3 = pSelmerGroup(K, S, 3) KS3 assert all(toKS3(fromKS3(v))==v for v in KS3)