Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/local_comp/liftings.py
4095 views
1
r"""
2
Helper functions for local components
3
4
This module contains various functions relating to lifting elements of
5
`\mathrm{SL}_2(\ZZ / N\ZZ)` to `\mathrm{SL}_2(\ZZ)`, and other related
6
problems.
7
"""
8
9
from sage.rings.all import ZZ, Zmod
10
from sage.rings.arith import crt, inverse_mod
11
from sage.modular.modsym.p1list import lift_to_sl2z
12
13
def lift_to_gamma1(g, m, n):
14
r"""
15
If ``g = [a,b,c,d]`` is a list of integers defining a `2 \times 2` matrix
16
whose determinant is `1 \pmod m`, return a list of integers giving the
17
entries of a matrix which is congruent to `g \pmod m` and to
18
`\begin{pmatrix} 1 & * \\ 0 & 1 \end{pmatrix} \pmod n`. Here `m` and `n`
19
must be coprime.
20
21
Here `m` and `n` should be coprime positive integers. Either of `m` and `n`
22
can be `1`. If `n = 1`, this still makes perfect sense; this is what is
23
called by the function :func:`~lift_matrix_to_sl2z`. If `m = 1` this is a
24
rather silly question, so we adopt the convention of always returning the
25
identity matrix.
26
27
The result is always a list of Sage integers (unlike ``lift_to_sl2z``,
28
which tends to return Python ints).
29
30
EXAMPLE::
31
32
sage: from sage.modular.local_comp.liftings import lift_to_gamma1
33
sage: A = matrix(ZZ, 2, lift_to_gamma1([10, 11, 3, 11], 19, 5)); A
34
[371 68]
35
[ 60 11]
36
sage: A.det() == 1
37
True
38
sage: A.change_ring(Zmod(19))
39
[10 11]
40
[ 3 11]
41
sage: A.change_ring(Zmod(5))
42
[1 3]
43
[0 1]
44
sage: m = list(SL2Z.random_element())
45
sage: n = lift_to_gamma1(m, 11, 17)
46
sage: assert matrix(Zmod(11), 2, n) == matrix(Zmod(11),2,m)
47
sage: assert matrix(Zmod(17), 2, [n[0], 0, n[2], n[3]]) == 1
48
sage: type(lift_to_gamma1([10,11,3,11],19,5)[0])
49
<type 'sage.rings.integer.Integer'>
50
51
Tests with `m = 1` and with `n = 1`::
52
53
sage: lift_to_gamma1([1,1,0,1], 5, 1)
54
[1, 1, 0, 1]
55
sage: lift_to_gamma1([2,3,11,22], 1, 5)
56
[1, 0, 0, 1]
57
"""
58
if m == 1:
59
return [ZZ(1),ZZ(0),ZZ(0),ZZ(1)]
60
a,b,c,d = [ZZ(x) for x in g]
61
if not (a*d - b*c) % m == 1:
62
raise ValueError( "Determinant is {0} mod {1}, should be 1".format((a*d - b*c) % m, m) )
63
c2 = crt(c, 0, m, n)
64
d2 = crt(d, 1, m, n)
65
a3,b3,c3,d3 = map(ZZ, lift_to_sl2z(c2,d2,m*n))
66
r = (a3*b - b3*a) % m
67
return [a3 + r*c3, b3 + r*d3, c3, d3]
68
69
def lift_matrix_to_sl2z(A, N):
70
r"""
71
Given a list of length 4 representing a 2x2 matrix over `\ZZ / N\ZZ` with
72
determinant 1 (mod `N`), lift it to a 2x2 matrix over `\ZZ` with
73
determinant 1.
74
75
This is a special case of :func:`~lift_to_gamma1`, and is coded as such.
76
77
TESTS::
78
79
sage: from sage.modular.local_comp.liftings import lift_matrix_to_sl2z
80
sage: lift_matrix_to_sl2z([10, 11, 3, 11], 19)
81
[29, 106, 3, 11]
82
sage: type(_[0])
83
<type 'sage.rings.integer.Integer'>
84
sage: lift_matrix_to_sl2z([2,0,0,1], 5)
85
Traceback (most recent call last):
86
...
87
ValueError: Determinant is 2 mod 5, should be 1
88
"""
89
return lift_to_gamma1(A, N, 1)
90
91
def lift_gen_to_gamma1(m, n):
92
r"""
93
Return four integers defining a matrix in `\mathrm{SL}_2(\ZZ)` which is
94
congruent to `\begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix} \pmod m` and
95
lies in the subgroup `\begin{pmatrix} 1 & * \\ 0 & 1 \end{pmatrix} \pmod
96
n`.
97
98
This is a special case of :func:`~lift_to_gamma1`, and is coded as such.
99
100
EXAMPLE::
101
102
sage: from sage.modular.local_comp.liftings import lift_gen_to_gamma1
103
sage: A = matrix(ZZ, 2, lift_gen_to_gamma1(9, 8)); A
104
[441 62]
105
[ 64 9]
106
sage: A.change_ring(Zmod(9))
107
[0 8]
108
[1 0]
109
sage: A.change_ring(Zmod(8))
110
[1 6]
111
[0 1]
112
sage: type(lift_gen_to_gamma1(9, 8)[0])
113
<type 'sage.rings.integer.Integer'>
114
"""
115
return lift_to_gamma1([0,-1,1,0], m, n)
116
117
def lift_uniformiser_odd(p, u, n):
118
r"""
119
Construct a matrix over `\ZZ` whose determinant is `p`, and which is
120
congruent to `\begin{pmatrix} 0 & -1 \\ p & 0 \end{pmatrix} \pmod{p^u}` and
121
to `\begin{pmatrix} p & 0 \\ 0 & 1\end{pmatrix} \pmod n`.
122
123
This is required for the local components machinery in the "ramified" case
124
(when the exponent of `p` dividing the level is odd).
125
126
EXAMPLE::
127
128
sage: from sage.modular.local_comp.liftings import lift_uniformiser_odd
129
sage: lift_uniformiser_odd(3, 2, 11)
130
[432, 377, 165, 144]
131
sage: type(lift_uniformiser_odd(3, 2, 11)[0])
132
<type 'sage.rings.integer.Integer'>
133
"""
134
g = lift_gen_to_gamma1(p**u, n)
135
return [p*g[0], g[1], p*g[2], g[3]]
136
137
138
def lift_ramified(g, p, u, n):
139
r"""
140
Given four integers `a,b,c,d` with `p \mid c` and `ad - bc = 1 \pmod{p^u}`,
141
find `a',b',c',d'` congruent to `a,b,c,d \pmod{p^u}`, with `c' = c
142
\pmod{p^{u+1}}`, such that `a'd' - b'c'` is exactly 1, and `\begin{pmatrix}
143
a & b \\ c & d \end{pmatrix}` is in `\Gamma_1(n)`.
144
145
Algorithm: Uses :func:`~lift_to_gamma1` to get a lifting modulo `p^u`, and
146
then adds an appropriate multiple of the top row to the bottom row in order
147
to get the bottom-left entry correct modulo `p^{u+1}`.
148
149
EXAMPLE::
150
151
sage: from sage.modular.local_comp.liftings import lift_ramified
152
sage: lift_ramified([2,2,3,2], 3, 1, 1)
153
[5, 8, 3, 5]
154
sage: lift_ramified([8,2,12,2], 3, 2, 23)
155
[323, 110, -133584, -45493]
156
sage: type(lift_ramified([8,2,12,2], 3, 2, 23)[0])
157
<type 'sage.rings.integer.Integer'>
158
"""
159
a,b,c,d = lift_to_gamma1(g, p**u, n)
160
r = crt( (c - g[2]) / p**u * inverse_mod(a, p), 0, p, n)
161
c = c - p**u * r * a
162
d = d - p**u * r * b
163
# assert (c - g[2]) % p**(u+1) == 0
164
return [a,b,c,d]
165
166