Manin Relations for overconvergent modular symbols¶
Code to create the Manin Relations class, which solves the “Manin relations”. That is, a description of \(Div^0(P^1(\QQ))\) as a \(\ZZ[\Gamma_0(N)]\)module in terms of generators and relations is found. The method used is geometric, constructing a nice fundamental domain for \(\Gamma_0(N)\) and reading the relevant Manin relations off of that picture. The algorithm follows [PS2011].
AUTHORS:
 Robert Pollack, Jonathan Hanke (2012): initial version

sage.modular.pollack_stevens.fund_domain.
M2Z
(x)¶ Create an immutable \(2 \times 2\) integer matrix from
x
.INPUT: anything that can be converted into a \(2 \times 2\) matrix.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import M2Z sage: M2Z([1,2,3,4]) [1 2] [3 4] sage: M2Z(1) [1 0] [0 1]

class
sage.modular.pollack_stevens.fund_domain.
ManinRelations
(N)¶ Bases:
sage.modular.pollack_stevens.fund_domain.PollackStevensModularDomain
This class gives a description of \(Div^0(P^1(\QQ))\) as a \(\ZZ[\Gamma_0(N)]\)module.
INPUT:
N
– a positive integer, the level of \(\Gamma_0(N)\) to work with
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: ManinRelations(1) Manin Relations of level 1 sage: ManinRelations(11) Manin Relations of level 11
Large values of
N
are not supported:sage: ManinRelations(2^20) Traceback (most recent call last): ... OverflowError: Modulus is too large (must be <= 46340)

fd_boundary
(C)¶ Find matrices whose associated unimodular paths give the boundary of a fundamental domain.
Here the fundamental domain is for \(\Gamma_0(N)\). (In the case when \(\Gamma_0(N)\) has elements of order three the shape cut out by these unimodular matrices is a little smaller than a fundamental domain. See Section 2.5 of [PS2011].)
INPUT:
C
– a list of rational numbers coming fromself.form_list_of_cusps()
OUTPUT:
A list of \(2 \times 2\) integer matrices of determinant 1 whose associated unimodular paths give the boundary of a fundamental domain for \(\Gamma_0(N)\) (or nearly so in the case of 3torsion).
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: C = A.form_list_of_cusps(); C [1, 2/3, 1/2, 1/3, 0] sage: A.fd_boundary(C) [ [1 0] [ 1 1] [ 0 1] [1 1] [1 2] [2 1] [0 1], [1 0], [ 1 3], [ 3 2], [ 2 3], [ 3 1] ] sage: A = ManinRelations(13) sage: C = A.form_list_of_cusps(); C [1, 2/3, 1/2, 1/3, 0] sage: A.fd_boundary(C) [ [1 0] [ 1 1] [ 0 1] [1 1] [1 2] [2 1] [0 1], [1 0], [ 1 3], [ 3 2], [ 2 3], [ 3 1] ] sage: A = ManinRelations(101) sage: C = A.form_list_of_cusps(); C [1, 6/7, 5/6, 4/5, 7/9, 3/4, 11/15, 8/11, 5/7, 7/10, 9/13, 2/3, 5/8, 13/21, 8/13, 3/5, 7/12, 11/19, 4/7, 1/2, 4/9, 3/7, 5/12, 7/17, 2/5, 3/8, 4/11, 1/3, 2/7, 3/11, 1/4, 2/9, 1/5, 1/6, 0] sage: A.fd_boundary(C) [ [1 0] [ 1 1] [ 0 1] [1 1] [1 2] [2 1] [1 3] [3 2] [0 1], [1 0], [ 1 6], [ 6 5], [ 5 9], [ 9 4], [ 4 11], [11 7], [2 1] [1 4] [4 3] [3 2] [2 7] [7 5] [5 3] [3 4] [ 7 3], [ 3 11], [11 8], [ 8 5], [ 5 17], [17 12], [12 7], [ 7 9], [4 1] [1 4] [ 4 11] [11 7] [7 3] [3 8] [ 8 13] [ 9 2], [ 2 7], [ 7 19], [ 19 12], [12 5], [ 5 13], [ 13 21], [13 5] [5 2] [2 9] [9 7] [7 5] [5 8] [ 8 11] [ 21 8], [ 8 3], [ 3 13], [13 10], [10 7], [ 7 11], [ 11 15], [11 3] [3 7] [7 4] [4 5] [5 6] [6 1] [ 15 4], [ 4 9], [ 9 5], [ 5 6], [ 6 7], [ 7 1] ]

form_list_of_cusps
()¶ Return the intersection of a fundamental domain for \(\Gamma_0(N)\) with the real axis.
The construction of this fundamental domain follows the arguments of [PS2011] Section 2. The boundary of this fundamental domain consists entirely of unimodular paths when \(\Gamma_0(N)\) has no elements of order 3. (See [PS2011] Section 2.5 for the case when there are elements of order 3.)
OUTPUT:
A sorted list of rational numbers marking the intersection of a fundamental domain for \(\Gamma_0(N)\) with the real axis.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.form_list_of_cusps() [1, 2/3, 1/2, 1/3, 0] sage: A = ManinRelations(13) sage: A.form_list_of_cusps() [1, 2/3, 1/2, 1/3, 0] sage: A = ManinRelations(101) sage: A.form_list_of_cusps() [1, 6/7, 5/6, 4/5, 7/9, 3/4, 11/15, 8/11, 5/7, 7/10, 9/13, 2/3, 5/8, 13/21, 8/13, 3/5, 7/12, 11/19, 4/7, 1/2, 4/9, 3/7, 5/12, 7/17, 2/5, 3/8, 4/11, 1/3, 2/7, 3/11, 1/4, 2/9, 1/5, 1/6, 0]

indices_with_three_torsion
()¶ A list of indices of coset representatives whose associated unimodular path contains a point fixed by a \(\Gamma_0(N)\) element of order 3 in the ideal triangle directly below that path (the order is computed in \(PSL_2(\ZZ)\)).
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(11) sage: MR.indices_with_three_torsion() [] sage: MR = ManinRelations(13) sage: MR.indices_with_three_torsion() [2, 5] sage: B = MR.reps(2); B [ 0 1] [ 1 3]
The corresponding matrix of order three:
sage: A = MR.three_torsion_matrix(B); A [4 1] [13 3] sage: A^3 [1 0] [0 1]
The columns of
B
and the columns ofA*B
andA^2*B
give the same rational cusps:sage: B [ 0 1] [ 1 3] sage: A*B, A^2*B ( [1 1] [ 1 0] [ 3 4], [4 1] )

indices_with_two_torsion
()¶ Return the indices of coset representatives whose associated unimodular path contains a point fixed by a \(\Gamma_0(N)\) element of order 2 (where the order is computed in \(PSL_2(\ZZ)\)).
OUTPUT:
A list of integers.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(11) sage: MR.indices_with_two_torsion() [] sage: MR = ManinRelations(13) sage: MR.indices_with_two_torsion() [3, 4] sage: MR.reps(3), MR.reps(4) ( [1 1] [1 2] [ 3 2], [ 2 3] )
The corresponding matrix of order 2:
sage: A = MR.two_torsion_matrix(MR.reps(3)); A [ 5 2] [13 5] sage: A^2 [1 0] [ 0 1]
You can see that multiplication by
A
just interchanges the rational cusps determined by the columns of the matrixMR.reps(3)
:sage: MR.reps(3), A*MR.reps(3) ( [1 1] [ 1 1] [ 3 2], [2 3] )

is_unimodular_path
(r1, r2)¶ Determine whether two (noninfinite) cusps are connected by a unimodular path.
INPUT:
r1, r2
– rational numbers
OUTPUT:
A boolean expressing whether or not a unimodular path connects
r1
tor2
.EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.is_unimodular_path(0,1/3) True sage: A.is_unimodular_path(1/3,0) True sage: A.is_unimodular_path(0,2/3) False sage: A.is_unimodular_path(2/3,0) False

prep_hecke_on_gen
(l, gen, modulus=None)¶ This function does some precomputations needed to compute \(T_l\).
In particular, if \(\phi\) is a modular symbol and \(D_m\) is the divisor associated to the generator
gen
, to compute \((\phiT_{l})(D_m)\) one needs to compute \(\phi(\gamma_a D_m)\gamma_a\) where \(\gamma_a\) runs through the \(l+1\) matrices defining \(T_l\). One then takes \(\gamma_a D_m\) and writes it as a sum of unimodular divisors. For each such unimodular divisor, say \([M]\) where \(M\) is a \(SL_2\) matrix, we then write \(M=\gamma h\) where \(\gamma\) is in \(\Gamma_0(N)\) and \(h\) is one of our chosen coset representatives. Then \(\phi([M]) = \phi([h])  \gamma^{1}\). Thus, one has\[(\phi  \gamma_a)(D_m) = \sum_h \sum_j \phi([h])  \gamma_{hj}^{1} \cdot \gamma_a\]as \(h\) runs over all coset representatives and \(j\) simply runs over however many times \(M_h\) appears in the above computation.
Finally, the output of this function is a dictionary
D
whose keys are the coset representatives inself.reps()
where each value is a list of matrices, and the entries ofD
satisfy:\[D[h][j] = \gamma_{hj} * \gamma_a\]INPUT:
l
– a primegen
– a generator
OUTPUT:
A list of lists (see above).
EXAMPLES:
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [1/5, 1, 0] sage: M = phi.parent().source() sage: w = M.prep_hecke_on_gen(2, M.gens()[0]) sage: one = Matrix(ZZ,2,2,1) sage: one.set_immutable() sage: w[one] [[1 0] [0 2], [1 1] [0 2], [2 0] [0 1]]

prep_hecke_on_gen_list
(l, gen, modulus=None)¶ Return the precomputation to compute \(T_l\) in a way that speeds up the Hecke calculation.
Namely, returns a list of the form [h,A].
INPUT:
l
– a primegen
– a generator
OUTPUT:
A list of lists (see above).
EXAMPLES:
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [1/5, 1, 0] sage: M = phi.parent().source() sage: len(M.prep_hecke_on_gen_list(2, M.gens()[0])) 4

reps_with_three_torsion
()¶ A list of coset representatives whose associated unimodular path contains a point fixed by a \(\Gamma_0(N)\) element of order 3 in the ideal triangle directly below that path (the order is computed in \(PSL_2(\ZZ)\)).
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(13) sage: B = MR.reps_with_three_torsion()[0]; B [ 0 1] [ 1 3]
The corresponding matrix of order three:
sage: A = MR.three_torsion_matrix(B); A [4 1] [13 3] sage: A^3 [1 0] [0 1]
The columns of
B
and the columns ofA*B
andA^2*B
give the same rational cusps:sage: B [ 0 1] [ 1 3] sage: A*B, A^2*B ( [1 1] [ 1 0] [ 3 4], [4 1] )

reps_with_two_torsion
()¶ The coset representatives whose associated unimodular path contains a point fixed by a \(\Gamma_0(N)\) element of order 2 (where the order is computed in \(PSL_2(\ZZ)\)).
OUTPUT:
A list of matrices.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(11) sage: MR.reps_with_two_torsion() [] sage: MR = ManinRelations(13) sage: MR.reps_with_two_torsion() [ [1 1] [1 2] [ 3 2], [ 2 3] ] sage: B = MR.reps_with_two_torsion()[0]
The corresponding matrix of order 2:
sage: A = MR.two_torsion_matrix(B); A [ 5 2] [13 5] sage: A^2 [1 0] [ 0 1]
You can see that multiplication by
A
just interchanges the rational cusps determined by the columns of the matrixMR.reps(3)
:sage: B, A*B ( [1 1] [ 1 1] [ 3 2], [2 3] )

three_torsion_matrix
(A)¶ Return the matrix of order two in \(\Gamma_0(N)\) which corresponds to an
A
inself.reps_with_two_torsion()
.INPUT:
A
– a matrix inself.reps_with_two_torsion()
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(37) sage: B = MR.reps_with_three_torsion()[0]
The corresponding matrix of order 3:
sage: A = MR.three_torsion_matrix(B); A [11 3] [ 37 10] sage: A^3 [1 0] [0 1]

two_torsion_matrix
(A)¶ Return the matrix of order two in \(\Gamma_0(N)\) which corresponds to an
A
inself.reps_with_two_torsion()
.INPUT:
A
– a matrix inself.reps_with_two_torsion()
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(25) sage: B = MR.reps_with_two_torsion()[0]
The corresponding matrix of order 2:
sage: A = MR.two_torsion_matrix(B); A [ 7 2] [25 7] sage: A^2 [1 0] [ 0 1]

unimod_to_matrices
(r1, r2)¶ Return the two matrices whose associated unimodular paths connect
r1
andr2
andr2
andr1
, respectively.INPUT:
r1, r2
– rational numbers (that are assumed to be connected by a unimodular path)
OUTPUT:
A pair of \(2 \times 2\) matrices of determinant 1
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.unimod_to_matrices(0,1/3) ( [ 0 1] [1 0] [1 3], [3 1] )

class
sage.modular.pollack_stevens.fund_domain.
PollackStevensModularDomain
(N, reps, indices, rels, equiv_ind)¶ Bases:
sage.structure.sage_object.SageObject
The domain of a modular symbol.
INPUT:
N
– a positive integer, the level of the congruence subgroup \(\Gamma_0(N)\)reps
– a list of \(2 \times 2\) matrices, the coset representatives of \(Div^0(P^1(\QQ))\)indices
– a list of integers; indices of elements inreps
which are generatorsrels
– a list of list of triples(d, A, i)
, one for each coset representative ofreps
which describes how to express the elements ofreps
in terms of generators specified byindices
. Seerelations()
for a detailed explanations of these triples.equiv_ind
– a dictionary which maps normalized coordinates on \(P^1(\ZZ/N\ZZ)\) to an integer such that a matrix whose bottom row is equivalent to \([a:b]\) in \(P^1(\ZZ/N\ZZ)\) is in the coset ofreps[equiv_ind[(a,b)]]
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import PollackStevensModularDomain, M2Z sage: PollackStevensModularDomain(2 , [M2Z([1,0,0,1]), M2Z([1,1,1,0]), M2Z([0,1,1,1])], [0,2], [[(1, M2Z([1,0,0,1]), 0)], [(1,M2Z([1,1,0,1]),0)], [(1, M2Z([1,0,0,1]), 2)]], {(0,1): 0, (1,0): 1, (1,1): 2}) Modular Symbol domain of level 2

P1
()¶ Return the Sage representation of \(P^1(\ZZ/N\ZZ)\).
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.P1() The projective line over the integers modulo 11

equivalent_index
(A)¶ Return the index of the coset representative equivalent to
A
.Here by equivalent we mean the unique coset representative whose bottom row is equivalent to the bottom row of
A
in \(P^1(\ZZ/N\ZZ)\).INPUT:
A
– an element of \(SL_2(\ZZ)\)
OUTPUT:
The unique integer
j
satisfying that the bottom row ofself.reps(j)
is equivalent to the bottom row ofA
.EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(11) sage: A = matrix(ZZ,2,2,[1,5,3,16]) sage: j = MR.equivalent_index(A); j 11 sage: MR.reps(11) [ 1 1] [1 2] sage: MR.equivalent_rep(A) [ 1 1] [1 2] sage: MR.P1().normalize(3,16) (1, 9)

equivalent_rep
(A)¶ Return a coset representative that is equivalent to
A
modulo \(\Gamma_0(N)\).INPUT:
A
– a matrix in \(SL_2(\ZZ)\)
OUTPUT:
The unique generator congruent to
A
modulo \(\Gamma_0(N)\).EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = matrix([[5,3],[38,23]]) sage: ManinRelations(60).equivalent_rep(A) [7 3] [26 11]

gen
(n=0)¶ Return the
n
th generator.INPUT:
n
– integer (default: 0), which generator is desired
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(137) sage: A.gen(17) [4 1] [ 9 2]

gens
()¶ Return the list of coset representatives chosen as generators.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.gens() [ [1 0] [ 0 1] [1 1] [0 1], [ 1 3], [ 3 2] ]

indices
(n=None)¶ Return the \(n\)th index of the coset representatives which were chosen as our generators.
In particular, the divisors associated to these coset representatives generate all divisors over \(\ZZ[\Gamma_0(N)]\), and thus a modular symbol is uniquely determined by its values on these divisors.
INPUT:
n
– integer (default: None)
OUTPUT:
The
n
th index of the generating set inself.reps()
or all indices ifn
isNone
.EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.indices() [0, 2, 3] sage: A.indices(2) 3 sage: A = ManinRelations(13) sage: A.indices() [0, 2, 3, 4, 5] sage: A = ManinRelations(101) sage: A.indices() [0, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 23, 24, 26, 28]

level
()¶ Return the level \(N\) of \(\Gamma_0(N)\) that we work with.
OUTPUT:
The integer \(N\) of the group \(\Gamma_0(N)\) for which the Manin Relations are being computed.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.level() 11

ngens
()¶ Return the number of generators.
OUTPUT:
The number of coset representatives from which a modular symbol’s value on any coset can be derived.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(1137) sage: A.ngens() 255

relations
(A=None)¶ Express the divisor attached to the coset representative of
A
in terms of our chosen generators.INPUT:
A
–None
, an integer, or a coset representative (default:None
)
OUTPUT:
A \(\ZZ[\Gamma_0(N)]\)relation expressing the divisor attached to
A
in terms of the generating set. The relation is given as a list of triples(d, B, i)
such that the divisor attached to \(A\) is the sum ofd
times the divisor attached toB^{1} * self.reps(i)
.If
A
is an integer, then return this data for theA
th coset representative.If
A
isNone
, then return this data in a list for all coset representatives.Note
These relations allow us to recover the value of a modular symbol on any coset representative in terms of its values on our generating set.
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: MR = ManinRelations(11) sage: MR.indices() [0, 2, 3] sage: MR.relations(0) [(1, [1 0] [0 1], 0)] sage: MR.relations(2) [(1, [1 0] [0 1], 2)] sage: MR.relations(3) [(1, [1 0] [0 1], 3)]
The fourth coset representative can be expressed through the second coset representative:
sage: MR.reps(4) [1 2] [ 2 3] sage: d, B, i = MR.relations(4)[0] sage: P = B.inverse()*MR.reps(i); P [ 2 1] [3 2] sage: d # the above corresponds to minus the divisor of A.reps(4) since d is 1 1
The sixth coset representative can be expressed as the sum of the second and the third:
sage: MR.reps(6) [ 0 1] [ 1 2] sage: MR.relations(6) [(1, [1 0] [0 1], 2), (1, [1 0] [0 1], 3)] sage: MR.reps(2), MR.reps(3) # MR.reps(6) is the sum of these divisors ( [ 0 1] [1 1] [ 1 3], [ 3 2] )

reps
(n=None)¶ Return the
n
th coset representative associated with our fundamental domain.INPUT:
n
– integer (default: None)
OUTPUT:
The
n
th coset representative or all coset representatives ifn
isNone
.EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import ManinRelations sage: A = ManinRelations(11) sage: A.reps(0) [1 0] [0 1] sage: A.reps(1) [ 1 1] [1 0] sage: A.reps(2) [ 0 1] [ 1 3] sage: A.reps() [ [1 0] [ 1 1] [ 0 1] [1 1] [1 2] [2 1] [ 0 1] [ 1 0] [0 1], [1 0], [ 1 3], [ 3 2], [ 2 3], [ 3 1], [ 1 2], [2 1], [ 0 1] [ 1 0] [1 1] [ 1 1] [ 1 1], [1 1], [ 2 1], [1 2] ]

sage.modular.pollack_stevens.fund_domain.
basic_hecke_matrix
(a, l)¶ Return the \(2 \times 2\) matrix with entries
[1, a, 0, l]
ifa<l
and[l, 0, 0, 1]
ifa>=l
.INPUT:
 \(a\) – an integer or Infinity
l
– a prime
OUTPUT:
A \(2 \times 2\) matrix of determinant l
EXAMPLES:
sage: from sage.modular.pollack_stevens.fund_domain import basic_hecke_matrix sage: basic_hecke_matrix(0, 7) [1 0] [0 7] sage: basic_hecke_matrix(5, 7) [1 5] [0 7] sage: basic_hecke_matrix(7, 7) [7 0] [0 1] sage: basic_hecke_matrix(19, 7) [7 0] [0 1] sage: basic_hecke_matrix(infinity, 7) [7 0] [0 1]