Commit 22d06b1d authored by Gonzalo Tornaría's avatar Gonzalo Tornaría
Browse files

Paramodularity for C277

parents
//////////////////////////////////////////////////
// Implementation of parabolic group extensions
// Author: Gonzalo Tornaría <tornaria@cmat.edu.uy>
//////////////////////////////////////////////////
declare type GrpExt;
declare attributes GrpExt :
group, abelian, self, ambient, pi, gmodule, gmap, _gmodules;
intrinsic ParabolicExtension(G :: GrpMat, A :: ModMatFld) -> GrpExt
{ Construct the parabolic extension of G by A }
one := Matrix(One(G)); zero := Matrix(Zero(A));
require IsCompatible(one, zero)
: "G and A must have equal degree and base ring";
require &and [ g*a*g^-1 in A
: g in Generators(G), a in Generators(A)]
: "G must act on A by conjugation";
n := Degree(G);
R := BaseRing(G);
GL2n := GL(2*n, R);
// c : A --> ext
c := func< a | BlockMatrix([[one, a], [zero, one]]) >;
Cs := [c(r*a) : a in OrderedGenerators(A), r in Basis(R)];
// r : G --> ext
r := func< g | BlockMatrix([[g, zero], [zero, g]]) >;
Rs := [r(g) : g in OrderedGenerators(G)];
// p : ext --> G
p := func< x | ExtractBlock(x, 1, 1, n, n) >;
//
e := New(GrpExt);
e`group := G;
e`abelian := sub< GL2n | Cs >;
e`self := sub< GL2n | Cs cat Rs >;
e`ambient := e;
Ps := [p(x) : x in OrderedGenerators(e`self) ];
e`pi := hom< e`self -> e`group | Ps >;
cinv := func< x | ExtractBlock(x, 1, 1+n, n, n) >;
MA := MatrixAlgebra(R, Dimension(A));
gmap := func< x | Coordinates(A, A!cinv(x)) >;
gmat := func< g | MA ! [gmap(g^(-1)*c(a)*g) : a in Basis(A)] >;
action := [MA | gmat(r(g)) : g in Generators(G)];
// gmodule corresponding to the ambient
e`gmodule := GModule(G, action);
// e`gmap : e`abelian -> e`gmodule
e`gmap := hom< e`abelian -> e`gmodule | x :-> gmap(x) >;
// cache gmodules in the ambient for consistency
e`ambient`_gmodules := AssociativeArray();
e`ambient`_gmodules[G] := e`ambient`gmodule;
// it is required that G acts on A by conjugation
assert Kernel(e`pi) eq e`abelian;
assert Image(e`pi) eq e`group;
assert #e`abelian eq #A;
assert #e`self eq #e`group * #e`abelian;
return e;
end intrinsic
function sub(e, s)
assert s subset e`self;
f := New(GrpExt);
f`group := e`pi(s);
f`abelian := e`abelian meet s;
f`self := s;
f`ambient := e`ambient;
Ps := [e`pi(x) : x in OrderedGenerators(f`self)];
// compute gmodule
f`pi := hom< f`self -> f`group | Ps>;
b, gm := IsDefined(f`ambient`_gmodules, f`group);
if not b then
gm := Restriction(f`ambient`gmodule, f`group);
f`ambient`_gmodules[f`group] := gm;
end if;
f`gmodule := sub< gm |
[f`ambient`gmap(a) : a in Generators(f`abelian)] >;
f`gmap := hom< f`abelian -> f`gmodule | x :-> f`ambient`gmap(x) >;
assert Kernel(f`pi) eq f`abelian;
assert Image(f`pi) eq f`group;
assert #f`self eq #f`group * #f`abelian;
return f;
end function;
//////////////////////////////////////////////////
// Some Lie algebras (gl_n, sl_n, sp_n, gsp_n)
function gl(n, R)
return RMatrixSpace(R, n, n);
end function;
function sl(n, R)
A := gl(n, R);
B := RSpace(R, 1);
m := hom<A->B | [ [Trace(m)]
: m in OrderedGenerators(A)]>;
return Kernel(m);
end function;
// the standard symplectic form used by Sp(n, q) in magma
function symplectic_form(n, R)
assert IsEven(n);
J := Matrix(R, n, [i+j eq n+1
select (i lt j select 1 else -1)
else 0
: i,j in [1..n] ]);
assert J+Transpose(J) eq 0;
assert J*Transpose(J) eq 1;
return J;
end function;
function sp(n, R)
assert IsEven(n);
J := symplectic_form(n, R);
A := gl(n, R);
m := hom<A->A | [ mJ-Transpose(mJ)
where mJ is m*J
: m in OrderedGenerators(A)]>;
return Kernel(m);
end function;
function gsp(n, R)
assert IsEven(n);
J := symplectic_form(n, R);
assert J[1,n] eq 1;
A := gl(n, R);
m := hom<A->A | [ m1 - mu*J
where mu := m1[1,n] // m[1,1] + m[n,n]
where m1 := mJ-Transpose(mJ)
where mJ is m*J
: m in OrderedGenerators(A)]>;
return Kernel(m);
end function;
intrinsic SmallParabolic(G :: GrpMat) -> GrpExt
{ Small parabolic as a group extension }
n := Degree(G);
R := BaseRing(G);
require IsEven(n) : "Degree of G must be even";
spn := sp(n, R);
gspn := gsp(n, R);
e := ParabolicExtension(G, spn);
// use the normalizer as ambient space
a := ParabolicExtension(G, gspn);
return sub(a, e`self);
end intrinsic;
intrinsic Normalizer(e :: GrpExt) -> GrpExt
{ Normalizer of a group extension inside its ambient space }
return sub(e`ambient, Normalizer(e`ambient`self, e`self));
end intrinsic;
intrinsic Centralizer(e :: GrpExt) -> GrpExt
{ Centralizer of Normalizer(e) }
return sub(e`ambient, Centralizer(Normalizer(e)`self, e`self));
end intrinsic;
intrinsic GModule(e :: GrpExt) -> ModGrp
{ GModule corresponding to e }
return e`gmodule;
end intrinsic;
//////////////////////////////////////////////////
intrinsic Group(e :: GrpExt) -> GrpMat
{ .. }
return e`group;
end intrinsic;
intrinsic Abelian(e :: GrpExt) -> GrpMat
{ .. }
return e`abelian;
end intrinsic;
intrinsic Self(e :: GrpExt) -> GrpMat
{ .. }
return e`self;
end intrinsic;
intrinsic Ambient(e :: GrpExt) -> GrpMat
{ .. }
return e`ambient;
end intrinsic;
intrinsic BaseRing(e :: GrpExt) -> Rng
{ .. }
return BaseRing(Group(e));
end intrinsic;
intrinsic Dimension(e :: GrpExt) -> RngIntElt
{ .. }
return Integers() ! Log(#BaseRing(e), #Abelian(e));
end intrinsic;
intrinsic '#'(e :: GrpExt) -> RngIntElt
{ .. }
return #Self(e);
end intrinsic;
intrinsic GroupNameExt(G :: GrpMat : TeX := false) -> Str
{ ... }
GN := GroupName(G : TeX:=TeX);
G_3 := [g : g in G | Order(g) eq 3];
G_6 := [g : g in G | Order(g) eq 6];
if (#G_3 gt 0 and &and [Trace(g) eq 0 : g in G_3])
or
(#G_6 gt 0 and &and [Trace(g) eq 0 : g in G_6])
then
return GN cat "(A)";
end if;
if (#G_3 gt 0 and &and [Trace(g) eq 1 : g in G_3])
or
(#G_6 gt 0 and &and [Trace(g) eq 1 : g in G_6])
then
return GN cat "(B)";
end if;
return GN;
end intrinsic;
intrinsic Print(e :: GrpExt)
{ .. }
printf "GrpExt of %o by GF(%o)^%o",
GroupNameExt(Group(e)), #BaseRing(e), Dimension(e);
end intrinsic;
intrinsic Restriction(e :: GrpExt, H :: GrpMat) -> GrpExt
{ .. }
require H subset e`group : "H must be a subgroup of G";
return sub(e, H @@ e`pi meet e`self);
end intrinsic;
intrinsic Conjugates(e :: GrpExt, f :: GrpExt) -> []
{ .. }
return Conjugates(e`self, f`self);
end intrinsic;
intrinsic Conjugates(e :: GrpExt) -> []
{ .. }
return Conjugates(e`ambient`self, e`self);
end intrinsic;
intrinsic IsConjugate(e :: GrpExt, f :: GrpExt) -> BoolElt
{ .. }
require e`ambient eq f`ambient: "ambient spaces must be equal";
return IsConjugate(e`ambient`self, e`self, f`self);
end intrinsic;
intrinsic FilterConjugates(es :: [GrpExt]) -> []
{ .. }
fs := [];
ii := [];
for i := 1 to #es do
for j := 1 to #fs do
if IsConjugate(es[i], fs[j]) then
Append(~ii[j], i);
continue i;
end if;
end for;
// not found
Append(~fs, es[i]);
Append(~ii, [i]);
end for;
return fs, ii;
end intrinsic;
intrinsic Subextensions(e :: GrpExt : Codim := -1) -> []
{ .. }
if Codim eq -1 then
candidates := [ s`subgroup : s in
Subgroups(e`self
: OrderMultipleOf:=#e`group
, OrderDividing:=#e`self) ];
elif Codim gt Dimension(e) then
return [];
else
q := #BaseRing(e);
o := IntegerRing() ! (#e/q^Codim);
candidates := [ s`subgroup : s in
Subgroups(e`self : OrderEqual := o) ];
end if;
return [ sub(e, s) : s in candidates | e`pi(s) eq e`group ];
end intrinsic;
intrinsic 'meet' (e :: GrpExt, f :: GrpExt) -> GrpExt
{ .. }
return sub(e, e`self meet f`self);
end intrinsic;
intrinsic 'subset' (e :: GrpExt, f :: GrpExt) -> BoolElt
{ .. }
return Self(e) subset Self(f);
end intrinsic;
intrinsic 'eq' (e :: GrpExt, f :: GrpExt) -> BoolElt
{ .. }
assert e`ambient`self eq f`ambient`self;
return Self(e) eq Self(f);
end intrinsic;
// m can be of type HomGrp or GrpAutoElt
intrinsic IsIsomorphism(m, e :: GrpExt, f :: GrpExt) -> BoolElt
{ .. }
return IsTrivial(Kernel(m)) and Image(m) eq f`self and
// m should commute with the projections pi
&and[ x @ e`pi eq x @ m @ f`pi : x in Generators(e`self) ];
end intrinsic;
intrinsic IsIsomorphic (e :: GrpExt, f :: GrpExt) -> BoolElt, Map
{ test isomorphism as group extensions }
if e`group ne f`group or #e`abelian ne #f`abelian then
return false;
end if;
b, m := IsIsomorphic(e`self, f`self);
if not b then
return false;
end if;
// may or may not be isomorphic as group extensions
error if m(e`abelian) ne f`abelian, "Not implemented -- FIXME";
b, g := IsInnerAutomorphism(e`group, Inverse(e`pi) * m * f`pi);
// may or may not be isomorphic as group extensions
error if not b, "Not implemented for non-inner -- FIXME";
gg := g @@ f`pi;
mm := hom< e`self->f`self |
[gg*m(x)*gg^-1 : x in OrderedGenerators(e`self)] >;
// mm should be an isomorphism
assert IsIsomorphism(mm, e, f);
return true, mm;
end intrinsic;
intrinsic AutomorphismGroup(e :: GrpExt) -> GrpAuto
{ automorphisms as group extensions }
aut := AutomorphismGroup(e`self);
autg := AutomorphismGroup(e`group);
// m1 : autfp -> aut
// m2 : autfp -> autp
autfp, m1 := FPGroup(aut);
autp, m2 := PermutationGroup(autfp);
k := Kernel(hom<autp->autg |
[ hom<e`group->e`group |
[x @@ e`pi @ (a@@m2@m1) @ e`pi : x in OrderedGenerators(e`group)]>
: a in OrderedGenerators(autp)] >);
return k;
end intrinsic;
intrinsic OuterAutomorphismRepresentatives(e :: GrpExt) -> []
{ outer aut as gp ext (modulo inner aut by normalizer !!!)}
aut := AutomorphismGroup(e`self);
autg := AutomorphismGroup(e`group);
// m1 : autfp -> aut
// m2 : autfp -> outfp
// m3 : outfp -> outp
autfp, m1 := FPGroup(aut);
outfp, m2 := OuterFPGroup(aut);
outp, m3 := PermutationGroup(outfp);
// m0 : outp -> aut
m0 := Inverse(m3) * Inverse(m2) * m1;
out := [ m0(x) : x in outp ];
/* error if not &and[ IsIsomorphism(x, e, e) : x in out ], */
/* "an outer automorphism is not identity on G -- FIXME"; */
return out;
/*
v := e`abelian;
vg := e`self;
out3 := [m0(x) : x in outp | v @ m0(x) eq v and vg @ m0(x) eq vg];
// must fix x as in 'IsIsomorphic' so it is an isomorphism
// however, it seems to be ok due to the way magma computes aut gp
out2 := [ m0(x) : x in outp | b where b,g := IsInnerAutomorphism(e`group,
hom<e`group->e`group |
[g @@ e`pi @ m0(x) @ e`pi : g in OrderedGenerators(e`group)]>
)];
print #Kernel(m2), #Set(out3), #out3, #outp, #out2;
error if not &and[ IsIsomorphism((x), e, e) : x in out2 ],
"an outer automorphism is not identity on G -- FIXME";
return out2;
//return "-", #out2, #out3, #outp, "-";
*/
end intrinsic;
intrinsic GaloisExtension(R2 :: FldAb, VGs :: []) -> GrpExt
{ HACK, compute
VGs := IsomorphismClasses(Subextensions(SmallParabolic(Image(rho)))); }
gal, r, s := AbsoluteGaloisGroup(R2);
for VG in VGs do
b, m := IsIsomorphic(gal, VG`self);
if b then
print Dimension(VG);
end if;
end for;
return 0;
end intrinsic;
intrinsic GaloisExtension(R2 :: FldAb, R1 :: FldNum, rho :: HomGrp) -> GrpExt
{ Construct an extension corresponding to rho.
WARNING: This is a hack that works by finding a parabolic extension so
it will be ok as long as G has no outer automorphisms, otherwise
we should fix it by checking traces of frobenius or something like
that.
IOW the aim at first is to construct an extension corresponding to
some conjugate of rho }
gal, r, s := AbsoluteGaloisGroup(R2);
G := Image(rho);
SG := SmallParabolic(G);
for VG in IsomorphismClasses(Subextensions(SG)) do
b, m := IsIsomorphic(gal, VG`self);
if b then
print Dimension(VG);
end if;
end for;
return 0;
/* one := Matrix(One(G)); zero := Matrix(Zero(A)); */
/* require Parent(one) eq Parent(zero) */
/* : "G and A must have equal degree and base ring"; */
/* n := Degree(G); */
/* R := BaseRing(G); */
/* GL2n := GL(2*n, R); */
/* // c : A --> ext */
/* c := func< a | BlockMatrix([[one, a], [zero, one]]) >; */
/* Cs := [c(a) : a in OrderedGenerators(A)]; */
/* // r : G --> ext */
/* r := func< g | BlockMatrix([[g, zero], [zero, g]]) >; */
/* Rs := [r(g) : g in OrderedGenerators(G)]; */
/* // p : ext --> G */
/* p := func< x | ExtractBlock(x, 1, 1, n, n) >; */
/* // */
e := New(GrpExt);
e`group := Image(rho);
/* e`abelian := sub< GL2n | Cs >; */
/* e`self := sub< GL2n | Cs cat Rs >; */
/* e`ambient := e`self; */
/* Ps := [p(x) : x in OrderedGenerators(e`self) ]; */
/* e`pi := hom< e`self -> e`group | Ps >; */
/* // it is required that G acts on A by conjugation */
/* assert Kernel(e`pi) eq e`abelian; */
/* assert Image(e`pi) eq e`group; */
/* assert #e`self eq #e`group * #e`abelian; */
/* return e; */
end intrinsic
////////////////////////
// Proving modularity
///////////////////////
Attach("GrpExt.m");
declare type Modularity;
declare attributes Modularity :
R1, VGs, VHs, Vs, auts;
// ASSUME
// i. rho : Gal(R1) -~-> G, a subgroup inside Sp(4,2)
// ii. G is abs irreducible in Sp(4,2)
// iii. all automorphisms of G are inner [FIXME later]
intrinsic ModNew (R1 :: FldNum, rho :: HomGrp) -> Modularity
{ precomputation for modularity test }
G := Image(rho);
H := rho(Stabilizer(Domain(rho), 1));
SG := SmallParabolic(G);
VGs := FilterConjugates(Subextensions(SG));
auts := AssociativeArray();
VHs := AssociativeArray();
Vs := AssociativeArray();
// precompute automorphism groups
for VG in VGs do
auts[VG] := OuterAutomorphismRepresentatives(VG);
VHs[VG] := Restriction(VG, H);
Vs[VG] := VG`abelian;
end for;
m := New(Modularity);
m`R1 := R1;
m`VGs := VGs;
m`VHs := VHs;
m`Vs := Vs;
m`auts := auts;
return m;
end intrinsic;
intrinsic ModPhis(m :: Modularity, R2 :: FldAb) -> []
{ return a list of all possible phi }
assert NumberField(BaseRing(R2)) eq m`R1;
// may not be the most efficient way to do this
//gal, r, s := AbsoluteGaloisGroup(R2);
gal, r, s := GaloisGroup(AbsoluteField(NumberField(R2)));
ans := [* *];
for VG in m`VGs do
b, phi := IsIsomorphic(gal, VG`self);
VH := m`VHs[VG]`self;
V := m`Vs[VG];
if b then
//print Dimension(VG);
for psi in m`auts[VG] do
assert psi(VH) eq VH;
assert psi(V) eq V;
Append(~ans, phi*psi);
end for;
end if;
end for;
return ans;
end intrinsic;
/////////////////////////
// sorted degrees for a factorization (from high to low)
degrees := func<fact | Reverse(Sort([Degree(f[1]): f in fact]))>;
// return sorted degrees of factorization of pol mod p
factpat := func<pol,p | degrees(Factorization(ChangeRing(pol,GF(p))))>;
// turn a list of pairs <data,num> into a list repeating data num times
untally := func<fs | [f[1] : j in [1..f[2]], f in fs]>;
function tr(g)
return g[1,5]+g[2,6]+g[3,7]+g[4,8];
end function;
function tr1(g)
return g[1,1]+g[2,2]+g[3,3]+g[4,4];
end function;
ZZ := Integers();
function show_classes(m,phi)
gal := Domain(phi);
cc := ConjugacyClasses(gal);
/**/
G := Group(m`VGs[1]);
cs := ConjugacyClasses(G);
cclass := func<mm | [i : i in [1..#cs]
| IsConjugate(G,cs[i][3],G!mm)]>;
/* */