# Revision history [back]

sage: Gamma(1).random_element()

[-13  40]
[-27  83]

Never walk through the long corridors of the department where people are studying modular forms and elliptic curves with a visible book on numerical approximation. (They will immediately notice it, and kindly help you find the right department. It is so important to keep things clean and structural!)

So why use that CDF to make things uncertainly complicated?

The generators are living in a beautiful ring, ZZ, and here is the best place to make computations. Moreover, the corresponding group is the modular group SL2Z. Mention it!

Let us type some piece of code to investigate the landscape. First of all let us consider the matrices:

L = SL2Z( [1,1,0,1] )
R = SL2Z( [1,0,1,1] )
L, R

This gives:

(
[1 1]  [1 0]
[0 1], [1 1]
)

The posted generators correspond to:

sage: R^(-1), L
(
[ 1  0]  [1 1]
[-1  1], [0 1]
)

Do $L,R$ generate indeed the full modular group Gamma(1) or SL2Z? We only have to generate the (standard) generators of this group using $L,R$. For this:

from sage.modular.arithgroup.arithgroup_perm import eval_sl2z_word, sl2z_word_problem
S, T = SL2Z.gens()
S, T

wT = sl2z_word_problem( T )
wS = sl2z_word_problem( S )

This gives wT and wS and the representations:

sage: wT
[(0, 1)]
sage: wS
[(0, 1), (1, -1), (0, 1), (1, -1), (0, 1), (1, -1), (0, 1), (1, -1), (0, 1)]
sage: T == L
True
sage: S == (L*R^-1)^4*L
True

The 0 stays on the first place of the tuples in the list for the usage of L, the 1 for R. So (1, -1) means one should use the R, namely to the power -1. The evaluation does the job directly:

sage: T == eval_sl2z_word( wT )
True
sage: S == eval_sl2z_word( wS )
True

The random element generated above has the representation as follows...

sage: Z = SL2Z( [ -13, 40, -27, 83 ] )
sage: wZ = sl2z_word_problem( Z )
sage: wZ
[(1, 2),
(0, 12),
(1, 1),
(0, -4),
(0, 1),
(1, -1),
(0, 1),
(1, -1),
(0, 1),
(1, -1)]
sage: R^2 * L^12 * R * L^-4 * (R * L^-1)^3 == Z
True

Let us generate many elements, say twelve here:

sage: [ SL2Z.random_element() for _ in [1..12] ]
[
[  9  77]  [-58  79]  [-72  23]  [11 25]  [73 53]  [ 80 -11]
[-11 -94], [ 11 -15], [ 97 -31], [ 7 16], [84 61], [-29   4],

[ -6   7]  [ 15  62]  [-53  55]  [-80  73]  [ -1  -5]  [-83 -55]
[ 77 -90], [-23 -95], [-80  83], [-57  52], [-16 -81], [ 80  53]
]

They never go beyond $\pm 100$? Strange randomizer...

Let us take a closer look at the implemented method:

sage: SL2Z.random_element?
Signature:      SL2Z.random_element(bound=100, *args, **kwds)

and so on, and the first line in the doc tells us what to do. Let us do it six times!

sage: [ SL2Z.random_element( bound=2017) for _ in [1..6] ]
[
[-607  182]  [  577 -1998]  [  627 -1291]  [ 567 1340]  [ 1093  -663]
[1831 -549], [ -255   883], [ -932  1919], [-278 -657], [ 1670 -1013],

[   29 -1269]
[   33 -1444]
]