Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4f776ed
Changes in Unitary and Orthogonal
aniemeyer Dec 9, 2020
daf2543
Quicker way to get first std basis vector
fingolfin Dec 10, 2020
7cbdf0e
General cleanup in classical.gi
fingolfin Dec 10, 2020
3a23987
Add TODOs
ssiccha May 11, 2021
e28750b
DisplayRecog
ssiccha May 11, 2021
ea0591a
WIP RECOG.NonGenericLinear
ssiccha May 11, 2021
ecc81a3
Fixes for groups of Omega+ type
ssiccha Jan 13, 2021
349df2c
WIP Fixes unitary
ssiccha Aug 4, 2021
08c8c0d
Merge branch 'master' into AN/classical
fingolfin Dec 9, 2025
59a7d27
Make the Omega(+1,8,5) case a lot faster
fingolfin Dec 9, 2025
fe2f1d4
used ProjectiveActionHomomorphismMatrixGroup when possible
Dec 11, 2025
1b0bb36
Update gap/matrix/classical.gi
fingolfin Dec 11, 2025
3378898
Apply suggestions from code review
fingolfin Dec 11, 2025
ea3061f
checked conformal obrit cases
Dec 11, 2025
0e27085
only compute Orbit length once
Dec 11, 2025
b118b06
comments and improved 2.A7
Dec 11, 2025
69bc7d3
Merge branch 'master' into AN/classical
fingolfin Dec 11, 2025
200ed85
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
29f23c8
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
3a524c0
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
a666c08
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
1baca5b
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
6678c6c
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
680568e
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
23901c3
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
cfde50a
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
0b617ff
Update gap/matrix/classical.gi
aniemeyer Dec 12, 2025
bde2cd2
Add test sample for Alice
fingolfin Dec 12, 2025
d3931cb
more tests
Dec 30, 2025
211b90b
some tests/bug fixes
Dec 30, 2025
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
195 changes: 134 additions & 61 deletions gap/matrix/classical.gi
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,47 @@
##
## SPDX-License-Identifier: GPL-3.0-or-later
##
## This file contains an implementation of the non-constructive recognition
## algorithms for classical groups in their natural representation by
## Niemeyer and Praeger.
## This file contains an implementation of the naming algorithms
## (non-constructive recognition algorithms) for classical groups in their
## natural representation by Niemeyer and Praeger.
##
## A description of them can be found in [NP97], [NP98], and [NP99].
## Details of the algorithms implemented here are in the following publications.
##
## [NP98] Alice C. Niemeyer and Cheryl E. Praeger
## "A Recognition Algorithm for Classical Groups over Finite Fields",
## Proc. London Math. Soc (3) 77, 1998, 117-169.
##
## [NP97] Alice C. Niemeyer and Cheryl E. Praeger
## "Implementing a Recognition Algorithm for Classical Groups"
## "Groups and Computation II", Amer. Math. Soc. DIMACS Series 28, 1997.
##
## This implementation uses some algorithms described elsewhere, in:
## [CLG97a], [CLG97b], and [CLGM+95].
## [NP99] Alice C. Niemeyer and Cheryl E. Praeger
## "A Recognition Algorithm for Non-Generic Classical Groups over
## Finite Fields", J. Austral. Math. Soc. (Series A)67 , 223-253, 1999.
##
## This implementation uses some algorithms described elsewhere:
##
## [CLG97a] Frank Celler and C.R. Leedham-Green
## "Calculating the order of an invertible matrix",
## "Groups and Computation II", Amer. Math. Soc. DIMACS Series 28, 1997.
##
## [CLG97b] Frank Celler and C.R. Leedham-Green
## "A non-constructive recognition algorithm for the special linear
## and other classical groups"
## "Groups and Computation II", Amer. Math. Soc. DIMACS Series 28, 1997.
##
## In this implementation we use the irreducibility test of the algorithm
## described in [CL97b], which can often avoid an application of the Meataxe
## algorithm.
##
## An overview on applications of ppd-elements, see
##
## [Pra99] Cheryl E. Praeger,
## "Primitive prime divisor elements in finite classical groups",
## Proc. of Groups St. Andrews in Bath 1997, Cambridge University
## Press, 1999.
##
## - In this implementation we use the irreducibility test of the algorithm
## described in [CLG97b], which can often avoid an application of the
## Meataxe algorithm.
##
## For an overview, see also [Pra99].
##
#############################################################################

Expand Down Expand Up @@ -139,9 +166,15 @@ end;



# Test to check whether the group contains both a large ppd element
# and a basic ppd element
# TODO: Better comments...
# The naming algorithm for classical groups is divided into two
# parts: A version that applies to classical groups for sufficiently
# large parameters, called generic parameters, as described in [NP98, Def.3.2],
# and a part that applies to smaller cases of classical groups, where
# the exsistence of sufficiently informative ppd elements is not guaranteed.
# The naming algorithm for these cases is decribed in [NP99] and implemented
# in the functions whose name starts with NonGeneric below. This function tests
# whether the parameters are generic or not.
#
BindRecogMethod(FindHomMethodsClassical, "IsGenericParameters",
"tests whether group has generic parameters",
function( recognise, grp )
Expand Down Expand Up @@ -211,10 +244,11 @@ function( recognise, grp )
end);


# Generate elements until we find the required ppd type
# elements...monte yes
# TODO: Better comments

#
# In the case of generic parameters we need to have found at least
# two ppd elements, one large and one basic. If we have not yet
# found them, we return TemporaryFailure and have to inspect
# more random elements.
BindRecogMethod(FindHomMethodsClassical, "IsGeneric",
"tests whether group is generic",
function (recognise, grp)
Expand All @@ -232,8 +266,16 @@ function (recognise, grp)
return NeverApplicable;
end);

#enough info to rule out extension field groups...?
#TODO: comments...


# Once we have verified that the group has generic parameters we need to
# rule out the extension field case, that is we have to show the group
# cannot be embedded into GL(d/b,q^b).b. To rule this out, we need to find a
# b-witness for each of the pi(d) distinct prime divisors b of d, or
# in some cases a pair of witnesses, as discussed in Section 3.3 of
# [NP98]. The function RuledOutExtField() tests whether we can
# deduce that the group does not preserve an extension field structure.

BindRecogMethod(FindHomMethodsClassical, "RuledOutExtField",
"tests whether extension field case is ruled out",
function (recognise, grp)
Expand Down Expand Up @@ -339,6 +381,19 @@ function (recognise, grp)
fi;
end);


# Methods to rule out the nearly simple groups
#
# We assume that we have already tested that the group acts irreducibly
# on the underlying vector space and has a ppd(d,q;e_1)-element and a
# ppd(d,q;e_2)-element for d/2 < e_1 < e_2 <= d of which at least one is
# large and one is basic. The nearly simple groups that can have such
# ppd elements are listed in Tables 6 and 7 in [NP98]. These could
# arise as the commutator subgroup of the given group. In these
# tables also elements are listed that occur in a classical group put
# not in these nearly simple groups. If we find such elements, these
# groups are thereby ruled out.
#
BindRecogMethod(FindHomMethodsClassical, "IsNotAlternating",
"tests whether alternating groups are ruled out",
function( recognise, grp )
Expand Down Expand Up @@ -376,23 +431,12 @@ function( recognise, grp )
fi;
fi;


if q >= 23 then
# TODO Check Magma Code
o := Order( recognise.g );
if o mod 25 = 0 then
if 4 in recognise.LE then
Info( InfoClassical, 2, "G' not alternating;");
recognise.isNotAlternating := true;
return false;
fi;
o := Collected( Factors (o) );
for i in o do
if i[1] >= 11 then
Info( InfoClassical, 2, "G' not alternating;");
recognise.isNotAlternating := true;
return false;
fi;
od;

if recognise.n > 15 then
AddSet (recognise.possibleNearlySimple, "2.A7");
Expand Down Expand Up @@ -438,7 +482,7 @@ function( recognise, grp )
if d in [5, 6] then
ord := Order(g);
if (ord mod 121=0 or (d=5 and ord=13) or (d=6 and ord=7)) then
Info( InfoClassical, 2, "G' is not a Mathieu group;");
Info( InfoClassical, 2, "G' is not a Mathieu group.;");
recognise.isNotMathieu := true;
return false;
fi;
Expand All @@ -452,23 +496,25 @@ function( recognise, grp )


# TODO Check how big n should be
# if G' might be a Mathieu group, add the Atlas name to
# recognise.possibleNearlySimple
if d = 5 then
if recognise.n > 15 then
AddSet(recognise.possibleNearlySimple, "M_11" );
Info( InfoClassical, 2, "G' might be M_11;");
AddSet(recognise.possibleNearlySimple, "M11" );
Info( InfoClassical, 2, "G' might be M11;");
return fail;
fi;
elif d = 6 then
if recognise.n > 15 then
AddSet(recognise.possibleNearlySimple, "2M_12" );
Info( InfoClassical, 2, "G' might be 2M_12;");
AddSet(recognise.possibleNearlySimple, "2.M12" );
Info( InfoClassical, 2, "G' might be 2.M12;");
return fail;
fi;
else
if recognise.n > 15 then
AddSet(recognise.possibleNearlySimple, "M_23" );
AddSet(recognise.possibleNearlySimple, "M_24" );
Info( InfoClassical, 2, "G' might be M_23 or M_24;");
AddSet(recognise.possibleNearlySimple, "M23" );
AddSet(recognise.possibleNearlySimple, "M24" );
Info( InfoClassical, 2, "G' might be M23 or M24;");
return fail;
fi;
fi;
Expand Down Expand Up @@ -502,11 +548,20 @@ function (recognise, grp)
fi;

if d = 3 and (q = 5 or q = 2) then
Info( InfoClassical, 2, "G' is not PSL(2,7)");
if q = 5 then
Info( InfoClassical, 2, "G' is not PSL(2,7)");
fi;
# Note PSL(2,7) is isomorphic to PSL(3,2), so don't print this message
recognise.isNotPSL := true;
return false;
fi;

if [d,q] = [5,5] or [d,q] = [5,11] then
Info( InfoClassical, 2, "G' not PSL(2,11);");
recognise.isNotPSL := true;
return false;
fi;

if d = 6 and q = 2 then
Info( InfoClassical, 2, "G' is not PSL(2,11)");
recognise.isNotPSL := true;
Expand Down Expand Up @@ -536,7 +591,11 @@ function (recognise, grp)
fi;
else
if p = 3 or p = 7 or 2 in LE then
Info( InfoClassical, 2, "G' not PSL(2,7);");
# we are only certain that PSL(2,7) is ruled if 2 in LE
# and the cases p=3 or p=7 cannot have the required ppds
if 2 in LE then
Info( InfoClassical, 2, "G' not PSL(2,7);");
fi;
recognise.isNotPSL := true;
return false;
fi;
Expand Down Expand Up @@ -567,15 +626,15 @@ function (recognise, grp)
recognise.isNotPSL := true;
return false;
fi;
else
Info( InfoClassical, 2, "G' not PSL(2,r);");
recognise.isNotPSL := true;
return false;
#else
#Info( InfoClassical, 2, "G' not PSL(2,r);");
#recognise.isNotPSL := true;
#return false;
fi;


if recognise.n > 15 and Length(recognise.E) > 2 then
str := Concatenation("PSL(2,",Int(2*E[2]+1));
if recognise.n > 15 and Length(recognise.E) = 2 then
str := Concatenation("PSL(2,", String(Int(2*E[2]+1)));
str := Concatenation(str, ")");
Info( InfoClassical, 2, "G' might be ", str);
AddSet( recognise.possibleNearlySimple, str );
Expand Down Expand Up @@ -652,6 +711,7 @@ function(recognise, grp)
else
AddSet(recognise.E,ppd[1]);
recognise.currentgcd := GcdInt( recognise.currentgcd, ppd[1] );
# check whether we have a large ppd-element
if ppd[2] = true then
AddSet(recognise.LE,ppd[1]);
fi;
Expand All @@ -670,6 +730,7 @@ function(recognise, grp)
fi;
fi;
if recognise.needE2 = true then
# these are ppd(d,q;e)-elmenets with e=d/2
ppd := IsPpdElementD2(f, cpol, d, recognise.q, 1);
if ppd <> false then
str := " Found a large and special ppd(";
Expand Down Expand Up @@ -843,7 +904,10 @@ end);


# Compute the degrees of the irreducible factors of
# the characteristic polynomial <cpol>
# the characteristic polynomial recognise.cpol
# These might already yield enough information to show
# that the group acts irreducible without calling
# the Meataxe. This function is described in [CLG97b].
BindRecogMethod(FindHomMethodsClassical, "IsReducible",
"tests whether current random element rules out reducible",
function( recognise, grp )
Expand Down Expand Up @@ -1712,7 +1776,7 @@ end);
BindRecogMethod(FindHomMethodsClassical, "NonGenericOrthogonalPlus",
"tests whether group is non-generic O+",
function(recognise,grp)
local d, q, gp1, gp2, CheckFlag, pgrp, sc, orbs, isHypForm;
local d, q, gp1, gp2, CheckFlag, pgrp, sc, orbs, isHypForm, ol;

isHypForm := f -> IsSesquilinearForm(f) and IsHyperbolicForm(f);

Expand Down Expand Up @@ -1901,10 +1965,10 @@ function(recognise,grp)
return CheckFlag();
fi;
elif d = 4 and q = 4 then
# TODO: check all occurences of Orbit and Orbits for the "conformals
# can merge orbits"-bug.

if not Length( Orbit( grp, IdentityMat(d, GF(q))[1]) ) in [75,60] then
# the conformal group can have orbits of length 75 and 180
# the group Omega can have orbits of lengths 75 and 60
ol := Length(Orbit(grp, IdentityMat(d, GF(q))[1]));
if not ol in [60,75,180] then
return false;
fi;
pgrp := Image(ProjectiveActionHomomorphismMatrixGroup(grp));
Expand All @@ -1926,9 +1990,13 @@ function(recognise,grp)
fi;
elif d = 4 and q = 5 then
## Added fast test 4.7.2019 ACN
if not Length( Orbit( grp, IdentityMat(d, GF(q))[1]) ) in [144,120] then
return false;
# the conformal group can have orbits of length 144 and 480
# the group Omega can have orbits of lengths 144 and 120
ol := Length(Orbit(grp, IdentityMat(d, GF(q))[1]));
if not ol mod 144 = 0 and not ol mod 120 = 0 then
return false;
fi;

## The projective Group has half order of Omega
## Fix 4.7.2019
pgrp := Image(ProjectiveActionHomomorphismMatrixGroup(grp));
Expand All @@ -1940,9 +2008,13 @@ function(recognise,grp)
fi;
elif d = 4 and q = 7 then
## Added fast test 4.7.2019 ACN
if not Length( Orbit( grp, IdentityMat(d, GF(q))[1]) ) in [384,336] then
# the conformal group can have orbits of length 384 and 2016
# the group Omega can have orbits of lengths 384 and 336
ol := Length(Orbit(grp, IdentityMat(d, GF(q))[1]));
if not ol mod 384 = 0 and not ol mod 336 = 0 then
return false;
fi;

pgrp := Image(ProjectiveActionHomomorphismMatrixGroup(grp));
if Size(pgrp) mod 28224 <> 0 then
recognise.isOmegaContained := false;
Expand All @@ -1962,9 +2034,13 @@ function(recognise,grp)
fi;
elif d = 4 and q = 9 then
## Added fast test 4.7.2019 ACN
if not Length( Orbit( grp, IdentityMat(d, GF(q))[1]) ) in [800,720] then
# the conformal group can have orbits of length 800 and 5760
# the group Omega can have orbits of lengths 800 and 720
ol := Length(Orbit(grp, IdentityMat(d, GF(q))[1]));
if not ol mod 800 = 0 and not ol mod 720 = 0 then
return false;
fi;

pgrp := Image(ProjectiveActionHomomorphismMatrixGroup(grp));
if Size(pgrp) mod 129600 <> 0 then
recognise.isOmegaContained := false;
Expand Down Expand Up @@ -2114,7 +2190,7 @@ function( recognise, grp )
recognise.needForms := true;
return fail;
fi;
Info(InfoClassical,2,"group contains SOo(",
Info(InfoClassical,2,"group contains Omega(",
recognise.d, ", ", recognise.q, ");");
recognise.isOmegaContained := true;
return true;
Expand Down Expand Up @@ -2439,9 +2515,6 @@ DisplayRecog := function( r )
if Length(r.E2) > 0 then
Print("E2 : ", r.E2, "\n" );
fi;
if Length(r.LE2) > 0 then
Print("LE2 : ", r.LE2, "\n" );
fi;
if Length(r.BE2) > 0 then
Print("BE2 : ", r.BE2, "\n" );
fi;
Expand Down
Loading
Loading