Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions gap/projective/sl4_natural.gi
Comment thread
Till-Eisen marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
###############################################################################
##
## Authors: Till Eisenbrand
## The underlying algorithm is due to Daniel Rademacher; see
## Algorithm 15 ("GoingDownFinalStepSL") in:
## D. Rademacher, "Constructive Recognition of Finite Classical Groups with
## Stingray Elements", Ph.D. thesis, RWTH Aachen University, Germany, 2024.
##
##
## This file provides the function:
##
## RECOG.FindSL2inSL4(G, N)
##
## Purpose:
## Given G = SL(4,q) (q odd), this function finds an embedded copy of
## SL(2,q) inside G as a "stingray subgroup". Concretely, it looks for
## a base change matrix bas such that, in the new basis, the found
## subgroup consists of block matrices of the form
##
## [ A | 0 ]
## [ 0 | I ] with A in SL(2,q).
##
## The function proceeds by:
## 1. Searching for a strong pre-involution t of type 2+2, i.e. a
## non-trivial involution with dim(E_1(t)) = dim(E_{-1}(t)) = 2.
## 2. Building a base change from the eigenspaces of t.
## 3. Drawing random elements from the centraliser C_G(t) via the Bray
## trick (RECOG.CentralisingElementOfInvolution) and filtering for
## those that act trivially on the lower 2x2 block in the new basis.
## Such elements generate the stingray-embedded SL(2,q).
## 4. Stopping as soon as the collected generators are recognised
## (non-constructively) as SL(2,q).
##
## Input:
## G -- a matrix group equal to SL(4,q) for some odd prime power q,
## given by 4x4 matrices over GF(q).
## N -- positive integer: random-element budget.
##
## Returns:
## "fail" if the budget N is exhausted before success, OR a record with
## the following fields:
##
## .U -- a subgroup of G with U isomorphic to SL(2,q), stingray
## embedded in G with respect to the base change bas.
## .bas -- the 4x4 base change matrix bas such that u^bas
## is block-diagonal diag(A, I_2) for every u in U.
## .gens -- list of generators of U as elements of G (i.e. 4x4
## matrices over GF(q)).
## .Nout -- remaining budget after completion (N - number of random
## selections actually used).
##
#############################################################################


RECOG.FindSL2inSL4 := function(G, N)
local n, F, q, one, gens_group, gens_bas,
pr, t, basis1, basism1, bas, basInv,
h, hb, topLeft, bottomRight, ordr, K, slp, Nstart, U;

n := DimensionOfMatrixGroup(G);
F := FieldOfMatrixGroup(G);
q := Size(F);
one := IdentityMat(n, F);
Nstart := N;
slp := [];
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated

if n <> 4 then
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
Error("FindSL2inSL4: <G> must act in dimension 4");
fi;
if q mod 2 = 0 then
Error("FindSL2inSL4: q must be odd");
fi;

pr := ProductReplacer(GeneratorsOfGroup(G));

# find a strong pre-involution: t = x^(|x|/2) of type 2+2.
# RECOG.InvolutionSearcher(pr,ord,0) uses exactly one Next(pr).
t := fail;
while N > 0 do
t := RECOG.InvolutionSearcher(pr, Order, 0);
N := N - 1;
if t <> fail and Length(RECOG.FixspaceMat(t)) = 2 then
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
break;
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
fi;
t := fail;
od;

if t = fail then
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
Print("FindSL2inSL4: out of budget while looking for a strong pre-involution\n");
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
return fail;
fi;

basis1 := RECOG.FixspaceMat(t);
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
basism1 := RECOG.EigenspaceMat(t, -One(F));
basInv := Concatenation(basis1, basism1);
bas := basInv^-1;

gens_bas := [];
gens_group := [];

while N > 0 do
h := RECOG.CentralisingElementOfInvolution(pr, Order, t);
N := N - 1;

# Conjugate h into the eigenbasis of t; in this basis C_G(t)
# is block-diagonal diag(A, B) with A,B in GL(2,q).
hb := basInv * h * bas;
topLeft := hb{[1,2]}{[1,2]};
bottomRight := hb{[3,4]}{[3,4]};

# h^ordr kills the lower block (bottomRight^ordr = I_2) while
# potentially leaving a non-trivial upper block.
ordr := Order(bottomRight);
if topLeft^ordr <> IdentityMat(2, F) then
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
Add(gens_bas, topLeft^ordr);
Add(gens_group, h^ordr);
# Non-constructive recognition: check whether the collected
# 2x2 generators already span SL(2,q).
if RECOG.IsThisSL2Natural(gens_bas,GF(q)) then
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
Comment thread
Till-Eisen marked this conversation as resolved.
Outdated
U := Group(gens_group);
return rec(U := U, bas := bas, gens := gens_group, Nout := N);
fi;
fi;
od;
return fail;
end;
1 change: 1 addition & 0 deletions read.g
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ ReadPackage("recog","gap/projective/almostsimple/lietype.gi");
ReadPackage("recog","gap/projective/almostsimple/hints.gi");
ReadPackage("recog","gap/projective/classicalnatural.gi");
ReadPackage("recog","gap/projective/sl2_natural.gi");
ReadPackage("recog","gap/projective/sl4_natural.gi");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, now that your functions gets loaded, have you tried actually using it, i.e., by modifying RECOG.SLn_constructsl2 to call you code, instead?

ReadPackage("recog","gap/projective/sl.gi");
ReadPackage("recog","gap/projective/AnSnOnFDPM.gi");

Expand Down
31 changes: 31 additions & 0 deletions tst/working/quick/sl4.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
gap> SetInfoLevel(InfoRecog,0); SetInfoLevel(InfoMethSel,0);
gap> START_TEST("sl4.tst");
gap> testFindSL2inSL4 := function(q)
> local G, res, h, hb, F;
> F := GF(q);
> G := SL(4, q);
> res := RECOG.FindSL2inSL4(G, 2000);
> if res = fail then
> return false;
> fi;
> for h in res.gens do
> hb := res.bas^-1 * h * res.bas;
> if hb{[3,4]}{[3,4]} <> IdentityMat(2, F) then
> return false;
> fi;
> if hb{[1,2]}{[3,4]} <> NullMat(2, 2, F) then
> return false;
> fi;
> if hb{[3,4]}{[1,2]} <> NullMat(2, 2, F) then
> return false;
> fi;
> od;
> return true;
> end;;
gap> list := Filtered([3..100], q -> IsOddInt(q) and IsPrimePowerInt(q));;
gap> for q in list do
> if not testFindSL2inSL4(q) then
> Print("FAILED for q = ", q, "\n");
> fi;
> od;
gap> STOP_TEST("sl4.tst");