""" This module implements the matrix group representation of the action of PGL(2,p) on the components of the Riemann-Roch space of the invariant divisors of the curve y^2 = x^p-x over GF(p). To run this, you must attach it to a running copy of SAGE (version 3.0.5 will work but probably older versions of SAGE are okay too) using a command such as sage: attach "/home/wdj/sagefiles/bad-curves-meataxe.sage" EXAMPLE: sage: g1 = mat_gen_gamma1_Ak(3,2) sage: g2 = mat_gen_gamma2_Ak(3,2) sage: g3 = mat_gen_gamma3_Ak(3,2) sage: g4 = mat_gen_gamma4_Ak(3,2) sage: G = MatrixGroup([g1,g2,g3,g4]) sage: G.module_composition_factors() [ rec( field := GF(3), isMTXModule := true, dimension := 1, generators := [ [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 3, 4 ], [ 1, 3 ] ], [ 0*Z(3), Z(3), Z(3), Z(3), Z(3)^0, Z(3)^0 ] ], algebraElementMatrix := [ [ Z(3) ] ], characteristicPolynomial := x_1+Z(3)^0, charpolFactors := x_1+Z(3)^0, nullspaceVector := [ Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 1, generators := [ [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 2, 1 ], [ 2, 1 ] ], [ Z(3), 0*Z(3), Z(3), Z(3)^0, Z(3), Z(3)^0 ] ], algebraElementMatrix := [ [ Z(3) ] ], characteristicPolynomial := x_1+Z(3)^0, charpolFactors := x_1+Z(3)^0, nullspaceVector := [ Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 3, generators := [ [ [ Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ Z(3)^0, Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, Z(3)^0 ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ 0*Z(3), Z(3), Z(3) ], [ Z(3)^0, Z(3)^0, Z(3) ], [ Z(3)^0, Z(3), Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 1, 4 ], [ 5, 2 ] ], [ Z(3), Z(3)^0, Z(3)^0, Z(3), 0*Z(3), 0*Z(3) ] ], algebraElementMatrix := [ [ Z(3)^0, 0*Z(3), Z(3)^0 ], [ Z(3), 0*Z(3), Z(3) ], [ Z(3), Z(3)^0, 0*Z(3) ] ], characteristicPolynomial := x_1^3-x_1^2-x_1, charpolFactors := x_1, nullspaceVector := [ Z(3)^0, Z(3)^0, 0*Z(3) ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 1, generators := [ [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 2, 3 ], [ 3, 2 ] ], [ 0*Z(3), Z(3), 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0 ] ], algebraElementMatrix := [ [ Z(3) ] ], characteristicPolynomial := x_1+Z(3)^0, charpolFactors := x_1+Z(3)^0, nullspaceVector := [ Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 3, generators := [ [ [ Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ Z(3)^0, Z(3), Z(3)^0 ], [ 0*Z(3), Z(3)^0, Z(3)^0 ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ 0*Z(3), 0*Z(3), Z(3)^0 ], [ 0*Z(3), Z(3), 0*Z(3) ], [ Z(3)^0, 0*Z(3), 0*Z(3) ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 1, 4 ], [ 2, 5 ] ], [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3), Z(3) ] ], algebraElementMatrix := [ [ 0*Z(3), 0*Z(3), Z(3)^0 ], [ 0*Z(3), Z(3), 0*Z(3) ], [ Z(3)^0, 0*Z(3), 0*Z(3) ] ], characteristicPolynomial := x_1^3+x_1^2-x_1-Z(3)^0, charpolFactors := x_1-Z(3)^0, nullspaceVector := [ Z(3)^0, 0*Z(3), Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ) ] sage: g1 = mat_gen_gamma1_Bk(3,2) sage: g2 = mat_gen_gamma2_Bk(3,2) sage: g3 = mat_gen_gamma3_Bk(3,2) sage: g4 = mat_gen_gamma4_Bk(3,2) sage: G = MatrixGroup([g1,g2,g3,g4]) sage: G.module_composition_factors() [ rec( field := GF(3), isMTXModule := true, dimension := 3, generators := [ [ [ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3) ] ], [ [ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3) ] ], [ [ Z(3)^0, Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0, Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ Z(3)^0, Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ], [ Z(3)^0, Z(3), Z(3) ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 1, 2 ], [ 1, 4 ] ], [ 0*Z(3), 0*Z(3), Z(3)^0, Z(3)^0, Z(3), Z(3)^0 ] ], algebraElementMatrix := [ [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3) ] ], characteristicPolynomial := x_1^3, charpolFactors := x_1, nullspaceVector := [ 0*Z(3), 0*Z(3), Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 3, generators := [ [ [ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3) ] ], [ [ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3) ] ], [ [ Z(3)^0, Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0, Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ], [ [ Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), 0*Z(3) ], [ Z(3)^0, Z(3), Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 2, 3 ], [ 5, 1 ] ], [ Z(3)^0, 0*Z(3), 0*Z(3), Z(3), Z(3)^0, 0*Z(3) ] ], algebraElementMatrix := [ [ Z(3), Z(3), 0*Z(3) ], [ 0*Z(3), Z(3), Z(3)^0 ], [ Z(3), Z(3)^0, 0*Z(3) ] ], characteristicPolynomial := x_1^3-x_1^2+Z(3)^0, charpolFactors := x_1^3-x_1^2+Z(3)^0, nullspaceVector := [ Z(3)^0, 0*Z(3), 0*Z(3) ], ndimFlag := 3 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 1, generators := [ [ [ Z(3) ] ], [ [ Z(3) ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 1, 3 ], [ 2, 4 ] ], [ Z(3)^0, Z(3), 0*Z(3), 0*Z(3), Z(3)^0, Z(3) ] ], algebraElementMatrix := [ [ 0*Z(3) ] ], characteristicPolynomial := x_1, charpolFactors := x_1, nullspaceVector := [ Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 1, generators := [ [ [ Z(3) ] ], [ [ Z(3) ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 4, 3 ], [ 1, 2 ] ], [ 0*Z(3), 0*Z(3), Z(3)^0, Z(3), Z(3)^0, 0*Z(3) ] ], algebraElementMatrix := [ [ Z(3)^0 ] ], characteristicPolynomial := x_1-Z(3)^0, charpolFactors := x_1-Z(3)^0, nullspaceVector := [ Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ), rec( field := GF(3), isMTXModule := true, dimension := 1, generators := [ [ [ Z(3) ] ], [ [ Z(3) ] ], [ [ Z(3)^0 ] ], [ [ Z(3)^0 ] ] ], smashMeataxe := rec( algebraElement := [ [ [ 2, 3 ], [ 4, 1 ] ], [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3), Z(3), Z(3)^0 ] ], algebraElementMatrix := [ [ Z(3)^0 ] ], characteristicPolynomial := x_1-Z(3)^0, charpolFactors := x_1-Z(3)^0, nullspaceVector := [ Z(3)^0 ], ndimFlag := 1 ), IsIrreducible := true ) ] sage: g1 = mat_gen_gamma1_Bk(3,2) sage: g2 = mat_gen_gamma2_Bk(3,2) sage: g3 = mat_gen_gamma3_Bk(3,2) sage: g4 = mat_gen_gamma4_Bk(3,2) sage: G_Bk = MatrixGroup([g1,g2,g3,g4]) sage: g1 = mat_gen_gamma1_Ak(3,2) sage: g2 = mat_gen_gamma2_Ak(3,2) sage: g3 = mat_gen_gamma3_Ak(3,2) sage: g4 = mat_gen_gamma4_Ak(3,2) sage: G_Ak = MatrixGroup([g1,g2,g3,g4]) sage: G_Ak == G_Bk False sage: G_Ak.order() 12 sage: G_Bk.order() 24 sage: PGL(2,3).order() 24 Copyright David Joyner, July 2008. """ #***************************************************************************** # Copyright (C) 2008 David Joyner # # Distributed under the terms of the GNU General Public License (GPL), # version 2 or greater (at your choice). # # http://www.gnu.org/licenses/ #***************************************************************************** def skew_diagonal_matrix(L): """ L is a list of entries in a ring R of length n. The output is an nxn skew diagonal matrix, where the first entry of L goes in the first column of the output. EXAMPLES: sage: A = skew_diagonal_matrix([R(7),R(2)]); A [0 2] [7 0] sage: A.parent() Full MatrixSpace of 2 by 2 dense matrices over Ring of integers modulo 9 """ R = L[0].parent() n = len(L) MS = MatrixSpace(R, n, n) M = MS(0) for i in range(n): M[n-1-i,i] = L[i] return M def mat_gen_gamma1_Ak(p,k): """ Implements the gamma_1 action on A_k in the GF(p) case. EXAMPLES: sage: mat_gen_gamma1_Ak(3,2) [1 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0] [0 0 0 0 1 0 0 0 0] [0 0 0 0 0 1 0 0 0] [0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 1 0] [0 0 0 0 0 0 0 0 1] """ n = k*(p+1)+1 MS = MatrixSpace( GF(p), n, n) return MS(1) def mat_gen_gamma2_Ak(p,k): """ Implements the gamma_2(a) action on A_k in the GF(p) case. The element a is chosen. It is a 2(p-1)-st primitive root but the action on x is multiplication by a^2, by Goeb's formulas. Since we need the action on the A_k and on the B_k to be by the same group, and to be defined over GF(p), we take ** the element a to be a generator of GF(p)^x. ** EXAMPLES: sage: mat_gen_gamma2_Ak(3,2) [1 0 0 0 0 0 0 0 0] [0 2 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0] [0 0 0 2 0 0 0 0 0] [0 0 0 0 1 0 0 0 0] [0 0 0 0 0 2 0 0 0] [0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 2 0] [0 0 0 0 0 0 0 0 1] """ F = GF(p) a = F(primitive_root(p)) n = k*(p+1)+1 D = [a^(2*(i-k)) for i in range(n)] return diagonal_matrix(D) def mat_gen_gamma3_Ak(p,k): """ Implements the gamma_3 action on A_k in the GF(p) case. EXAMPLES: """ L = [] F = GF(p) n = k*(p+1)+1 MS = MatrixSpace( F, n, n) for j in range(n): c = [F(0)]*n for i in range(j+1): c[i] = binomial(j,i) L = L+c return MS(L).transpose() def mat_gen_gamma4_Ak(p,k): """ Implements the gamma_4 action on A_k in the GF(p) case. EXAMPLES: sage: mat_gen_gamma4_Ak(3,2) [ 0 0 0 0 0 0 0 0 1] [ 0 0 0 0 0 0 0 -1 0] [ 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 -1 0 0 0] [ 0 0 0 0 1 0 0 0 0] [ 0 0 0 -1 0 0 0 0 0] [ 0 0 1 0 0 0 0 0 0] [ 0 -1 0 0 0 0 0 0 0] [ 1 0 0 0 0 0 0 0 0] """ n = k*(p+1)+1 sd = [(-1)^(k+i) for i in range(n)] return skew_diagonal_matrix(sd) def mat_gen_gamma1_Bk(p,k): """ Implements the gamma_1 action on B_k in the GF(p) case. EXAMPLES: sage: mat_gen_gamma1_Bk(3,2) [1 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0] [0 0 0 0 1 0 0 0 0] [0 0 0 0 0 1 0 0 0] [0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 1 0] [0 0 0 0 0 0 0 0 1] """ n = k*(p+1)+1 MS = MatrixSpace( GF(p), n, n) return MS(-1) def mat_gen_gamma2_Bk(p,k): """ Implements the gamma_2(a) action on B_k in the GF(p) case. The element a is chosen. It is a 2(p-1)-st primitive root but since we need the action on the A_k and on the B_k to be by the same group, and to be defined over GF(p), we take it to be a generator of GF(p)^x. EXAMPLES: sage: mat_gen_gamma2_Bk(3,2) [1 0 0 0 0 0 0 0 0] [0 2 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0] [0 0 0 2 0 0 0 0 0] [0 0 0 0 1 0 0 0 0] [0 0 0 0 0 2 0 0 0] [0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 2 0] [0 0 0 0 0 0 0 0 1] """ F = GF(p) a = F(primitive_root(p)) n = k*(p+1)+1 D = [a^(2*(i-k)+1) for i in range(n)] return diagonal_matrix(D) mat_gen_gamma3_Bk = mat_gen_gamma3_Ak mat_gen_gamma4_Bk = mat_gen_gamma4_Ak