Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/arithgroup/congroup_sl2z.py
8820 views
1
r"""
2
The modular group `{\rm SL}_2(\ZZ)`
3
4
AUTHORS:
5
6
- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
7
8
"""
9
10
################################################################################
11
#
12
# Copyright (C) 2009, The Sage Group -- http://www.sagemath.org/
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
#
16
# The full text of the GPL is available at:
17
#
18
# http://www.gnu.org/licenses/
19
#
20
################################################################################
21
22
from congroup_gamma0 import Gamma0_class
23
from arithgroup_element import ArithmeticSubgroupElement
24
from sage.rings.integer_ring import ZZ
25
from sage.modular.cusps import Cusp
26
from sage.rings.arith import gcd
27
from sage.modular.modsym.p1list import lift_to_sl2z
28
29
def is_SL2Z(x):
30
r"""
31
Return True if x is the modular group `{\rm SL}_2(\ZZ)`.
32
33
EXAMPLES::
34
35
sage: from sage.modular.arithgroup.all import is_SL2Z
36
sage: is_SL2Z(SL2Z)
37
True
38
sage: is_SL2Z(Gamma0(6))
39
False
40
"""
41
return isinstance(x, SL2Z_class)
42
43
class SL2Z_class(Gamma0_class):
44
r"""
45
The full modular group `{\rm SL}_2(\ZZ)`, regarded as a congruence
46
subgroup of itself.
47
"""
48
49
def __init__(self):
50
r"""
51
The modular group ${\rm SL}_2(\Z)$.
52
53
EXAMPLES::
54
55
sage: G = SL2Z; G
56
Modular Group SL(2,Z)
57
sage: G.gens()
58
(
59
[ 0 -1] [1 1]
60
[ 1 0], [0 1]
61
)
62
sage: G.0
63
[ 0 -1]
64
[ 1 0]
65
sage: G.1
66
[1 1]
67
[0 1]
68
sage: latex(G)
69
\mbox{\rm SL}_2(\Bold{Z})
70
sage: G([1,-1,0,1])
71
[ 1 -1]
72
[ 0 1]
73
sage: TestSuite(G).run()
74
sage: SL2Z.0 * SL2Z.1
75
[ 0 -1]
76
[ 1 1]
77
sage: SL2Z is loads(dumps(SL2Z))
78
True
79
"""
80
Gamma0_class.__init__(self, 1)
81
82
def __reduce__(self):
83
"""
84
Used for pickling self.
85
86
EXAMPLES::
87
88
sage: SL2Z.__reduce__()
89
(<function _SL2Z_ref at ...>, ())
90
"""
91
return _SL2Z_ref, ()
92
93
def _element_constructor_(self, x, check=True):
94
r"""
95
Create an element of self from x, which must be something that can be
96
coerced into a 2x2 integer matrix. If check=True (the default), check
97
that x really has determinant 1.
98
99
EXAMPLE::
100
101
sage: SL2Z([1,0,0,1]) # indirect doctest
102
[1 0]
103
[0 1]
104
sage: SL2Z([2, 0, 0, 2], check=False) # don't do this!
105
[2 0]
106
[0 2]
107
sage: SL2Z([1, QQ, False], check=False) # don't do this either!
108
Traceback (most recent call last):
109
...
110
TypeError: entries has the wrong length
111
"""
112
return ArithmeticSubgroupElement(self, x, check=check)
113
114
def _contains_sl2(self,a,b,c,d):
115
r"""
116
Test whether [a,b,c,d] is an element of self, where a,b,c,d are integers with `ad-bc=1`. In other words, always return True.
117
118
EXAMPLE::
119
120
sage: [8,7,9,8] in SL2Z # indirect doctest
121
True
122
"""
123
return True
124
125
def _repr_(self):
126
"""
127
Return the string representation of self.
128
129
EXAMPLES::
130
131
sage: SL2Z._repr_()
132
'Modular Group SL(2,Z)'
133
"""
134
return "Modular Group SL(2,Z)"
135
136
def _latex_(self):
137
r"""
138
Return the \LaTeX representation of self.
139
140
EXAMPLES::
141
142
sage: SL2Z._latex_()
143
'\\mbox{\\rm SL}_2(\\Bold{Z})'
144
sage: latex(SL2Z)
145
\mbox{\rm SL}_2(\Bold{Z})
146
"""
147
return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_())
148
149
def is_subgroup(self, right):
150
"""
151
Return True if self is a subgroup of right.
152
153
EXAMPLES::
154
155
sage: SL2Z.is_subgroup(SL2Z)
156
True
157
sage: SL2Z.is_subgroup(Gamma1(1))
158
True
159
sage: SL2Z.is_subgroup(Gamma0(6))
160
False
161
"""
162
return right.level() == 1
163
164
def reduce_cusp(self, c):
165
r"""
166
Return the unique reduced cusp equivalent to c under the
167
action of self. Always returns Infinity, since there is only
168
one equivalence class of cusps for $SL_2(Z)$.
169
170
EXAMPLES::
171
172
sage: SL2Z.reduce_cusp(Cusps(-1/4))
173
Infinity
174
"""
175
return Cusp(1,0)
176
177
def random_element(self, bound=100, *args, **kwds):
178
r"""
179
Return a random element of `{\rm SL}_2(\ZZ)` with entries whose
180
absolute value is strictly less than bound (default 100).
181
Additional arguments and keywords are passed to the random_element
182
method of ZZ.
183
184
(Algorithm: Generate a random pair of integers at most bound. If they
185
are not coprime, throw them away and start again. If they are, find an
186
element of `{\rm SL}_2(\ZZ)` whose bottom row is that, and
187
left-multiply it by `\begin{pmatrix} 1 & w \\ 0 & 1\end{pmatrix}` for
188
an integer `w` randomly chosen from a small enough range that the
189
answer still has entries at most bound.)
190
191
It is, unfortunately, not true that all elements of SL2Z with entries <
192
bound appear with equal probability; those with larger bottom rows are
193
favoured, because there are fewer valid possibilities for w.
194
195
EXAMPLES::
196
197
sage: SL2Z.random_element()
198
[60 13]
199
[83 18]
200
sage: SL2Z.random_element(5)
201
[-1 3]
202
[ 1 -4]
203
204
Passes extra positional or keyword arguments through::
205
206
sage: SL2Z.random_element(5, distribution='1/n')
207
[ 1 -4]
208
[ 0 1]
209
"""
210
if bound <= 1: raise ValueError("bound must be greater than 1")
211
c = ZZ.random_element(1-bound, bound, *args, **kwds)
212
d = ZZ.random_element(1-bound, bound, *args, **kwds)
213
if gcd(c,d) != 1: # try again
214
return self.random_element(bound, *args, **kwds)
215
else:
216
a,b,c,d = lift_to_sl2z(c,d,0)
217
whi = bound
218
wlo = bound
219
if c > 0:
220
whi = min(whi, ((bound - a)/ZZ(c)).ceil())
221
wlo = min(wlo, ((bound + a)/ZZ(c)).ceil())
222
elif c < 0:
223
whi = min(whi, ((bound + a)/ZZ(-c)).ceil())
224
wlo = min(wlo, ((bound - a)/ZZ(-c)).ceil())
225
226
if d > 0:
227
whi = min(whi, ((bound - b)/ZZ(d)).ceil())
228
wlo = min(wlo, ((bound + b)/ZZ(d)).ceil())
229
elif d < 0:
230
whi = min(whi, ((bound + b)/ZZ(-d)).ceil())
231
wlo = min(wlo, ((bound - b)/ZZ(-d)).ceil())
232
233
w = ZZ.random_element(1-wlo, whi, *args, **kwds)
234
a += c*w
235
b += d*w
236
return self([a,b,c,d])
237
238
239
SL2Z = SL2Z_class()
240
241
def _SL2Z_ref():
242
"""
243
Return SL2Z. (Used for pickling SL2Z.)
244
245
EXAMPLES::
246
247
sage: sage.modular.arithgroup.congroup_sl2z._SL2Z_ref()
248
Modular Group SL(2,Z)
249
sage: sage.modular.arithgroup.congroup_sl2z._SL2Z_ref() is SL2Z
250
True
251
"""
252
return SL2Z
253
254
255
256