We show the computations that are needed in order to prove the following statements from the paper Finite groups can be generated by a $\pi$-subgroup and a $\pi'$-subgroup.

Let $S$ be a sporadic simple group and let $P$ be a Sylow $2$-subgroup of $S$. If $1 \neq x \in S$, then $S = \langle P, x^g \rangle$ for some $g \in S$.

Let $S$ be a sporadic simple group and let $p \leq q$ be primes each dividing $|S|$. Then $S$ can be generated by a Sylow $p$-subgroup and a Sylow $q$-subgroup.

Let $S$ be a sporadic simple group, $p$ be a prime dividing $|S|$, and $P$ be a Sylow $p$-subgroup of $S$. If $1 \neq x \in S$, then $S = \langle P, x^g \rangle$ for some $g \in S$.

We will use OSCAR for the computations. Julia's JSON and HTTP packages will also be needed.

In [1]:

```
using Oscar; using JSON; using HTTP;
```

```
----- ----- ----- - -----
| | | | | | | | | |
| | | | | | | |
| | ----- | | | |-----
| | | | |-----| | |
| | | | | | | | | |
----- ----- ----- - - - -
...combining (and extending) ANTIC, GAP, Polymake and Singular
Version 0.11.0 ...
... which comes with absolutely no warranty whatsoever
Type: '?Oscar' for more information
(c) 2019-2022 by The OSCAR Development Team
```

First we show Proposition 2.2. Let $S$ be a sporadic simple group, fix a Sylow $2$-subgroup $P$ of $S$, and let $x$ be a nonidentity element in $S$. We use known information about maximal subgroups of $S$ to show that $x^S$ is not a subset of the union of those maximal subgroups in $S$ that contain $P$.

Let $M$ be a maximal subgroup of $S$ with the property $P \leq M$. The number of $S$-conjugates of $M$ that contain $P$ is equal to $|N_S(P)|/|N_M(P)| \leq [N_S(P):P]$, thus these subgroups can contain at most $[N_S(P):P] |x^S \cap M|$ elements from the class $x^S$.

Thus the number of elements in $x^S$ that generate a proper subgroup of $S$ together with $P$ is bounded from above by $[N_S(P):P] \sum_M |x^S \cap M|$, where the sum is taken over representatives $M$ of conjugacy classes of maximal subgroups of odd index in $S$.

Let $1_M^S$ denote the permutation character of the action of $S$ on the cosets of $M$. We have $|x^S \cap M| = |x^S| 1_M^S(x) / 1_M^S(1)$. Hence we are done when we show that $$ [N_S(P):P] \sum_M 1_M^S(x) / 1_M^S(1) < 1 $$ holds.

The numbers $[N_S(P):P]$ can be read off from Wil98, Table I. Here we use the fact that the character table of the Sylow $2$-normalizer of $S$ is available except if $S$ is one of $Co_1$, $J_4$, $F_{3+}$, $B$, or $M$, and that the Sylow $2$-subgroup is self-normalizing in these cases.

In [2]:

```
spor_names = all_character_table_names(is_sporadic_simple => true,
is_duplicate_table => false; ordered_by = order);
println(spor_names)
```

In [3]:

```
normindices = Dict("Co1" => 1, "J4" => 1, "F3+" => 1, "B" => 1, "M" => 1);
for name in spor_names
n = character_table("$(name)N2")
if n == nothing
println(name)
else
two_part = 1
ord = order(n)
while iseven(ord)
ord = div(ord, 2)
two_part = 2 * two_part
end
normindices[name] = div(order(n), two_part)
end
end
```

Co1 J4 F3+ B M

For all sporadic simple groups $S$ except the Monster group, the primitive permutation characters $1_M^S$ can be computed from the data about maximal subgroups contained in the library of character tables.

Here we omit the computations for the Baby Monster group because they need a long time, due to the fact that the class fusion of one maximal subgroup is currently not known. (It turns out that the result does not depend on the class fusion, but computing this is lengthy.)

We see that the left hand side of the above inequality is always less than or equal to $3/5$, in particular it is less than $1$.

In [4]:

```
maxbound = [];
for name in filter(x -> x != "M" && x != "B", spor_names)
t = character_table(name)
mx = [character_table(m) for m in maxes(t)]
odd = filter(s -> isodd(div(order(t), order(s))), mx)
primperm = [trivial_character(s)^t for s in odd]
wsum = normindices[name] * sum(pi -> [ZZ(x.data) // degree(pi) for x in values(pi)], primperm)
push!(maxbound, [name, maximum(wsum[2:length(wsum)])])
end
sort!(maxbound, by = x -> -x[2]);
println(maxbound[1])
```

Any["J2", 3//5]

The Monster group is known to contain exactly five classes of maximal subgroups of odd index, of the following structures.

$2^{1+24}.Co_1$ (the normalizer of a $2B$ element in the Monster), $2^{10+16}.O_{10}^+(2)$, $2^{2+11+22}.(M_{24} \times S_3)$, $2^{5+10+20}.(S_3 \times L_5(2))$, $[2^{39}].(L_3(2) \times 3S_6)$.

The corresponding permutation characters are known, see the documentation of the character table library. First we read the information about the known primitive permutation characters of the Monster into the Julia session, and extract the primitive permutation characters of odd degree.

In [5]:

```
filename = "http://www.math.rwth-aachen.de/~Thomas.Breuer/ctbllib/data/prim_perm_M.json";
str = String(HTTP.request("GET", filename; verbose = 0).body);
monster_prim_data = JSON.parse(str; inttype = BigInt)[2];
length(monster_prim_data)
```

Out[5]:

44

In [6]:

```
t = character_table("M");
monstermaxindices = [];
monstermaxtables = [];
for entry in monster_prim_data
if length(entry) == 1
s = character_table(entry[1])
push!(monstermaxtables, s)
push!(monstermaxindices, div(order(t), order(s)))
else
push!(monstermaxtables, nothing)
push!(monstermaxindices, entry[2][1])
end
end;
odd_prim = Vector{fmpz}[];
for i in 1:length(monster_prim_data)
if isodd(monstermaxindices[i])
if monstermaxtables[i] != nothing
push!(odd_prim, [ZZ(x.data) for x in trivial_character(monstermaxtables[i])^t])
else
push!(odd_prim, Vector{fmpz}(monster_prim_data[i][2]))
end
end
end;
length(odd_prim)
```

Out[6]:

5

Now we can use the same approach as before.

In [7]:

```
wsum = normindices["M"] * sum(pi -> [x // pi[1] for x in values(pi)], odd_prim);
mx = maximum(wsum[2:length(wsum)])
```

Out[7]:

12784979//103007903752128375

Next we show Theorem 7.1 and its stronger version stated above. Let us first assume that $S$ is not the Monster.

As a first step, we generalize the approach from the above computations in order to check for which prime divisors $p$ of $|S|$ and for which nontrivial conjugacy classes $x^S$ of $S$ the group $S$ is generated by a Sylow $p$-subgroup $P$ together with a conjugate of $x$.

The upper bound $[N_S(P):P]$ for $|N_S(P)|/|N_M(P)|$, for a maximal subgroup $M$ of $S$ that contains $P$, is not good enough in some of the cases considered here. Instead of it, we compute the upper bound $u(S, M, p)$ which is defined as follows; we assume that we know $|N_S(P)|$.

- If $P$ is cyclic then we can compute $|N_M(P)|$ from the character table of $M$, and set $u(S, M, p) = |N_S(P)| / |N_M(P)|$.
- Otherwise, if $P$ is normal in $M$, we set $u(S, M, p) = |N_S(P)| / |M|$.
- Otherwise, if we know a subgroup $U$ of $M$ such that $P$ is a proper normal subgroup of $U$, we set $u(S, M, p) = |N_S(P)| / |U|$.
- Otherwise, we set $u(S, M, p) = |N_S(P)| / |P|$.

In [8]:

```
function upper_bound( tblS, tblM, p )
facts = collect(factor(order(tblS)))
pos = findfirst(x -> x[1] == p, facts)
ppart = p^facts[pos][2]
ppartposS = filter(i -> orders_class_representatives(tblS)[i] == ppart, 1:nrows(tblS))
if 0 < length(ppartposS)
# P is cyclic.
if tblM == nothing
return (orders_centralizers(tblS)[ppartposS[1]] * euler_phi(ppart)
// length(ppartposS)) // ppart
else
ppartposM = filter(i -> orders_class_representatives(tblM)[i] == ppart, 1:nrows(tblM))
return (orders_centralizers(tblS)[ppartposS[1]] * euler_phi(ppart)
// length(ppartposS)) //
(orders_centralizers(tblM)[ppartposM[1]] * euler_phi(ppart)
// length(ppartposM))
end
end
# Compute |N_S(P)|.
n = character_table("$(identifier(tblS))N$p")
if n != nothing
N_S = order(n)
elseif p == 2
N_S = ppart * normindices[identifier(tblS)]
elseif identifier(tblS) == "M" && p == 3
# The Sylow 3-normalizer is contained in 3^(3+2+6+6):(L3(3)xSD16)
N_S = ppart * 2^6
elseif identifier(tblS) == "F3+" && p == 3
N_S = ppart * 8
else
error("cannot compute |N_S(P)|")
end
if tblM == nothing
return N_S // ppart
elseif sum(class_lengths(tblM)[class_positions_of_pcore(tblM, p)]) == ppart
# P is normal in M.
return N_S // order(tblM)
end
# Inspect known character tables of subgroups of M.
f = N_S // ppart
for subname in Oscar.names_of_fusion_sources(tblM)
u = character_table(subname)
if class_positions_of_kernel(known_class_fusion(u, tblM)[2]) == [1] &&
sum([order(u) // x for x in orders_centralizers(u)[class_positions_of_pcore(u, p)]]) == ppart
f = min(f, N_S // order(u));
end
end
return f;
end;
```

We run over the sporadic simple groups (except the Monster), and collect in the list

For the proof of ,
we can discard all those entries from the list of "bad" $p$ and $x$ where $x$ is not a $q$-element, for some prime $q$, or where another nonidentity $q$-element exists that does not occur in the list. This is done by collecting a second list

For the proof of the stronger version, we will later explicitly compute group elements from the classes in question that generate $S$ together with a Sylow $p$-subgroup.

(The only technical complication is that the class fusion of maximal subgroups of the type $(2^2 \times F_4(2)):2$ of the Baby Monster is currently not known, thus we cannot simply induce the trivial character in this case. However, the permutation character is uniquely determined by the two character tables.)

In [9]:

```
badcases_thm = [];
badcases_strong = [];
for name in filter(x -> x != "M" && x != "B", spor_names)
t = character_table(name)
orders = orders_class_representatives(t)
n = nrows(t)
mx = [character_table(m) for m in maxes(t)]
for p in prime_divisors(order(t))
primperm = []
good = filter(s -> mod(order(t) // order(s), p) != 0, mx)
for s in good
if known_class_fusion(s, t)[1]
push!(primperm, [ZZ(x.data) for x in trivial_character(s)^t])
else
ind = Set([induced_class_function(trivial_character(s), t, map)
for map in possible_class_fusions(s, t)])
length(ind) == 1 || error("permutation character not uniquely determined")
push!(primperm, [ZZ(x.data) for x in pop!(ind)])
end
end
weighted = []
for i in 1:length(good)
bd = upper_bound(t, good[i], p)
pi = primperm[i]
push!(weighted, [bd * pi[j] // pi[1] for j in 1:length(pi)])
end
sumx = sum(weighted)
badpos = filter(i -> sumx[i] >= 1, 2:length(sumx))
if length(badpos) != 0
# We have to deal with this case for the stronger variant of Theorem 1.7.
push!(badcases_strong, (name, p, copy(badpos)))
for i in copy(badpos)
facts = collect(factor(orders[i]))
if length(facts) == 1
q = facts[1][1]
# If we know some `q`-element for which the bound is good enough
# then we need not deal with this class for Theorem 1.7.
if any(j -> mod(orders[j], q) == 0 &&
length(collect(factor(orders[j]))) == 1 &&
!(j in badpos), 2:n)
setdiff!(badpos, i)
end
end
end
length(badpos) != 0 && push!(badcases_thm, (name, p, badpos))
end
end
end;
```

In [10]:

```
badcases_thm
```

Out[10]:

2-element Vector{Any}: ("M23", 3, [3]) ("HS", 3, [4, 11])

In [11]:

```
badcases_strong
```

Out[11]:

18-element Vector{Any}: ("M11", 5, [2]) ("M12", 5, [3, 4]) ("M22", 5, [2]) ("M22", 3, [2]) ("J2", 3, [2]) ("M23", 5, [2]) ("M23", 7, [2]) ("M23", 3, [2, 3]) ("HS", 5, [2, 3, 5]) ("HS", 3, [2, 3, 4, 5, 6, 7, 9, 11]) ("M24", 5, [2, 4]) ("M24", 7, [2, 4]) ("He", 5, [2]) ("Co2", 3, [2, 3]) ("Fi22", 5, [2]) ("Fi22", 7, [2]) ("Fi23", 5, [2, 3, 5]) ("Fi23", 7, [2])

Most of these open cases can be ruled out by constructing the group $S$ and a Sylow $p$-subgroup $P$ in question and then finding explicit elements $x$ such that $S$ is generated by $P$ and $x$. For that, we use the data from the ATLAS of Group Representations .

hier!!!

The following function tries to find random elements from all conjugacy classes of nonidentity elements that have the desired property. It returns

In [12]:

```
function prove_generation(name, prg, p)
S = atlas_group(name)
P = sylow_subgroup(S, p)[1]
reps = evaluate(prg, gens(S))
good = elem_type(S)[]
for x in filter(!isone, reps)
U = P
g = x
while order(U) < order(S)
g = x^rand(S)
U = sub(S, vcat(gens(P), [g]))[1]
end
push!(good, g)
end
return (P, good)
end;
```

In [13]:

```
for (name, p, badpos) in badcases_strong
prg = atlas_program(name, :classes)
if prg == nothing
println("no classes script for ", (name, p, badpos))
else
prove_generation(name, prg, p)
end
end
```

In the remaining cases, we show only the generation property for the class representatives in the list. These are involutions from the class

A

In [14]:

```
S = atlas_group("He");
x = rand(S);
while order(x) != 10 x = rand(S); end
x = x^5;
P5 = sylow_subgroup(S, 5)[1];
g = x^rand(S);
U = sub(S, vcat(gens(P5), [g]))[1]
while order(U) != order(S)
g = x^rand(S)
U = sub(S, vcat(gens(P5), [g]))[1]
end
```

A

In [15]:

```
S = atlas_group("Fi22");
x = rand(S);
while order(x) != 30 x = rand(S); end
x = x^15;
P5 = sylow_subgroup(S, 5)[1];
g = x^rand(S);
U = sub(S, vcat(gens(P5), [g]))[1]
while order(U) != order(S)
g = x^rand(S)
U = sub(S, vcat(gens(P5), [g]))[1]
end
P7 = sylow_subgroup(S, 7)[1];
g = x^rand(S);
U = sub(S, vcat(gens(P7), [g]))[1]
while order(U) != order(S)
g = x^rand(S);
U = sub(S, vcat(gens(P7), [g]))[1]
end
```

A

In [16]:

```
S = atlas_group("Fi23");
x = rand(S);
while order(x) != 42 x = rand(S); end
x = x^21;
P5 = sylow_subgroup(S, 5)[1];
g = x^rand(S);
U = sub(S, vcat(gens(P5), [g]))[1]
while order(U) != order(S)
g = x^rand(S)
U = sub(S, vcat(gens(P5), [g]))[1]
end
P7 = sylow_subgroup(S, 7)[1];
g = x^rand(S);
U = sub(S, vcat(gens(P7), [g]))[1]
while order(U) != order(S)
g = x^rand(S);
U = sub(S, vcat(gens(P7), [g]))[1]
end
```

A

In [17]:

```
x60 = rand(S);
while order(x60) != 60 x60 = rand(S); end
x = x60^30;
g = x^rand(S);
U = sub(S, vcat(gens(P5), [g]))[1]
while order(U) != order(S)
g = x^rand(S)
U = sub(S, vcat(gens(P5), [g]))[1]
end
```

A

In [18]:

```
x = rand(S);
while order(x) != 60 x = rand(S); end
x = x60^20;
g = x^rand(S);
U = sub(S, vcat(gens(P5), [g]))[1]
while order(U) != order(S)
g = x^rand(S)
U = sub(S, vcat(gens(P5), [g]))[1]
end
```

In [19]:

```
t = character_table("B");
ords = orders_class_representatives(t);
pos7 = filter(i -> ords[i] == 7, 1:length(ords))
pos47 = filter(i -> ords[i] == 47, 1:length(ords))
class_multiplication_coefficient(t, 2, pos7[1], pos47[1]) != 0
filter(x -> mod(order(character_table(x)), 47) == 0, maxes(t))
```

Out[19]:

1-element Vector{String}: "47:23"

Now consider the case that $S$ is the Monster, which is special because the complete list of classes of maximal subgroups of $S$ is currently not known. We know $44$ classes of maximal subgroups, and that each possible additional maximal subgroup is almost simple and has socle $L_2(13)$, $U_3(4)$, $U_3(8)$, or $Sz(8)$. This implies that we know all those maximal subgroups that contain a Sylow $p$-subgroup of $S$ except in the case $p = 19$, where maximal subgroups with socle $U_3(8)$ may arise.

Thus let us first consider that at least one of $p$, $r$ is different from $19$. In this situation, we use the same approach as for the other sporadic simple groups. The only complication is that not all permutation characters $1_M^S$, for the relevant maximal subgroups $M$ of $S$, are known; however, if this happens then the character table of $M$ is known, and we can compute the possible permutation characters, and take the common upper bounds for these characters. In each case, we get that the claimed property holds.

In [20]:

```
t = character_table("M");
orders = orders_class_representatives(t);
for p in setdiff(prime_divisors(order(t)), [19])
goodpos = filter(i -> mod(monstermaxindices[i], p) != 0, 1:length(monster_prim_data))
sumx = zeros(fmpz, ncols(t))
for i in goodpos
if length(monster_prim_data[i]) == 2
# We know the permutation character but not the subgroup table.
bd = upper_bound(t, nothing, p)
sumx = sumx + [bd * fmpz(x) // monstermaxindices[i] for x in monster_prim_data[i][2]]
else
s = monstermaxtables[i]
if known_class_fusion(s, t)[1]
# We can compute the permutation character.
bd = upper_bound(t, s, p)
sumx = sumx + [bd * ZZ(x.data) // monstermaxindices[i] for x in trivial_character(s)^t]
else
# We get only candidates for the permutation character.
cand = Set([[ZZ(x.data) for x in induced_class_function(trivial_character(s), t, map)]
for map in possible_class_fusions(s, t)])
# For each column, take the maximum of the possible values.
mat = matrix(ZZ, collect(cand))
mx = [maximum(mat[1:nrows(mat), i]) for i in 1:ncols(mat)]
bd = upper_bound(t, s, p)
sumx = sumx + [bd * x // monstermaxindices[i] for x in mx]
end
end
end
badpos = filter(i -> sumx[i] >= 1, 2:length(sumx));
if length(badpos) > 0
error("p = $p: check open cases in $badpos");
end
end;
```

In [21]:

```
pos19 = filter(i -> orders[i] == 19, 1:length(orders))
```

Out[21]:

1-element Vector{Int64}: 63

In [22]:

```
pos71 = filter(i -> orders[i] == 71, 1:length(ords))
```

Out[22]:

2-element Vector{Int64}: 169 170

In [23]:

```
class_multiplication_coefficient(t, pos19[1], pos19[1], pos71[1]) != 0
```

Out[23]:

true

In [24]:

```
any(x -> mod(order(t) // x, 19 * 71) == 0, monstermaxindices)
```

Out[24]:

false

In [25]:

```
any(x -> mod(order(character_table(x)), 71) == 0, ["L2(13)", "U3(4)", "U3(8)", "Sz(8)"])
```

Out[25]:

false