Module: sage.modular.congroup
Congruence subgroups of SL2(Z)
Sage can compute with the congruence subgroups
,
, and
.
Author: William Stein
Module-level Functions
level, H) |
Return the congruence subgroup
.
Input:
sage: GammaH(11,0) Congruence Subgroup Gamma0(11) sage: GammaH(11,1) Congruence Subgroup Gamma1(11) sage: GammaH(11,[2]) Congruence Subgroup Gamma_H(11) with H generated by [2] sage: GammaH(11,[2,1]) Congruence Subgroup Gamma_H(11) with H generated by [2]
order) |
order) |
x) |
Return True if x is of type CongruenceSubgroup.
sage: is_CongruenceSubgroup(SL2Z) True sage: is_CongruenceSubgroup(Gamma0(13)) True sage: is_CongruenceSubgroup(Gamma1(6)) True sage: is_CongruenceSubgroup(GammaH(11, [3])) True sage: is_CongruenceSubgroup(SymmetricGroup(3)) False
x) |
Return True if x is a congruence subgroup of type Gamma0.
sage: is_Gamma0(SL2Z) True sage: is_Gamma0(Gamma0(13)) True sage: is_Gamma0(Gamma1(6)) False
x) |
Return True if x is a congruence subgroup of type Gamma1.
sage: is_Gamma1(SL2Z) True sage: is_Gamma1(Gamma1(13)) True sage: is_Gamma1(Gamma0(6)) False
x) |
Return True if x is a congruence subgroup of type GammaH.
sage: is_GammaH(GammaH(13, [2])) True sage: is_GammaH(Gamma0(6)) False
x) |
Return True if x is the modular group
.
sage: is_SL2Z(SL2Z) True sage: is_SL2Z(Gamma0(6)) False
c, d, N) |
If this Manin symbol is (c,d) viewed modulo N, this function computes and returns a list [a, b, c', d'] that defines a 2x2 matrix with determinant 1 and integer entries, such that c=c'(mod N) and d=d'(mod N).
sage: lift_to_sl2z(1, 0, 12) [0, -1, 1, 0] sage: lift_to_sl2z(29, 100, 7) [9, 31, 29, 100] sage: lift_to_sl2z(5, 10, 3) [2, 5, 5, 13] sage: lift_to_sl2z(1000, 10000, 10000) [0, -1, 1000, 20000]
Class: CongruenceSubgroup
self, level) |
Functions: are_equivalent,
coset_reps,
gen,
generators,
gens,
is_abelian,
is_even,
is_finite,
is_odd,
is_subgroup,
level,
modular_abelian_variety,
modular_symbols,
ngens,
order
self, x, y) |
Determine whether
and
are equivalent by an element of
self, i.e. whether or not there exists an element
of self
such that
.
NOTE: This function must be overridden by all subclasses.
self) |
Return coset representatives for this congruence subgroup.
NOTE: This function must be overridden by all subclasses.
self, i) |
Return the i-th generator of self, i.e. the i-th element of the tuple self.gens().
sage: SL2Z.gen(1) [1 1] [0 1] sage: Gamma0(20).gen(7) [17 11] [20 13] sage: Gamma1(16).gen(5) [ 1329 -758] [ 3056 -1743] sage: GammaH(13, [8]).gen(3) [ 885 -218] [1157 -285]
self) |
Return generators for this congruence subgroup.
NOTE: This function must be overridden by all subclasses.
self) |
Return tuple of generators for this congruence subgroup.
The generators need not be minimal.
sage: SL2Z.gens() ([ 0 -1] [ 1 0], [1 1] [0 1]) sage: Gamma0(3).gens() ([1 1] [0 1], [-1 0] [ 0 -1], [ 1 -1] [ 0 1], [ 1 -1] [ 3 -2], [ 2 -1] [ 3 -1], [-2 1] [-3 1]) sage: Gamma1(2).gens() ([1 1] [0 1], [-1 0] [ 0 -1], [ 1 -1] [ 0 1], [ 1 -1] [ 2 -1], [-1 1] [-2 1]) sage: GammaH(3, [2]).gens() ([1 1] [0 1], [-1 0] [ 0 -1], [ 1 -1] [ 0 1], [ 1 -1] [ 3 -2], [ 2 -1] [ 3 -1], [-2 1] [-3 1])
self) |
Return True if this congruence subgroup is abelian.
Since congruence subgroups are always nonabelian, this always returns False.
sage: SL2Z.is_abelian() False sage: Gamma0(3).is_abelian() False sage: Gamma1(12).is_abelian() False sage: GammaH(4, [2]).is_abelian() False
self) |
Return True precisely if this subgroup contains the matrix -1.
sage: SL2Z.is_even() True sage: Gamma0(20).is_even() True sage: Gamma1(5).is_even() False sage: GammaH(11, [3]).is_even() False
self) |
Return True if this congruence subgroup is finite.
Since congruence subgroups are always infinite, this always returns False.
sage: SL2Z.is_finite() False sage: Gamma0(3).is_finite() False sage: Gamma1(12).is_finite() False sage: GammaH(4, [2]).is_finite() False
self) |
Return True precisely if this subgroup does not contain the matrix -1.
sage: SL2Z.is_odd() False sage: Gamma0(20).is_odd() False sage: Gamma1(5).is_odd() True sage: GammaH(11, [3]).is_odd() True
self) |
Return the level of this congruence subgroup.
sage: SL2Z.level() 1 sage: Gamma0(20).level() 20 sage: Gamma1(11).level() 11 sage: GammaH(14, [2]).level() 14
self) |
Return the modular abelian variety corresponding to the congruence subgroup self.
sage: Gamma0(11).modular_abelian_variety() Abelian variety J0(11) of dimension 1 sage: Gamma1(11).modular_abelian_variety() Abelian variety J1(11) of dimension 1 sage: GammaH(11,[3]).modular_abelian_variety() Abelian variety JH(11,[3]) of dimension 1
self, [sign=0], [weight=2], [base_ring=Rational Field]) |
Return the space of modular symbols of the specified weight and sign on the congruence subgroup self.
sage: G = Gamma0(23) sage: G.modular_symbols() Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Rational Field sage: G.modular_symbols(weight=4) Modular Symbols space of dimension 12 for Gamma_0(23) of weight 4 with sign 0 over Rational Field sage: G.modular_symbols(base_ring=GF(7)) Modular Symbols space of dimension 5 for Gamma_0(23) of weight 2 with sign 0 over Finite Field of size 7 sage: G.modular_symbols(sign=1) Modular Symbols space of dimension 3 for Gamma_0(23) of weight 2 with sign 1 over Rational Field
self) |
Return the number of generators for this congruence subgroup.
This need not be the minimal number of generators of self.
sage: Gamma0(22).ngens() 42 sage: Gamma1(14).ngens() 250 sage: GammaH(11, [3]).ngens() 31 sage: SL2Z.ngens() 2
self) |
Return the number of elements in this congruence subgroup.
Since congruence subgroups are always infinite, this always returns infinity.
sage: SL2Z.order() +Infinity sage: Gamma0(5).order() +Infinity sage: Gamma1(2).order() +Infinity sage: GammaH(12, [5]).order() +Infinity
Special Functions: __call__,
__cmp__,
__init__,
_new_group_from_level,
_repr_
self, level) |
Return a new group of the same type (Gamma0, Gamma1, or GammaH)
as self of the given level. In the case that self is of type
GammaH, we take the largest H inside
which maps to H, namely its inverse image under the natural map.
sage: G = Gamma0(20) sage: G._new_group_from_level(4) Congruence Subgroup Gamma0(4) sage: G._new_group_from_level(40) Congruence Subgroup Gamma0(40)
sage: G = Gamma1(10) sage: G._new_group_from_level(6) Traceback (most recent call last): ... ValueError: one level must divide the other
sage: G = GammaH(50,[3,37]) sage: G Congruence Subgroup Gamma_H(50) with H generated by [3, 37] sage: G._new_group_from_level(25) Congruence Subgroup Gamma_H(25) with H generated by [3, 12] sage: G._new_group_from_level(100) Congruence Subgroup Gamma_H(100) with H generated by [3, 37, 53, 87]
Class: Gamma0
sage: G = Gamma0(11); G Congruence Subgroup Gamma0(11) sage: loads(G.dumps()) == G True
self, level) |
Functions: coset_reps,
gamma_h_subgroups,
generators,
is_even,
is_subgroup
self) |
Return representatives for the right cosets of this
congruence subgroup in
as a generator.
Use list(self.coset_reps())
to obtain coset reps as a
list.
sage: list(Gamma0(5).coset_reps()) [[1, 0, 0, 1], [0, -1, 1, 0], [1, 0, 1, 1], [1, 1, 1, 2], [1, 2, 1, 3], [1, 3, 1, 4]] sage: list(Gamma0(4).coset_reps()) [[1, 0, 0, 1], [0, -1, 1, 0], [1, 0, 1, 1], [1, 1, 1, 2], [1, 2, 1, 3], [-1, -1, 2, 1]] sage: list(Gamma0(1).coset_reps()) [[1, 0, 0, 1]]
self) |
Return the subgroups of the form
contained
in self, where
is the level of self.
sage: G = Gamma0(11) sage: G.gamma_h_subgroups() [Congruence Subgroup Gamma_H(11) with H generated by [2], Congruence Subgroup Gamma_H(11) with H generated by [4], Congruence Subgroup Gamma_H(11) with H generated by [10], Congruence Subgroup Gamma_H(11) with H generated by []] sage: G = Gamma0(12) sage: G.gamma_h_subgroups() [Congruence Subgroup Gamma_H(12) with H generated by [5, 7], Congruence Subgroup Gamma_H(12) with H generated by [7], Congruence Subgroup Gamma_H(12) with H generated by [5], Congruence Subgroup Gamma_H(12) with H generated by []]
self) |
Return generators for this congruence subgroup.
The result is cached.
sage: for g in Gamma0(3).generators(): ... print g ... print '---' [1 1] [0 1] --- [-1 0] [ 0 -1] --- ... --- [-2 1] [-3 1] ---
self) |
Return True precisely if this subgroup contains the matrix -1.
Since Gamma0(N) always, contains the matrix -1, this always returns True.
sage: Gamma0(12).is_even() True sage: SL2Z.is_even() True
self, right) |
Return True if self is a subgroup of right.
sage: G = Gamma0(20) sage: G.is_subgroup(SL2Z) True sage: G.is_subgroup(Gamma0(4)) True sage: G.is_subgroup(Gamma0(20)) True sage: G.is_subgroup(Gamma0(7)) False sage: Gamma0(2).is_subgroup(Gamma1(2)) True
Special Functions: __call__,
__cmp__,
__init__,
_generators_for_H,
_latex_,
_list_of_elements_in_H,
_repr_
self, x, [check=True]) |
Create an element of this congruence subgroup from x.
If the optional flag check is True (default), check whether x actually gives an element of self.
sage: G = Gamma0(12) sage: G([1, 0, 24, 1]) [ 1 0] [24 1] sage: G(matrix(ZZ, 2, [1, 1, -12, -11])) [ 1 1] [-12 -11] sage: G([1, 0, 23, 1]) Traceback (most recent call last): ... TypeError: matrix must have lower left entry (=23) divisible by 12
self) |
sage: Gamma0(15)._generators_for_H() [11, 7]
self) |
sage: Gamma0(20)._latex_() '\Gamma_0(20)' sage: latex(Gamma0(20)) \Gamma_0(20)
self) |
Returns a sorted list of Python ints that are representatives between 0 and N-1 of the elements of H.
sage: G = Gamma0(11) sage: G._list_of_elements_in_H() [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Class: Gamma1
sage: G = Gamma1(11); G Congruence Subgroup Gamma1(11) sage: loads(G.dumps()) == G True
self, level) |
Functions: generators,
is_even,
is_subgroup
self) |
Return generators for this congruence subgroup.
The result is cached.
sage: for g in Gamma1(3).generators(): ... print g ... print '---' [1 1] [0 1] --- [ 31 -14] [ 51 -23] --- [-5 4] [-9 7] --- ... --- [4 3] [9 7] --- [ -5 -2] [-12 -5] ---
self) |
Return True precisely if this subgroup contains the matrix -1.
sage: Gamma1(1).is_even() True sage: Gamma1(2).is_even() True sage: Gamma1(15).is_even() False
self, right) |
Return True if self is a subgroup of right.
sage: Gamma1(3).is_subgroup(SL2Z) True sage: Gamma1(3).is_subgroup(Gamma1(5)) False sage: Gamma1(3).is_subgroup(Gamma1(6)) False sage: Gamma1(6).is_subgroup(Gamma1(3)) True sage: Gamma1(6).is_subgroup(Gamma0(2)) True
Special Functions: __call__,
__cmp__,
__init__,
_latex_,
_repr_
self, x, [check=True]) |
Create an element of this congruence subgroup from x.
If the optional flag check is True (default), check whether x actually gives an element of self.
sage: G = Gamma1(5) sage: G([1, 0, -10, 1]) [ 1 0] [-10 1] sage: G(matrix(ZZ, 2, [6, 1, 5, 1])) [6 1] [5 1] sage: G([1, 1, 6, 7]) Traceback (most recent call last): ... TypeError: matrix must have diagonal entries (=1, 7) congruent to 1 modulo 5, and lower left entry (=6) divisible by 5
self) |
sage: Gamma1(3)._latex_() '\Gamma_1(3)' sage: latex(Gamma1(3)) \Gamma_1(3)
Class: GammaH_class
self, level, H) |
Functions: divisor_subgroups,
generators,
is_even,
restrict
self) |
Given this congruence subgroup
, return all
subgroups
for
a divisor of
and such that
is equal to the image of
modulo
.
sage: G = GammaH(33,[2]); G Congruence Subgroup Gamma_H(33) with H generated by [2] sage: G._list_of_elements_in_H() [1, 2, 4, 8, 16, 17, 25, 29, 31, 32] sage: G.divisor_subgroups() [Congruence Subgroup Gamma_H(1) with H generated by [], Congruence Subgroup Gamma_H(3) with H generated by [2], Congruence Subgroup Gamma_H(11) with H generated by [2], Congruence Subgroup Gamma_H(33) with H generated by [2]]
self) |
Return generators for this congruence subgroup.
The result is cached.
sage: for g in GammaH(3, [2]).generators(): ... print g ... print '---' [1 1] [0 1] --- [-1 0] [ 0 -1] --- [ 1 -1] [ 0 1] --- [ 1 -1] [ 3 -2] --- [ 2 -1] [ 3 -1] --- [-2 1] [-3 1] ---
self) |
Return True precisely if this subgroup contains the matrix -1.
sage: GammaH(10, [3]).is_even() True sage: GammaH(14, [1]).is_even() False
self, M) |
Return the subgroup of
obtained by taking
to
be the image of the
at level
modulo
.
sage: G = GammaH(33,[2]) sage: G.restrict(11) Congruence Subgroup Gamma_H(11) with H generated by [2] sage: G.restrict(1) Congruence Subgroup Gamma_H(1) with H generated by [] sage: G.restrict(15) Traceback (most recent call last): ... ValueError: M (=15) must be a divisor of the level (33) of self
Special Functions: __call__,
__cmp__,
__init__,
_coset_reduction_data,
_coset_reduction_data_first_coord,
_coset_reduction_data_second_coord,
_generators_for_H,
_latex_,
_list_of_elements_in_H,
_reduce_coset,
_reduce_cusp,
_repr_
self, x, [check=True]) |
Create an element of this congruence subgroup from x.
If the optional flag check is True (default), check whether x actually gives an element of self.
sage: G = GammaH(10, [3]) sage: G([1, 0, -10, 1]) [ 1 0] [-10 1] sage: G(matrix(ZZ, 2, [7, 1, 20, 3])) [ 7 1] [20 3] sage: GammaH(10, [9])([7, 1, 20, 3]) Traceback (most recent call last): ... TypeError: matrix must have lower right entry (=3) congruent modulo 10 to some element of H
self) |
Compute data used for determining the canonical coset representative of an element of SL_2(Z) modulo G.
sage: G = GammaH(12,[-1,7]); G Congruence Subgroup Gamma_H(12) with H generated by [-1, 7] sage: G._coset_reduction_data() ([(0, 12, 0), (1, 1, 1), (2, 2, 1), (3, 3, 1), (4, 4, 1), (1, 1, 5), (6, 6, 1), (1, 1, 7), (4, 4, 5), (3, 3, 7), (2, 2, 5), (1, 1, 11)], {1: [1], 2: [1, 7], 3: [1, 5], 4: [1, 7], 6: [1, 5, 7, 11], 12: [1, 5, 7, 11]})
G) |
Compute data used for determining the canonical coset representative of an element of SL_2(Z) modulo G. This function specifically returns data needed for the first part of the reduction step (the first coordinate).
Input:
sage: G = GammaH(12,[-1,5]); G Congruence Subgroup Gamma_H(12) with H generated by [-1, 5] sage: G._coset_reduction_data_first_coord() [(0, 12, 0), (1, 1, 1), (2, 2, 1), (3, 3, 1), (4, 4, 1), (1, 1, 5), (6, 6, 1), (1, 1, 7), (4, 4, 5), (3, 3, 7), (2, 2, 5), (1, 1, 11)]
G) |
Compute data used for determining the canonical coset representative of an element of SL_2(Z) modulo G. This function specifically returns data needed for the second part of the reduction step (the second coordinate).
Input: self
Output: a dictionary v with keys the divisors of N such that v[d] is the subgroup h in H : h = 1 (mod N/d).
sage: G = GammaH(240,[7,239]) sage: print G._coset_reduction_data_second_coord() {1: [1], 2: [1], 3: [1], 4: [1], 5: [1, 49], 6: [1], 48: [1, 191], 8: [1], 80: [1, 7, 49, 103], 10: [1, 49], 12: [1], 15: [1, 49], 240: [1, 7, 49, 103, 137, 191, 233, 239], 40: [1, 7, 49, 103], 20: [1, 49], 24: [1, 191], 120: [1, 7, 49, 103, 137, 191, 233, 239], 60: [1, 49, 137, 233], 30: [1, 49, 137, 233], 16: [1]} sage: G = GammaH(1200,[-1,7]); G Congruence Subgroup Gamma_H(1200) with H generated by [-1, 7] sage: K = G._coset_reduction_data_second_coord().keys() ; K.sort() sage: K == divisors(1200) True
self) |
Returns a sorted list of Python ints that are representatives between 1 and N-1 of the elements of H.
WARNING: Do not change this returned list.
sage: G = GammaH(11,[3]); G Congruence Subgroup Gamma_H(11) with H generated by [3] sage: G._list_of_elements_in_H() [1, 3, 4, 5, 9]
self, uu, vv) |
Compute a canonical form for a given Manin symbol.
Input:
Two integers (uu,vv) that define an element of
.
NOTE: We do *not* require that gcd(uu,vv,N) = 1. If the gcd is not 1, we return (0,0).
An example at level 9.
sage: G = GammaH(9,[7]); G Congruence Subgroup Gamma_H(9) with H generated by [7] sage: a = [] sage: for i in range(G.level()): ... for j in range(G.level()): ... a.append(G._reduce_coset(i,j)) sage: v = list(set(a)) sage: v.sort() sage: v [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (3, 1), (3, 2), (6, 1), (6, 2)]
An example at level 100.
sage: G = GammaH(100,[3,7]); G Congruence Subgroup Gamma_H(100) with H generated by [3, 7] sage: a = [] sage: for i in range(G.level()): ... for j in range(G.level()): ... a.append(G._reduce_coset(i,j)) sage: v = list(set(a)) sage: v.sort() sage: len(v) 361
self, c) |
Compute a minimal representative for the given cusp c. Returns a pair (c', t), where c' is the minimal representative for the given cusp, and t is either 1 or -1, as explained below.
The minimal representative for a cusp is the element in
in lowest terms with minimal denominator, and minimal
numerator for that denominator.
Two cusps
and
are equivalent modulo
if and only if
and
or
and
for some
. Then t is 1 or -1 as c and c' fall into
the first or second case, respectively.
sage: GammaH(6,[5])._reduce_cusp(Cusp(5,3)) (1/3, -1) sage: GammaH(12,[5])._reduce_cusp(Cusp(8,9)) (1/3, -1) sage: GammaH(12,[5])._reduce_cusp(Cusp(5,12)) (Infinity, 1) sage: GammaH(12,[])._reduce_cusp(Cusp(5,12)) (5/12, 1) sage: GammaH(21,[5])._reduce_cusp(Cusp(-9/14)) (1/7, 1)
Class: SL2Z_class
sage: G = SL2Z; G Modular Group SL(2,Z) sage: G.gens() ([ 0 -1] [ 1 0], [1 1] [0 1]) sage: G.0 [ 0 -1] [ 1 0] sage: G.1 [1 1] [0 1] sage: latex(G) \mbox{\rm SL}_2(\mathbf{Z}) sage: G([1,-1,0,1]) [ 1 -1] [ 0 1] sage: loads(G.dumps()) == G True sage: SL2Z.0 * SL2Z.1 [ 0 -1] [ 1 1]
self) |
Functions: is_subgroup
self, right) |
Return True if self is a subgroup of right.
sage: SL2Z.is_subgroup(SL2Z) True sage: SL2Z.is_subgroup(Gamma1(1)) True sage: SL2Z.is_subgroup(Gamma0(6)) False
Special Functions: __init__,
_latex_,
_repr_
self) |
sage: SL2Z._latex_() '\mbox{\rm SL}_2(\mathbf{Z})' sage: latex(SL2Z) \mbox{ m SL}_2(\mathbf{Z})