Quelle obrienmalle.gi
Sprache: unbekannt
|
|
# GAP translation attempt Jan 2004 SL
#**************************************************************/
# Identify the non-abelian simple composition factor */
# of a nearly simple matrix group. */
# Uses: element orders, involution centralizers */
# */
# Step 1: Determine possible underlying characteristic */
# (recursively constructing small invol. central.) */
# */
# Step 2: Identify Lie type groups using LieType () */
# */
# Step 3: Determine degree (if alternating) */
# */
# Step 4: Determine sporadic candidates */
# */
# Gunter Malle & E.A. O'Brien March 2001 */
#**************************************************************/
# SetVerbose ("STCS", 1);
NMR_GENS := 12;
NMR_COMM := 6;
NR1 := 30;
NR2 := 30;
NRINV := 150; # if no element of even order found after NRINV tries,
# assume characteristic 2 type group
Commutators := function (l1, l2)
return Union(List(l1,x->Set(l2,y->Comm(x,y))));
end; # Commutators
ProbablyGroupExponent := function (G)
local l, i, orders, g, o, m;
l := [1];
i := 1;
orders := [];
repeat
g := PseudoRandom (G);
o := Order (g);
AddSet(orders,o);
l[i+1] := Lcm (l[i], o);
i := i+1;
m := Maximum ([1, i - 10]);
until (i > 10) and l[i] = l[m];
return [l[i], orders];
end; # GroupExponent
RandomGensDerived := function (G)
local gens, i, g1, g2;
gens := [];
for i in [1..NMR_COMM] do
g1 := PseudoRandom (G);
g2 := PseudoRandom (G);
AddSet(gens,Comm(g1,g2));
od;
return gens;
end; # RandomGensCommutator
InvolutionModCenter := function (G, g)
local o, x;
o := Order (g);
if o mod 2 = 0 then
while o mod 2 = 0 do
o := o/2;
od;
g := g^o;
if ForAll(GeneratorsOfGroup(G), i->g*i=i*g) then
return One (G);
fi;
for x in GeneratorsOfGroup (G) do
while g^2*x <> x*g^2 do
g := g^2;
od;
od;
return g;
fi;
return One (G);
end;
RandomInvModCenter := function (G)
local i, g, o;
for i in [1..NRINV] do
g := PseudoRandom (G);
o := PossiblyProjectiveOrder (g);
g := InvolutionModCenter (G, g);
if not IsOne(g) then
return [g, true];
fi;
od;
return [One(G), false]; # No involution found
end; # RandomInvModCenter
FindFieldSize := function (H, dim)
local o, qs, i, ree;
o := ProbablyGroupExponent ( H )[1];
qs := [];
for i in [o+1, o-1] do
if IsPrimePowerInt(i) then
AddSet(qs,i);
fi;
od;
ree := false;
if dim = 2 then
if IsPrimePowerInt(2*o-1) and 2*o-1 mod 3 = 0 then
ree := true;
fi;
fi; # to recognize the Ree groups
if (dim = 1) or ree then
for i in [2*o+1, 2*o-1] do
if IsPrimePowerInt(i) then
AddSet(qs,i);
fi;
od;
fi;
if o = 12 then
AddSet(qs,3);
return [qs, false];
fi; # it may be L2 (3)
return [qs, true];
end;
# recognize an L2 (q), given a list of possible q's */
WhichL2q := function (G, qs)
local orders, maxord, q, p;
orders := List([1..NR1], i->PossiblyProjectiveOrder(PseudoRandom(G)));
#some random orders
maxord := Maximum (orders);
for q in qs do
p := Factors(q)[1];
if ForAny(orders, o->2*p mod o <> 0 and (q+1) mod o <> 0 and
(q-1) mod o <> 0) then
RemoveSet(qs,q);
fi;
od;
if not (4 in orders or 8 in orders) then RemoveSet(qs,9); fi;
if not (5 in orders or 10 in orders) then RemoveSet(qs, 5); fi;
return qs;
end; # WhichL2q
# Find a small involution centralizer */
SmallCentralizer := function (G)
local G0, dim, tmp, r1, flag, invs, jf, g, h, x, o,
H, cc, oG, xx, yy;
G0 := G;
dim := 0;
repeat
tmp := RandomInvModCenter(G);
r1 := tmp[1];
flag := tmp[2];
if not flag then
return [G, 0, G, false];
fi;
invs := [];
for jf in [1..NMR_GENS] do
g := PseudoRandom (G);
h := r1*r1^g;
x := InvolutionModCenter (G, h);
if x <> One(G) then
Add(invs, x);
else # element has odd order mod center
o := PossiblyProjectiveOrder (h);
while o mod 2 = 0 do o := o/2; od;
Add (invs, h^ ((o+1)/ 2)/g);
fi;
od;
if invs <> [] then
dim := dim +1;
H := SubgroupNC(G0,invs);
cc := RandomGensDerived (H);
oG := G;
G := SubgroupNC(G0,cc);
xx := RandomGensDerived (G);
G := SubgroupNC(G0, xx);
yy := Commutators ( xx, cc );
if ForAll(yy,i->Order(i)=1) then
return [oG, dim, H, true]; # L2 (q), D_{q+-1}
fi;
fi;
until false;
Error( "Error: SmallCentralizer failed!");
return [G, -1, H];
end; # SmallCentralizer
# given group G, determine its defining field */
DetermineFieldSize := function (G)
local tmp, qs;
tmp := SmallCentralizer (G);
qs := FindFieldSize (tmp[3], tmp[2]);
return qs;
end;
RemoveSome := function (types, ns, orders)
if ns = 7 and not 6 in orders then
ns := 0;
fi;
if ns = 9 then
if 15 in orders then
RemoveSome(types, "U_4 ( 3 )");
else
ns := 0;
fi;
fi;
if ns >= 19 then
if ForAny(orders, o-> not o in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 24, 28, 30, 33, 35]) then
RemoveSet( types,"2E_6 ( 2 )");
fi;
fi;
return [types, ns];
end; # RemoveSome
DegreeAlternating := function (orders)
local degs, prims, m, f, n;
degs := [];
prims := [];
for m in orders do
if m > 1 then
f := Collected(Factors(m));
Sort(f);
n := Sum(f, x->x[1]^x[2]);
if f[1][1] = 2 then n := n+2; fi;
AddSet(degs,n);
UniteSet(prims,Set(f,x->x[1]));
fi;
od;
return [degs, prims];
end; # DegreeAlternating
RecognizeAlternating := function (orders)
local tmp, degs, prims, mindeg, p1, p2, i;
tmp := DegreeAlternating (orders);
degs := tmp[1];
prims := tmp[2];
if Length(degs) = 0 then
return "Unknown";
fi;
mindeg := Maximum (degs); # minimal possible degree
p1 := PrevPrimeInt (mindeg + 1);
p2 := PrevPrimeInt (p1);
if not p1 in prims or not p2 in prims then
return 0;
fi;
if mindeg mod 2 = 1 then
if not (mindeg in orders and mindeg - 2 in orders) then
return 0;
fi;
else
if not mindeg - 1 in orders then
return 0;
fi;
fi;
for i in [3..Minimum (QuoInt(mindeg,2) - 1, 6)] do
if IsPrime (i) and IsPrime (mindeg - i) then
if not i * (mindeg - i) in orders then
return 0;
fi;
elif IsPrime (i) and IsPrime (mindeg - i -1) then
if not i * (mindeg - i - 1) in orders then
return 0;
fi;
fi;
od;
return mindeg;
end; # RecognizeAlternating
RecogniseAlternating := RecognizeAlternating;
SporadicGroupData := [
rec( req := [5,6,8,11],
allowed := [],
name := "M_11"),
rec( req := [6,8,10,11],
allowed := [],
name := "M_12"),
rec( req := [5,6,7,8,11],
allowed := [],
name := "M_22"),
rec( req := [11,14,15,23],
allowed := [6,8],
name := "M_23"),
rec( req := [11,21,23],
allowed := [8,10,12,14,15],
name := "M_24"),
rec( req := [11,15,19],
allowed := [6,7,10],
name := "J_1"),
rec( req := [7,12,15],
allowed := [8,10],
name := "J_2"),
rec( req := [15,17,19],
allowed := [8,9,10,12],
name := "J_3"),
rec( req := [11,20],
allowed := [7,8,10,12,15],
name := "HS"),
rec( req := [11,14,30],
allowed := [8,9,12],
name := "McL"),
rec( req := [11,13],
allowed := [14,15,18,20,21,24],
name := "Suz"),
rec( req := [26,29],
allowed := [14,15,16,20,24],
name := "Ru"),
rec( req := [22,23,24,30],
allowed := [14,18,20,21],
name := "Co_3"),
rec( req := [16,23,28,30],
allowed := [11,18,20,24],
name := "Co_2"),
rec( req := [33,42],
allowed := [16,22,23,24,26,28,35,36,39,40,60],
name := "Co_1"),
rec( req := [19,28,31],
allowed := [11,12,15,16,19,20,28,31],
name := "ON"),
rec( req := [13,24,30],
allowed := [14,16,18,20,21,22],
name := "Fi_22"),
rec( req := [17,28],
allowed := [8,10,12,15,21],
name := "He"),
rec( req := [31,67],
allowed := [18,22,24,25,28,30,33,37,40,42],
name := "Ly"),
rec( req := [37,43],
allowed := [16,23,24,28,29,30,31,33,35,40,42,44,66],
name := "J_4")];
# is 15 not needed here?
RecognizeSporadic := function (orders)
local maxords, spors, r;
orders := Set(orders);
maxords := Filtered(orders, i-> Number(orders,j -> j mod i = 0)=1);
spors := [];
for r in SporadicGroupData do
if ForAll(r.req, o->o in maxords) and
ForAll(maxords, o->o in r.allowed or o in r.req) then
Add(spors,r.name);
fi;
od;
return spors;
end; # RecognizeSporadic
RecogniseSporadic := RecognizeSporadic;
IdentifySimple := function (G0)
local NmrTries, limit, d, orders, NRtries, ct, tmp, G,
dim, H, flag, qs, flag2, ps, types, p, erg, ns,
spors, deg;
NmrTries := ValueOption("NmrTries");
if NmrTries = fail then
NmrTries := 15;
fi;
if IsMatrixGroup(G0) then
deg := DimensionOfMatrixGroup(G0);
else
deg := 100;
fi;
# /* replace G0 by successive terms of its derived series
# until we obtain a perfect group; if there are more
# than 3 iterations, then we can conclude that
# G/Z (F^* (G)) is probably not almost simple */
limit := 0;
while IsProbablyPerfect (G0) = false and limit < 4 do
limit := limit + 1;
G0 := DerivedSubgroupApproximation (G0);
if IsTrivial(G0) then
return [false];
fi;
od;
if limit > 4 then
return [false, "G0 is not quasi-simple"];
fi;
if IsMatrixGroup(G0) then
d := DimensionOfMatrixGroup(G0);
else
d := 100; # I dunno
fi;
orders := [];
NRtries := 0;
repeat
NRtries := NRtries + 1;
ct := 0;
repeat
tmp := SmallCentralizer (G0);
G := tmp[1];
dim := tmp[2];
H := tmp[3];
flag := tmp[4];
if flag then
tmp := FindFieldSize(H, dim);
qs := tmp[1];
flag2 := tmp[2];
qs := WhichL2q (G, qs);
ct := ct + 1;
else
qs := [2];
fi;
until Length(qs) >= 1 or ct >= 6;
UniteSet(orders,Set([1..NR2 + 4*d], i-> PossiblyProjectiveOrder(PseudoRandom(G0))));
ps := Set(qs, q->Factors(q)[1]);
AddSet(ps,2);
types := [];
for p in ps do
erg := LieType (G0, p, orders, 30 + 10 * deg);
if not IsRecognitionOutcome(erg) then
AddSet(types,erg);
fi;
od;
ns := RecognizeAlternating (orders);
if ns <> "Unknown" then
tmp := RemoveSome (types, ns, orders);
types := tmp[1];
ns := tmp[2];
if ns <> 0 then
AddSet(types,Concatenation("A_",String(ns)));
fi;
fi;
spors := RecognizeSporadic (orders);
types := Union(types, spors);
if Length(types) >= 1 then
if Length(types) = 1 then
return [true, types[1]];
else
return [true, types];
fi;
fi;
until Length(types) > 0 or NRtries > NmrTries;
Print("Not recognized after ", NmrTries, " tries; qs = ",qs,"\n");
return [false];
end; # IdentifySimple
InstallNonConstructiveRecognizer(function(g)
local res;
res := IdentifySimple(g);
if res[1] = true then
RecognitionInfo(g).Name := res[2];
return res[2];
else
return RO_NO_LUCK;
fi;
end,
"Malle and O'Brien code translated into GAP");
[ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet)
]
|
2026-04-02
|