/*
VERSION: 2020-07-29
This file contains Magma programs that verify a statement made in the paper
"Algorithms to enumerate superspecial Howe curves of genus 4", by Momonari Kudo,
Shushi Harashita, and Everett W. Howe [KHH2020].
The statement is the following: Let D be a nonhyperelliptic curve of genus 4
over a field of characteristic not 2. It is shown in [KHH2020] that then the
automorphism group of D has order at most 511, by a result of Henn. Let G be the
2-Sylow subgroup of Aut D. To every involution delta in G, we let g(delta) be
the genus of the quotient of D by delta. If G is not isomorpic to (Z/2Z)^3,
then G does not contain two V4 subgroups
X1 = {alpha1, beta1, gamma1, id}
X2 = {alpha2, beta2, gamma2, id}
such that
g(alpha1) = g(alpha2) = 2
g(beta1 = g(gamma1) = g(beta2) = g(gamma2) = 1
and such that alpha1 and alpha2 are not conjugate to one another in G.
We prove this by looking at every $2$-group G of order less than 511,
enumerating possible subgroups X1 and X2, computing the value of the function g
on as many involutions as we can, and then noting that we can always find an
involution delta for which g(delta) = 2 and yet the group
Centralizer_G(delta) /
is not one of the eight possible 2-groups that can appear as a subgroup of an
automorphism group of a genus-2 curve over a field of characteristic not 2.
The way we derive new values of g(delta) is via the observation, made in the
paper, that if x and y are commuting involutions, then
g(x*y) = 2 if g(x) = g(y),
g(x*y) = 1 if g(x) != g(y).
If a group G *does* contain a pair of V4-subgroups as above, we will say that
G "has an unfortunate pair".
The function UnfortunatePairs(G) returns a list of unfortunate pairs in G that
represent all unfortunate pairs, up to conjugacy. The pairs are given as
quadruples [alpha1, alpha2, beta1, beta2], with notation as above.
The procedure FindProblematicGroups() prints out a list of the groups IDs
(in terms of Magma's small groups database) of the $2$-groups of order at most
511 that have unfortunate pairs.
Note that the eight 2-groups that can be embedded in the automorphism group of
a genus-2 curve in characteristic not are:
* Any group of order 1, 2, or 4
* SmallGroup(8,1)
* SmallGroup(8,3)
* SmallGroup(8,4)
* SmallGroup(16,8)
This is verified by the function CheckTwoGroupsGenusTwo(), which looks at the
families of curves identified by Igusa as covering all possible automorphism
groups.
Finally, since we know that the only group in the size range we are considering
that has an unfortunate pair is SmallGroup(8,5) = (Z/2Z)^3, we added some extra
analysis for this group into the code for UnfortunatePairs. Namely, when we run
the program on G = SmallGroup(8,5), we additionally check that for each
unfortunate pair that we find, three of the seven involutions in G have genus 2,
and four have genus 1 --- and furthermore, the three genus-2 involutions sum to
the identity.
USAGE:
======
Once you have loaded this file into Magma, run
CheckTwoGroupsGenusTwo();
and you will get the value "true", indicating that our list of eight 2-groups
above is indeed the list of all 2-groups that can appear as subgroups of the
automorphism group of a genus-2 curve over an algebraically closed field of
characteristic not 2.
Then run
FindProblematicGroups();
and verify that it prints
"SmallGroup(8,5) is problematic. But the extra condition is satisfied."
and nothing else. (This takes a little under 17 minutes on a 2.8 GHz Quad-Core
Intel Core i7 MacBook Pro with 16GB RAM. If you want to track progress,
uncomment the print statement in the code for FindProblematicGroups.)
Finally, enter
Exponent(SmallGroup(8,5));
and get the answer "2" to see that SmallGroup(8,5) is (Z/2Z)^3.
VERSION HISTORY:
================
2020-06-16: First released version.
2020-07-29: Updated comments to reflect changes in paper.
Corrected an error in CheckTwoGroupsGenusTwo.
Modified FindProblematicGroups so it looks only at 2-groups, to
match the argument in the paper.
REFERENCES:
===========
[KHH2020] Momonari Kudo, Shushi Harashita, and Everett W. Howe:
Algorithms to enumerate superspecial Howe curves of genus 4,
arXiv: 2006.11499 [math.NT]
https://arxiv.org/abs/2006.11499
*/
function CheckTwoGroupsGenusTwo();
subgroupAttained := AssociativeArray();
expectedGroups := [ [1,1],[2,1],[4,1],[4,2],[8,1],[8,3],[8,4],[16,8] ];
// We index the families of curves as does Igusa. His first two families
// have Sylow 2-subgroups of order 4 and his sixth has Sylow 2-subgroup
// Z/2Z, so the 2-groups we get from these families clearly lie in our
// expected groups.
// Third family: y^2 = x*(x-1)*(x+1)*(x-lambda)(x-1/lambda).
// Reduced automorphism group V4.
Q := QuadraticField(-1);
K:=FunctionField(Q);
R:=PolynomialRing(K);
lambda := (t^2 + 1)/(2*t);
f := x*(x-1)*(x+1)*(x-lambda)*(x-1/lambda);
C := HyperellipticCurve(f);
G := AutomorphismGroup(C);
assert #G eq 8;
G := SylowSubgroup(G,2);
for S in Subgroups(G) do
n := S`order;
i := 0;
repeat i+:=1;
until IsIsomorphic(S`subgroup,SmallGroup(n,i));
subgroupAttained[[n,i]] := true;
end for;
// Fourth family: y^2 = x*(x-1)*(x+1)*(x-2)*(x-1/2);
// Reduced automorphism group D_12
Q := CyclotomicField(12);
R:=PolynomialRing(Q);
f := x*(x-1)*(x+1)*(x-2)*(x-1/2);
C := HyperellipticCurve(f);
G, phi := AutomorphismGroup(C);
assert #G eq 24;
G := SylowSubgroup(G,2);
for S in Subgroups(G) do
n := S`order;
i := 0;
repeat i+:=1;
until IsIsomorphic(S`subgroup,SmallGroup(n,i));
subgroupAttained[[n,i]] := true;
end for;
// Fifth family: y^2 = x*(x-1)*(x+1)*(x^2 + 1);
// Reduced automorphism group S_4
Q := CyclotomicField(24);
R:=PolynomialRing(Q);
f := x*(x-1)*(x+1)*(x^2 + 1);
C := HyperellipticCurve(f);
G, phi := AutomorphismGroup(C);
assert #G eq 48;
G := SylowSubgroup(G,2);
for S in Subgroups(G) do
n := S`order;
i := 0;
repeat i+:=1;
until IsIsomorphic(S`subgroup,SmallGroup(n,i));
subgroupAttained[[n,i]] := true;
end for;
// There is also Igusa's "one modification" of his listing: In characteristic
// 5, his cases four, five, and six combine into one curve with reduced
// automorphism group of order 120.
Q := GF(5^2);
R:=PolynomialRing(Q);
f := x*(x-1)*(x+1)*(x^2 + 1);
C := HyperellipticCurve(f);
G, phi := AutomorphismGroup(C);
assert #G eq 240;
G := SylowSubgroup(G,2);
for S in Subgroups(G) do
n := S`order;
i := 0;
repeat i+:=1;
until IsIsomorphic(S`subgroup,SmallGroup(n,i));
subgroupAttained[[n,i]] := true;
end for;
return Keys(subgroupAttained) eq Set(expectedGroups);
end function;
function UnfortunatePairs(G);
// In addition to computing unfortunate pairs, we also keep track of
// an extra condition for the group G = SmallGroup(8,5) = (Z/2Z)^3:
// namely, we check that for all of the unfortunate pairs for this group,
// we know the genus for each of the seven involutions in the group, and
// exactly three of the involutions have genus 2; furthermore, these three
// involutions add up to the identity. This boolean variable keeps track of
// this... it starts as being true, and is set to false if we find a
// counterexample.
extraCondition := true;
unfortunatePairs := [];
H := SylowSubgroup(G,2);
involutions := [a : a in H | Order(a) eq 2];
// First, find the involutions delta such that if g(delta) = 2, then we
// will get a genus-2 curve with an impossible automorphism group.
badInvolutions := [];
for delta in involutions do
inducedAutomorphisms := quo;
if #inducedAutomorphisms gt 6 and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(8,1)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(8,3)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(8,4)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(10,2)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(12,1)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(12,4)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(12,5)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(16,8)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(24,3)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(24,8)) and
not IsIsomorphic(inducedAutomorphisms,SmallGroup(48,29))
then
badInvolutions cat:= [delta];
end if;
end for;
// If every involution causes a problem, we are done.
if #badInvolutions eq #involutions then return [], true; end if;
// The alpha's in an unfortunate pair both have g(alpha) = 2,
// so no alpha can be in badInvolutions.
possibleAlpha := [a : a in involutions | not a in badInvolutions];
// Speed up the search by limiting alpha1 to representatives in H
// for each G-conjugacy class of non-bad involutions.
possibleAlphaUpToConjugacy := [possibleAlpha[1]];
for a in possibleAlpha do
if &and[not IsConjugate(G,a,x) : x in possibleAlphaUpToConjugacy] then
possibleAlphaUpToConjugacy cat:= [a];
end if;
end for;
// Now start the search. Pick alpha1.
for alpha1 in possibleAlphaUpToConjugacy do
// genusList1 will keep track of known values of g(delta) derived from
// our selection of alpha1.
genusList1 := AssociativeArray();
for a in involutions do
if IsConjugate(G,alpha1,a) then
genusList1[a] := 2;
end if;
end for;
// Derive new values of the genus.
repeat
added := false;
for a,b in Keys(genusList1) do if a*b eq b*a and a*b in involutions then
if genusList1[a] eq genusList1[b] then newvalue := 2; else newvalue := 1; end if;
// If we've shown that a bad involution has genus 2, then this alpha1 is
// not going to be part of an unfortunate pair.
if a*b in badInvolutions and newvalue eq 2 then continue alpha1; end if;
// Otherwise, check to see whether we've reached a contradiction.
// If not, record the new value.
if not a*b in Keys(genusList1) then
added := true;
genusList1[a*b] := newvalue;
else
if genusList1[a*b] ne newvalue then continue alpha1; end if;
end if;
end if; end for;
until not added;
// Now pick a value for beta1.
for beta1 in [a : a in involutions | a*alpha1 eq alpha1*a and a ne alpha1] do
// Cut down the search space by never choosing both beta1 and alpha*beta1
// over the course of the computation, because they give the same V4 subgroup.
if Hash(beta1) eq Sort([Hash(beta1),Hash(alpha1*beta1)])[1] then
// Also, only choose beta1 if we do not already know that its genus is 2.
if ((not beta1 in Keys(genusList1)) or (genusList1[beta1] eq 1)) then
// genusList2 will keep track of known values of g(delta) derived from
// our selection of alpha1 and beta1.
// Seed genusList2 with the values we already know.
genusList2 := AssociativeArray();
for k in Keys(genusList1) do genusList2[k] := genusList1[k]; end for;
// Every conjugate of beta1 has genus 1.
for a in involutions do
if IsConjugate(G,beta1,a) then
if not a in Keys(genusList2) then
genusList2[a] := 1;
else
// If we reach a contradiction, the beta1 cannot work with the choice of alpha1.
if genusList2[a] ne 1 then continue beta1; end if;
end if;
end if;
end for;
// As before, derive new values of the genus.
repeat
added := false;
for a,b in Keys(genusList2) do if a*b eq b*a and a*b in involutions then
if genusList2[a] eq genusList2[b] then newvalue := 2; else newvalue := 1; end if;
if a*b in badInvolutions and newvalue eq 2 then continue beta1; end if;
if not a*b in Keys(genusList2) then
added := true;
genusList2[a*b] := newvalue;
else
if genusList2[a*b] ne newvalue then continue beta1; end if;
end if;
end if; end for;
until not added;
// Now we choose possible values for alpha2:
for alpha2 in possibleAlpha do
if not IsConjugate(G,alpha2,alpha1) and ((not alpha2 in Keys(genusList2)) or (genusList2[alpha2] eq 2)) then
// genusList3 will keep track of known values of g(delta) derived from
// our selection of alpha1 and beta1 and alpha2.
// Seed genusList3 with the values we already know.
genusList3 := AssociativeArray();
for k in Keys(genusList2) do genusList3[k] := genusList2[k]; end for;
for a in involutions do
if IsConjugate(G,alpha2,a) then
if not a in Keys(genusList3) then
genusList3[a] := 2;
else
if genusList3[a] ne 2 then continue alpha2; end if;
end if;
end if;
end for;
repeat
added := false;
for a,b in Keys(genusList3) do if a*b eq b*a and a*b in involutions then
if genusList3[a] eq genusList3[b] then newvalue := 2; else newvalue := 1; end if;
if a*b in badInvolutions and newvalue eq 2 then continue alpha2; end if;
if not a*b in Keys(genusList3) then
added := true;
genusList3[a*b] := newvalue;
else
if genusList3[a*b] ne newvalue then continue alpha2; end if;
end if;
end if; end for;
until not added;
// And finally, choose possible values for beta2.
for beta2 in [a : a in involutions | a*alpha2 eq alpha2*a and a ne alpha2] do
if Hash(beta2) eq Sort([Hash(beta2),Hash(beta2*alpha2)])[1] then
if (not beta2 in Keys(genusList3)) or (genusList3[beta2] eq 1) then
// genusList4 will keep track of known values of g(delta) derived from
// our selection of alpha1 and beta1 and alpha2 and beta2.
// Seed genusList4 with the values we already know.
genusList4 := AssociativeArray();
for k in Keys(genusList3) do genusList4[k] := genusList3[k]; end for;
for a in involutions do
if IsConjugate(G,beta2,a) then
if not a in Keys(genusList4) then
genusList4[a] := 1;
else
if genusList4[a] ne 1 then continue beta2; end if;
end if;
end if;
end for;
repeat
added := false;
for a,b in Keys(genusList4) do if a*b eq b*a and a*b in involutions then
if genusList4[a] eq genusList4[b] then newvalue := 2; else newvalue := 1; end if;
if a*b in badInvolutions and newvalue eq 2 then continue beta2; end if;
if not a*b in Keys(genusList4) then
added := true;
genusList4[a*b] := newvalue;
else
if genusList4[a*b] ne newvalue then continue beta2; end if;
end if;
end if; end for;
until not added;
unfortunatePairs cat:= [ < alpha1, alpha2, beta1, beta2 > ];
// a posteriori, we know that we will only be at this point
// when G = SmallGroup(8,5). Let's check the extra condition.
K := Keys(genusList4);
if K ne Set(involutions) then
extraCondition := false;
else
genus2 := [k : k in K | genusList4[k] eq 2];
if #genus2 ne 3 then
extraCondition := false;
else
if &*[g : g in genus2] ne Identity(G) then
extraCondition := false;
end if;
end if;
end if;
end if;
end if;
end for;
end if;
end for;
end if;
end if;
end for;
end for;
return unfortunatePairs, extraCondition;
end function;
procedure FindProblematicGroups()
for n in [4, 8, 16, 32, 64, 128, 256] do
print "\n", n, NumberOfSmallGroups(n);
space := &cat[" " : i in [1..#IntegerToString(n,10)]];
for i in [1..NumberOfSmallGroups(n)] do
printf "%o%o %o ", CodeToString(13),space,i;
unfortunatePairs, boolean := UnfortunatePairs(SmallGroup(n,i));
if #unfortunatePairs gt 0 then
printf "\nSmallGroup(%o,%o) is problematic.", n, i;
if boolean then print " But the extra condition is satisfied."; else print ""; end if;
end if;
end for;
end for;
end procedure;