aboutsummaryrefslogtreecommitdiff
path: root/mathcomp/solvable/maximal.v
diff options
context:
space:
mode:
authorEnrico Tassi2015-03-09 11:07:53 +0100
committerEnrico Tassi2015-03-09 11:24:38 +0100
commitfc84c27eac260dffd8f2fb1cb56d599f1e3486d9 (patch)
treec16205f1637c80833a4c4598993c29fa0fd8c373 /mathcomp/solvable/maximal.v
Initial commit
Diffstat (limited to 'mathcomp/solvable/maximal.v')
-rw-r--r--mathcomp/solvable/maximal.v1656
1 files changed, 1656 insertions, 0 deletions
diff --git a/mathcomp/solvable/maximal.v b/mathcomp/solvable/maximal.v
new file mode 100644
index 0000000..7b50dc9
--- /dev/null
+++ b/mathcomp/solvable/maximal.v
@@ -0,0 +1,1656 @@
+(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *)
+Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice div fintype.
+Require Import finfun bigop finset prime binomial fingroup morphism perm.
+Require Import automorphism quotient action commutator gproduct gfunctor.
+Require Import ssralg finalg zmodp cyclic pgroup center gseries.
+Require Import nilpotent sylow abelian finmodule.
+
+(******************************************************************************)
+(* This file establishes basic properties of several important classes of *)
+(* maximal subgroups: maximal, max and min normal, simple, characteristically *)
+(* simple subgroups, the Frattini and Fitting subgroups, the Thompson *)
+(* critical subgroup, special and extra-special groups, and self-centralising *)
+(* normal (SCN) subgroups. In detail, we define: *)
+(* charsimple G == G is characteristically simple (it has no nontrivial *)
+(* characteristic subgroups, and is nontrivial) *)
+(* 'Phi(G) == the Frattini subgroup of G, i.e., the intersection of *)
+(* all its maximal proper subgroups. *)
+(* 'F(G) == the Fitting subgroup of G, i.e., the largest normal *)
+(* nilpotent subgroup of G (defined as the (direct) *)
+(* product of all the p-cores of G). *)
+(* critical C G == C is a critical subgroup of G: C is characteristic *)
+(* (but not functorial) in G, the center of C contains *)
+(* both its Frattini subgroup and the commutator [G, C], *)
+(* and is equal to the centraliser of C in G. The *)
+(* Thompson_critical theorem provides critical subgroups *)
+(* for p-groups; we also show that in this case the *)
+(* centraliser of C in Aut G is a p-group as well. *)
+(* special G == G is a special group: its center, Frattini, and *)
+(* derived sugroups coincide (we follow Aschbacher in *)
+(* not considering nontrivial elementary abelian groups *)
+(* as special); we show that a p-group factors under *)
+(* coprime action into special groups (Aschbacher 24.7). *)
+(* extraspecial G == G is a special group whose center has prime order *)
+(* (hence G is non-abelian). *)
+(* 'SCN(G) == the set of self-centralising normal abelian subgroups *)
+(* of G (the A <| G such that 'C_G(A) = A). *)
+(* 'SCN_n(G) == the subset of 'SCN(G) containing all groups with rank *)
+(* at least n (i.e., A \in 'SCN(G) and 'm(A) >= n). *)
+(******************************************************************************)
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Unset Printing Implicit Defensive.
+
+Import GroupScope.
+
+Section Defs.
+
+Variable gT : finGroupType.
+Implicit Types (A B D : {set gT}) (G : {group gT}).
+
+Definition charsimple A := [min A of G | G :!=: 1 & G \char A].
+
+Definition Frattini A := \bigcap_(G : {group gT} | maximal_eq G A) G.
+
+Canonical Frattini_group A : {group gT} := Eval hnf in [group of Frattini A].
+
+Definition Fitting A := \big[dprod/1]_(p <- primes #|A|) 'O_p(A).
+
+Lemma Fitting_group_set G : group_set (Fitting G).
+Proof.
+suffices [F ->]: exists F : {group gT}, Fitting G = F by exact: groupP.
+rewrite /Fitting; elim: primes (primes_uniq #|G|) => [_|p r IHr] /=.
+ by exists [1 gT]%G; rewrite big_nil.
+case/andP=> rp /IHr[F defF]; rewrite big_cons defF.
+suffices{IHr} /and3P[p'F sFG nFG]: p^'.-group F && (F <| G).
+ have nFGp: 'O_p(G) \subset 'N(F) := subset_trans (pcore_sub p G) nFG.
+ have pGp: p.-group('O_p(G)) := pcore_pgroup p G.
+ have{pGp} tiGpF: 'O_p(G) :&: F = 1 by rewrite coprime_TIg ?(pnat_coprime pGp).
+ exists ('O_p(G) <*> F)%G; rewrite dprodEY // (sameP commG1P trivgP) -tiGpF.
+ by rewrite subsetI commg_subl commg_subr (subset_trans sFG) // gFnorm.
+move/bigdprodWY: defF => <- {F}; elim: r rp => [_|q r IHr] /=.
+ by rewrite big_nil gen0 pgroup1 normal1.
+rewrite inE eq_sym big_cons -joingE -joing_idr => /norP[qp /IHr {IHr}].
+set F := <<_>> => /andP[p'F nsFG]; rewrite norm_joinEl /= -/F; last first.
+ exact: subset_trans (pcore_sub q G) (normal_norm nsFG).
+by rewrite pgroupM p'F normalM ?pcore_normal //= (pi_pgroup (pcore_pgroup q G)).
+Qed.
+
+Canonical Fitting_group G := group (Fitting_group_set G).
+
+Definition critical A B :=
+ [/\ A \char B,
+ Frattini A \subset 'Z(A),
+ [~: B, A] \subset 'Z(A)
+ & 'C_B(A) = 'Z(A)].
+
+Definition special A := Frattini A = 'Z(A) /\ A^`(1) = 'Z(A).
+
+Definition extraspecial A := special A /\ prime #|'Z(A)|.
+
+Definition SCN B := [set A : {group gT} | A <| B & 'C_B(A) == A].
+
+Definition SCN_at n B := [set A in SCN B | n <= 'r(A)].
+
+End Defs.
+
+Arguments Scope charsimple [_ group_scope].
+Arguments Scope Frattini [_ group_scope].
+Arguments Scope Fitting [_ group_scope].
+Arguments Scope critical [_ group_scope group_scope].
+Arguments Scope special [_ group_scope].
+Arguments Scope extraspecial [_ group_scope].
+Arguments Scope SCN [_ group_scope].
+Arguments Scope SCN_at [_ nat_scope group_scope].
+
+Prenex Implicits maximal simple charsimple critical special extraspecial.
+
+Notation "''Phi' ( A )" := (Frattini A)
+ (at level 8, format "''Phi' ( A )") : group_scope.
+Notation "''Phi' ( G )" := (Frattini_group G) : Group_scope.
+
+Notation "''F' ( G )" := (Fitting G)
+ (at level 8, format "''F' ( G )") : group_scope.
+Notation "''F' ( G )" := (Fitting_group G) : Group_scope.
+
+Notation "''SCN' ( B )" := (SCN B)
+ (at level 8, format "''SCN' ( B )") : group_scope.
+Notation "''SCN_' n ( B )" := (SCN_at n B)
+ (at level 8, n at level 2, format "''SCN_' n ( B )") : group_scope.
+
+Section PMax.
+
+Variables (gT : finGroupType) (p : nat) (P M : {group gT}).
+Hypothesis pP : p.-group P.
+
+Lemma p_maximal_normal : maximal M P -> M <| P.
+Proof.
+case/maxgroupP=> /andP[sMP sPM] maxM; rewrite /normal sMP.
+have:= subsetIl P 'N(M); rewrite subEproper.
+case/predU1P=> [/setIidPl-> // | /maxM/= SNM]; case/negP: sPM.
+rewrite (nilpotent_sub_norm (pgroup_nil pP) sMP) //.
+by rewrite SNM // subsetI sMP normG.
+Qed.
+
+Lemma p_maximal_index : maximal M P -> #|P : M| = p.
+Proof.
+move=> maxM; have nM := p_maximal_normal maxM.
+rewrite -card_quotient ?normal_norm //.
+rewrite -(quotient_maximal _ nM) ?normal_refl // trivg_quotient in maxM.
+case/maxgroupP: maxM; rewrite properEneq eq_sym sub1G andbT /=.
+case/(pgroup_pdiv (quotient_pgroup M pP)) => p_pr /Cauchy[] // xq.
+rewrite /order -cycle_subG subEproper => /predU1P[-> // | sxPq oxq_p _].
+by move/(_ _ sxPq (sub1G _)) => xq1; rewrite -oxq_p xq1 cards1 in p_pr.
+Qed.
+
+Lemma p_index_maximal : M \subset P -> prime #|P : M| -> maximal M P.
+Proof.
+move=> sMP /primeP[lt1PM pr_PM].
+apply/maxgroupP; rewrite properEcard sMP -(Lagrange sMP).
+rewrite -{1}(muln1 #|M|) ltn_pmul2l //; split=> // H sHP sMH.
+apply/eqP; rewrite eq_sym eqEcard sMH.
+case/orP: (pr_PM _ (indexSg sMH (proper_sub sHP))) => /eqP iM.
+ by rewrite -(Lagrange sMH) iM muln1 /=.
+by have:= proper_card sHP; rewrite -(Lagrange sMH) iM Lagrange ?ltnn.
+Qed.
+
+End PMax.
+
+Section Frattini.
+
+Variables gT : finGroupType.
+Implicit Type G M : {group gT}.
+
+Lemma Phi_sub G : 'Phi(G) \subset G.
+Proof. by rewrite bigcap_inf // /maximal_eq eqxx. Qed.
+
+Lemma Phi_sub_max G M : maximal M G -> 'Phi(G) \subset M.
+Proof. by move=> maxM; rewrite bigcap_inf // /maximal_eq predU1r. Qed.
+
+Lemma Phi_proper G : G :!=: 1 -> 'Phi(G) \proper G.
+Proof.
+move/eqP; case/maximal_exists: (sub1G G) => [<- //| [M maxM _] _].
+exact: sub_proper_trans (Phi_sub_max maxM) (maxgroupp maxM).
+Qed.
+
+Lemma Phi_nongen G X : 'Phi(G) <*> X = G -> <<X>> = G.
+Proof.
+move=> defG; have: <<X>> \subset G by rewrite -{1}defG genS ?subsetUr.
+case/maximal_exists=> //= [[M maxM]]; rewrite gen_subG => sXM.
+case/andP: (maxgroupp maxM) => _ /negP[].
+by rewrite -defG gen_subG subUset Phi_sub_max.
+Qed.
+
+Lemma Frattini_continuous (rT : finGroupType) G (f : {morphism G >-> rT}) :
+ f @* 'Phi(G) \subset 'Phi(f @* G).
+Proof.
+apply/bigcapsP=> M maxM; rewrite sub_morphim_pre ?Phi_sub // bigcap_inf //.
+have {2}<-: f @*^-1 (f @* G) = G by rewrite morphimGK ?subsetIl.
+by rewrite morphpre_maximal_eq ?maxM //; case/maximal_eqP: maxM.
+Qed.
+
+End Frattini.
+
+Canonical Frattini_igFun := [igFun by Phi_sub & Frattini_continuous].
+Canonical Frattini_gFun := [gFun by Frattini_continuous].
+
+Section Frattini0.
+
+Variable gT : finGroupType.
+Implicit Types (rT : finGroupType) (D G : {group gT}).
+
+Lemma Phi_char G : 'Phi(G) \char G.
+Proof. exact: gFchar. Qed.
+
+Lemma Phi_normal G : 'Phi(G) <| G.
+Proof. exact: gFnormal. Qed.
+
+Lemma injm_Phi rT D G (f : {morphism D >-> rT}) :
+ 'injm f -> G \subset D -> f @* 'Phi(G) = 'Phi(f @* G).
+Proof. exact: injmF. Qed.
+
+Lemma isog_Phi rT G (H : {group rT}) : G \isog H -> 'Phi(G) \isog 'Phi(H).
+Proof. exact: gFisog. Qed.
+
+Lemma PhiJ G x : 'Phi(G :^ x) = 'Phi(G) :^ x.
+Proof.
+rewrite -{1}(setIid G) -(setIidPr (Phi_sub G)) -!morphim_conj.
+by rewrite injm_Phi ?injm_conj.
+Qed.
+
+End Frattini0.
+
+Section Frattini2.
+
+Variables gT : finGroupType.
+Implicit Type G : {group gT}.
+
+Lemma Phi_quotient_id G : 'Phi (G / 'Phi(G)) = 1.
+Proof.
+apply/trivgP; rewrite -cosetpreSK cosetpre1 /=; apply/bigcapsP=> M maxM.
+have nPhi := Phi_normal G; have nPhiM: 'Phi(G) <| M.
+ by apply: normalS nPhi; [exact: bigcap_inf | case/maximal_eqP: maxM].
+by rewrite sub_cosetpre_quo ?bigcap_inf // quotient_maximal_eq.
+Qed.
+
+Lemma Phi_quotient_cyclic G : cyclic (G / 'Phi(G)) -> cyclic G.
+Proof.
+case/cyclicP=> /= Px; case: (cosetP Px) => x nPx ->{Px} defG.
+apply/cyclicP; exists x; symmetry; apply: Phi_nongen.
+rewrite -joing_idr norm_joinEr -?quotientK ?cycle_subG //.
+by rewrite /quotient morphim_cycle //= -defG quotientGK ?Phi_normal.
+Qed.
+
+Variables (p : nat) (P : {group gT}).
+
+Lemma trivg_Phi : p.-group P -> ('Phi(P) == 1) = p.-abelem P.
+Proof.
+move=> pP; case: (eqsVneq P 1) => [P1 | ntP].
+ by rewrite P1 abelem1 -subG1 -P1 Phi_sub.
+have [p_pr _ _] := pgroup_pdiv pP ntP.
+apply/eqP/idP=> [trPhi | abP].
+ apply/abelemP=> //; split=> [|x Px].
+ apply/commG1P/trivgP; rewrite -trPhi.
+ apply/bigcapsP=> M /predU1P[-> | maxM]; first exact: der1_subG.
+ have /andP[_ nMP]: M <| P := p_maximal_normal pP maxM.
+ rewrite der1_min // cyclic_abelian // prime_cyclic // card_quotient //.
+ by rewrite (p_maximal_index pP).
+ apply/set1gP; rewrite -trPhi; apply/bigcapP=> M.
+ case/predU1P=> [-> | maxM]; first exact: groupX.
+ have /andP[_ nMP] := p_maximal_normal pP maxM.
+ have nMx : x \in 'N(M) by exact: subsetP Px.
+ apply: coset_idr; rewrite ?groupX ?morphX //=; apply/eqP.
+ rewrite -(p_maximal_index pP maxM) -card_quotient // -order_dvdn cardSg //=.
+ by rewrite cycle_subG mem_quotient.
+apply/trivgP/subsetP=> x Phi_x; rewrite -cycle_subG.
+have Px: x \in P by exact: (subsetP (Phi_sub P)).
+have sxP: <[x]> \subset P by rewrite cycle_subG.
+case/splitsP: (abelem_splits abP sxP) => K /complP[tiKx defP].
+have [-> | nt_x] := eqVneq x 1; first by rewrite cycle1.
+have oxp := abelem_order_p abP Px nt_x.
+rewrite /= -tiKx subsetI subxx cycle_subG.
+apply: (bigcapP Phi_x); apply/orP; right.
+apply: p_index_maximal; rewrite -?divgS -defP ?mulG_subr //.
+by rewrite (TI_cardMg tiKx) mulnK // [#|_|]oxp.
+Qed.
+
+End Frattini2.
+
+Section Frattini3.
+
+Variables (gT : finGroupType) (p : nat) (P : {group gT}).
+Hypothesis pP : p.-group P.
+
+Lemma Phi_quotient_abelem : p.-abelem (P / 'Phi(P)).
+Proof. by rewrite -trivg_Phi ?morphim_pgroup //= Phi_quotient_id. Qed.
+
+Lemma Phi_joing : 'Phi(P) = P^`(1) <*> 'Mho^1(P).
+Proof.
+have [sPhiP nPhiP] := andP (Phi_normal P).
+apply/eqP; rewrite eqEsubset join_subG.
+case: (eqsVneq P 1) => [-> | ntP] in sPhiP *.
+ by rewrite /= (trivgP sPhiP) sub1G der_subS Mho_sub.
+have [p_pr _ _] := pgroup_pdiv pP ntP.
+have [abP x1P] := abelemP p_pr Phi_quotient_abelem.
+apply/andP; split.
+ have nMP: P \subset 'N(P^`(1) <*> 'Mho^1(P)) by rewrite normsY // !gFnorm.
+ rewrite -quotient_sub1 ?(subset_trans sPhiP) //=.
+ suffices <-: 'Phi(P / (P^`(1) <*> 'Mho^1(P))) = 1 by exact: morphimF.
+ apply/eqP; rewrite (trivg_Phi (morphim_pgroup _ pP)) /= -quotientE.
+ apply/abelemP=> //; rewrite [abelian _]quotient_cents2 ?joing_subl //.
+ split=> // _ /morphimP[x Nx Px ->] /=.
+ rewrite -morphX //= coset_id // (MhoE 1 pP) joing_idr expn1.
+ by rewrite mem_gen //; apply/setUP; right; exact: mem_imset.
+rewrite -quotient_cents2 // [_ \subset 'C(_)]abP (MhoE 1 pP) gen_subG /=.
+apply/subsetP=> _ /imsetP[x Px ->]; rewrite expn1.
+have nPhi_x: x \in 'N('Phi(P)) by exact: (subsetP nPhiP).
+by rewrite coset_idr ?groupX ?morphX ?x1P ?mem_morphim.
+Qed.
+
+Lemma Phi_Mho : abelian P -> 'Phi(P) = 'Mho^1(P).
+Proof. by move=> cPP; rewrite Phi_joing (derG1P cPP) joing1G. Qed.
+
+End Frattini3.
+
+Section Frattini4.
+
+Variables (p : nat) (gT : finGroupType).
+Implicit Types (rT : finGroupType) (P G H K D : {group gT}).
+
+Lemma PhiS G H : p.-group H -> G \subset H -> 'Phi(G) \subset 'Phi(H).
+Proof.
+move=> pH sGH; rewrite (Phi_joing pH) (Phi_joing (pgroupS sGH pH)).
+by rewrite genS // setUSS ?dergS ?MhoS.
+Qed.
+
+Lemma morphim_Phi rT P D (f : {morphism D >-> rT}) :
+ p.-group P -> P \subset D -> f @* 'Phi(P) = 'Phi(f @* P).
+Proof.
+move=> pP sPD; rewrite !(@Phi_joing _ p) ?morphim_pgroup //.
+rewrite morphim_gen ?(subset_trans _ sPD) ?subUset ?der_subS ?Mho_sub //.
+by rewrite morphimU -joingE morphimR ?morphim_Mho.
+Qed.
+
+Lemma quotient_Phi P H :
+ p.-group P -> P \subset 'N(H) -> 'Phi(P) / H = 'Phi(P / H).
+Proof. exact: morphim_Phi. Qed.
+
+(* This is Aschbacher (23.2) *)
+Lemma Phi_min G H :
+ p.-group G -> G \subset 'N(H) -> p.-abelem (G / H) -> 'Phi(G) \subset H.
+Proof.
+move=> pG nHG; rewrite -trivg_Phi ?quotient_pgroup // -subG1 /=.
+by rewrite -(quotient_Phi pG) ?quotient_sub1 // (subset_trans (Phi_sub _)).
+Qed.
+
+Lemma Phi_cprod G H K :
+ p.-group G -> H \* K = G -> 'Phi(H) \* 'Phi(K) = 'Phi(G).
+Proof.
+move=> pG defG; have [_ /mulG_sub[sHG sKG] cHK] := cprodP defG.
+rewrite cprodEY /=; last by rewrite (centSS (Phi_sub _) (Phi_sub _)).
+rewrite !(Phi_joing (pgroupS _ pG)) //=.
+have /cprodP[_ <- /cent_joinEr <-] := der_cprod 1 defG.
+have /cprodP[_ <- /cent_joinEr <-] := Mho_cprod 1 defG.
+by rewrite !joingA /= -!(joingA H^`(1)) (joingC K^`(1)).
+Qed.
+
+Lemma Phi_mulg H K :
+ p.-group H -> p.-group K -> K \subset 'C(H) ->
+ 'Phi(H * K) = 'Phi(H) * 'Phi(K).
+Proof.
+move=> pH pK cHK; have defHK := cprodEY cHK.
+have [|_ -> _] := cprodP (Phi_cprod _ defHK); rewrite /= cent_joinEr //.
+by apply: pnat_dvd (dvdn_cardMg H K) _; rewrite pnat_mul; exact/andP.
+Qed.
+
+Lemma charsimpleP G :
+ reflect (G :!=: 1 /\ forall K, K :!=: 1 -> K \char G -> K :=: G)
+ (charsimple G).
+Proof.
+apply: (iffP mingroupP); rewrite char_refl andbT => [[ntG simG]].
+ by split=> // K ntK chK; apply: simG; rewrite ?ntK // char_sub.
+split=> // K /andP[ntK chK] _; exact: simG.
+Qed.
+
+End Frattini4.
+
+Section Fitting.
+
+Variable gT : finGroupType.
+Implicit Types (p : nat) (G H : {group gT}).
+
+Lemma Fitting_normal G : 'F(G) <| G.
+Proof.
+rewrite -['F(G)](bigdprodWY (erefl 'F(G))).
+elim/big_rec: _ => [|p H _ nsHG]; first by rewrite gen0 normal1.
+by rewrite -[<<_>>]joing_idr normalY ?pcore_normal.
+Qed.
+
+Lemma Fitting_sub G : 'F(G) \subset G.
+Proof. by rewrite normal_sub ?Fitting_normal. Qed.
+
+Lemma Fitting_nil G : nilpotent 'F(G).
+Proof.
+apply: (bigdprod_nil (erefl 'F(G))) => p _.
+exact: pgroup_nil (pcore_pgroup p G).
+Qed.
+
+Lemma Fitting_max G H : H <| G -> nilpotent H -> H \subset 'F(G).
+Proof.
+move=> nsHG nilH; rewrite -(Sylow_gen H) gen_subG.
+apply/bigcupsP=> P /SylowP[p _ SylP].
+case Gp: (p \in \pi(G)); last first.
+ rewrite card1_trivg ?sub1G // (card_Hall SylP).
+ rewrite part_p'nat // (pnat_dvd (cardSg (normal_sub nsHG))) //.
+ by rewrite /pnat cardG_gt0 all_predC has_pred1 Gp.
+move/nilpotent_Hall_pcore: SylP => ->{P} //.
+rewrite -(bigdprodWY (erefl 'F(G))) sub_gen //.
+rewrite -(filter_pi_of (ltnSn _)) big_filter big_mkord.
+have le_pG: p < #|G|.+1.
+ by rewrite ltnS dvdn_leq //; move: Gp; rewrite mem_primes => /and3P[].
+apply: (bigcup_max (Ordinal le_pG)) => //=.
+apply: pcore_max (pcore_pgroup _ _) _.
+exact: char_normal_trans (pcore_char p H) nsHG.
+Qed.
+
+Lemma pcore_Fitting pi G : 'O_pi('F(G)) \subset 'O_pi(G).
+Proof.
+rewrite pcore_max ?pcore_pgroup //.
+exact: char_normal_trans (pcore_char _ _) (Fitting_normal _).
+Qed.
+
+Lemma p_core_Fitting p G : 'O_p('F(G)) = 'O_p(G).
+Proof.
+apply/eqP; rewrite eqEsubset pcore_Fitting pcore_max ?pcore_pgroup //.
+apply: normalS (normal_sub (Fitting_normal _)) (pcore_normal _ _).
+exact: Fitting_max (pcore_normal _ _) (pgroup_nil (pcore_pgroup _ _)).
+Qed.
+
+Lemma nilpotent_Fitting G : nilpotent G -> 'F(G) = G.
+Proof.
+by move=> nilG; apply/eqP; rewrite eqEsubset Fitting_sub Fitting_max.
+Qed.
+
+Lemma Fitting_eq_pcore p G : 'O_p^'(G) = 1 -> 'F(G) = 'O_p(G).
+Proof.
+move=> p'G1; have /dprodP[_ /= <- _ _] := nilpotent_pcoreC p (Fitting_nil G).
+by rewrite p_core_Fitting ['O_p^'(_)](trivgP _) ?mulg1 // -p'G1 pcore_Fitting.
+Qed.
+
+Lemma FittingEgen G :
+ 'F(G) = <<\bigcup_(p < #|G|.+1 | (p : nat) \in \pi(G)) 'O_p(G)>>.
+Proof.
+apply/eqP; rewrite eqEsubset gen_subG /=.
+rewrite -{1}(bigdprodWY (erefl 'F(G))) (big_nth 0) big_mkord genS.
+ by apply/bigcupsP=> p _; rewrite -p_core_Fitting pcore_sub.
+apply/bigcupsP=> [[i /= lti]] _; set p := nth _ _ i.
+have pi_p: p \in \pi(G) by rewrite mem_nth.
+have p_dv_G: p %| #|G| by rewrite mem_primes in pi_p; case/and3P: pi_p.
+have lepG: p < #|G|.+1 by rewrite ltnS dvdn_leq.
+by rewrite (bigcup_max (Ordinal lepG)).
+Qed.
+
+End Fitting.
+
+Section FittingFun.
+
+Implicit Types gT rT : finGroupType.
+
+Lemma morphim_Fitting : GFunctor.pcontinuous Fitting.
+Proof.
+move=> gT rT G D f; apply: Fitting_max.
+ by rewrite morphim_normal ?Fitting_normal.
+by rewrite morphim_nil ?Fitting_nil.
+Qed.
+
+Lemma FittingS gT (G H : {group gT}) : H \subset G -> H :&: 'F(G) \subset 'F(H).
+Proof.
+move=> sHG; rewrite -{2}(setIidPl sHG).
+do 2!rewrite -(morphim_idm (subsetIl H _)) morphimIdom; exact: morphim_Fitting.
+Qed.
+
+Lemma FittingJ gT (G : {group gT}) x : 'F(G :^ x) = 'F(G) :^ x.
+Proof.
+rewrite !FittingEgen -genJ /= cardJg; symmetry; congr <<_>>.
+rewrite (big_morph (conjugate^~ x) (fun A B => conjUg A B x) (imset0 _)).
+by apply: eq_bigr => p _; rewrite pcoreJ.
+Qed.
+
+End FittingFun.
+
+Canonical Fitting_igFun := [igFun by Fitting_sub & morphim_Fitting].
+Canonical Fitting_gFun := [gFun by morphim_Fitting].
+Canonical Fitting_pgFun := [pgFun by morphim_Fitting].
+
+Section IsoFitting.
+
+Variables (gT rT : finGroupType) (G D : {group gT}) (f : {morphism D >-> rT}).
+
+Lemma Fitting_char : 'F(G) \char G. Proof. exact: gFchar. Qed.
+
+Lemma injm_Fitting : 'injm f -> G \subset D -> f @* 'F(G) = 'F(f @* G).
+Proof. exact: injmF. Qed.
+
+Lemma isog_Fitting (H : {group rT}) : G \isog H -> 'F(G) \isog 'F(H).
+Proof. exact: gFisog. Qed.
+
+End IsoFitting.
+
+Section CharSimple.
+
+Variable gT : finGroupType.
+Implicit Types (rT : finGroupType) (G H K L : {group gT}) (p : nat).
+
+Lemma minnormal_charsimple G H : minnormal H G -> charsimple H.
+Proof.
+case/mingroupP=> /andP[ntH nHG] minH.
+apply/charsimpleP; split=> // K ntK chK.
+by apply: minH; rewrite ?ntK (char_sub chK, char_norm_trans chK).
+Qed.
+
+Lemma maxnormal_charsimple G H L :
+ G <| L -> maxnormal H G L -> charsimple (G / H).
+Proof.
+case/andP=> sGL nGL /maxgroupP[/andP[/andP[sHG not_sGH] nHL] maxH].
+have nHG: G \subset 'N(H) := subset_trans sGL nHL.
+apply/charsimpleP; rewrite -subG1 quotient_sub1 //; split=> // HK ntHK chHK.
+case/(inv_quotientN _): (char_normal chHK) => [|K defHK sHK]; first exact/andP.
+case/andP; rewrite subEproper defHK => /predU1P[-> // | ltKG] nKG.
+have nHK: H <| K by rewrite /normal sHK (subset_trans (proper_sub ltKG)).
+case/negP: ntHK; rewrite defHK -subG1 quotient_sub1 ?normal_norm //.
+rewrite (maxH K) // ltKG -(quotientGK nHK) -defHK norm_quotient_pre //.
+by rewrite (char_norm_trans chHK) ?quotient_norms.
+Qed.
+
+Lemma abelem_split_dprod rT p (A B : {group rT}) :
+ p.-abelem A -> B \subset A -> exists C : {group rT}, B \x C = A.
+Proof.
+move=> abelA sBA; have [_ cAA _]:= and3P abelA.
+case/splitsP: (abelem_splits abelA sBA) => C /complP[tiBC defA].
+by exists C; rewrite dprodE // (centSS _ sBA cAA) // -defA mulG_subr.
+Qed.
+
+Lemma p_abelem_split1 rT p (A : {group rT}) x :
+ p.-abelem A -> x \in A ->
+ exists B : {group rT}, [/\ B \subset A, #|B| = #|A| %/ #[x] & <[x]> \x B = A].
+Proof.
+move=> abelA Ax; have sxA: <[x]> \subset A by rewrite cycle_subG.
+have [B defA] := abelem_split_dprod abelA sxA.
+have [_ defxB _ ti_xB] := dprodP defA.
+have sBA: B \subset A by rewrite -defxB mulG_subr.
+by exists B; split; rewrite // -defxB (TI_cardMg ti_xB) mulKn ?order_gt0.
+Qed.
+
+Lemma abelem_charsimple p G : p.-abelem G -> G :!=: 1 -> charsimple G.
+Proof.
+move=> abelG ntG; apply/charsimpleP; split=> // K ntK /charP[sKG chK].
+case/eqVproper: sKG => // /properP[sKG [x Gx notKx]].
+have ox := abelem_order_p abelG Gx (group1_contra notKx).
+have [A [sAG oA defA]] := p_abelem_split1 abelG Gx.
+case/trivgPn: ntK => y Ky nty; have Gy := subsetP sKG y Ky.
+have{nty} oy := abelem_order_p abelG Gy nty.
+have [B [sBG oB defB]] := p_abelem_split1 abelG Gy.
+have: isog A B; last case/isogP=> fAB injAB defAB.
+ rewrite (isog_abelem_card _ (abelemS sAG abelG)) (abelemS sBG) //=.
+ by rewrite oA oB ox oy.
+have: isog <[x]> <[y]>; last case/isogP=> fxy injxy /= defxy.
+ by rewrite isog_cyclic_card ?cycle_cyclic // [#|_|]oy -ox eqxx.
+have cfxA: fAB @* A \subset 'C(fxy @* <[x]>).
+ by rewrite defAB defxy; case/dprodP: defB.
+have injf: 'injm (dprodm defA cfxA).
+ by rewrite injm_dprodm injAB injxy defAB defxy; apply/eqP; case/dprodP: defB.
+case/negP: notKx; rewrite -cycle_subG -(injmSK injf) ?cycle_subG //=.
+rewrite morphim_dprodml // defxy cycle_subG /= chK //.
+have [_ {4}<- _ _] := dprodP defB; have [_ {3}<- _ _] := dprodP defA.
+by rewrite morphim_dprodm // defAB defxy.
+Qed.
+
+Lemma charsimple_dprod G : charsimple G ->
+ exists H : {group gT}, [/\ H \subset G, simple H
+ & exists2 I : {set {perm gT}}, I \subset Aut G
+ & \big[dprod/1]_(f in I) f @: H = G].
+Proof.
+case/charsimpleP=> ntG simG.
+have [H minH sHG]: {H : {group gT} | minnormal H G & H \subset G}.
+ by apply: mingroup_exists; rewrite ntG normG.
+case/mingroupP: minH => /andP[ntH nHG] minH.
+pose Iok (I : {set {perm gT}}) :=
+ (I \subset Aut G) &&
+ [exists (M : {group gT} | M <| G), \big[dprod/1]_(f in I) f @: H == M].
+have defH: (1 : {perm gT}) @: H = H.
+ apply/eqP; rewrite eqEcard card_imset ?leqnn; last exact: perm_inj.
+ by rewrite andbT; apply/subsetP=> _ /imsetP[x Hx ->]; rewrite perm1.
+have [|I] := @maxset_exists _ Iok 1.
+ rewrite /Iok sub1G; apply/existsP; exists H.
+ by rewrite /normal sHG nHG (big_pred1 1) => [|f]; rewrite ?defH /= ?inE.
+case/maxsetP=> /andP[Aut_I /exists_eq_inP[M /andP[sMG nMG] defM]] maxI.
+rewrite sub1set=> ntI; case/eqVproper: sMG => [defG | /andP[sMG not_sGM]].
+ exists H; split=> //; last by exists I; rewrite ?defM.
+ apply/mingroupP; rewrite ntH normG; split=> // N /andP[ntN nNH] sNH.
+ apply: minH => //; rewrite ntN /= -defG.
+ move: defM; rewrite (bigD1 1) //= defH; case/dprodP=> [[_ K _ ->] <- cHK _].
+ by rewrite mul_subG // cents_norm // (subset_trans cHK) ?centS.
+have defG: <<\bigcup_(f in Aut G) f @: H>> = G.
+ have sXG: \bigcup_(f in Aut G) f @: H \subset G.
+ by apply/bigcupsP=> f Af; rewrite -(im_autm Af) morphimEdom imsetS.
+ apply: simG.
+ apply: contra ntH; rewrite -!subG1; apply: subset_trans.
+ by rewrite sub_gen // (bigcup_max 1) ?group1 ?defH.
+ rewrite /characteristic gen_subG sXG; apply/forall_inP=> f Af.
+ rewrite -(autmE Af) -morphimEsub ?gen_subG ?morphim_gen // genS //.
+ rewrite morphimEsub //= autmE.
+ apply/subsetP=> _ /imsetP[_ /bigcupP[g Ag /imsetP[x Hx ->]] ->].
+ apply/bigcupP; exists (g * f); first exact: groupM.
+ by apply/imsetP; exists x; rewrite // permM.
+have [f Af sfHM]: exists2 f, f \in Aut G & ~~ (f @: H \subset M).
+ move: not_sGM; rewrite -{1}defG gen_subG; case/subsetPn=> x.
+ by case/bigcupP=> f Af fHx Mx; exists f => //; apply/subsetPn; exists x.
+case If: (f \in I).
+ by case/negP: sfHM; rewrite -(bigdprodWY defM) sub_gen // (bigcup_max f).
+case/idP: (If); rewrite -(maxI ([set f] :|: I)) ?subsetUr ?inE ?eqxx //.
+rewrite {maxI}/Iok subUset sub1set Af {}Aut_I; apply/existsP.
+have sfHG: autm Af @* H \subset G by rewrite -{4}(im_autm Af) morphimS.
+have{minH nHG} /mingroupP[/andP[ntfH nfHG] minfH]: minnormal (autm Af @* H) G.
+ apply/mingroupP; rewrite andbC -{1}(im_autm Af) morphim_norms //=.
+ rewrite -subG1 sub_morphim_pre // -kerE ker_autm subG1.
+ split=> // N /andP[ntN nNG] sNfH.
+ have sNG: N \subset G := subset_trans sNfH sfHG.
+ apply/eqP; rewrite eqEsubset sNfH sub_morphim_pre //=.
+ rewrite -(morphim_invmE (injm_autm Af)) [_ @* N]minH //=.
+ rewrite -subG1 sub_morphim_pre /= ?im_autm // morphpre_invm morphim1 subG1.
+ by rewrite ntN -{1}(im_invm (injm_autm Af)) /= {2}im_autm morphim_norms.
+ by rewrite sub_morphim_pre /= ?im_autm // morphpre_invm.
+have{minfH sfHM} tifHM: autm Af @* H :&: M = 1.
+ apply/eqP/idPn=> ntMfH; case/setIidPl: sfHM.
+ rewrite -(autmE Af) -morphimEsub //.
+ by apply: minfH; rewrite ?subsetIl // ntMfH normsI.
+have cfHM: M \subset 'C(autm Af @* H).
+ rewrite centsC (sameP commG1P trivgP) -tifHM subsetI commg_subl commg_subr.
+ by rewrite (subset_trans sMG) // (subset_trans sfHG).
+exists (autm Af @* H <*> M)%G; rewrite /normal /= join_subG sMG sfHG normsY //=.
+rewrite (bigD1 f) ?inE ?eqxx // (eq_bigl (mem I)) /= => [|g]; last first.
+ by rewrite /= !inE andbC; case: eqP => // ->.
+by rewrite defM -(autmE Af) -morphimEsub // dprodE // cent_joinEr ?eqxx.
+Qed.
+
+Lemma simple_sol_prime G : solvable G -> simple G -> prime #|G|.
+Proof.
+move=> solG /simpleP[ntG simG].
+have{solG} cGG: abelian G.
+ apply/commG1P; case/simG: (der_normal 1 G) => // /eqP/idPn[].
+ by rewrite proper_neq // (sol_der1_proper solG).
+case: (trivgVpdiv G) ntG => [-> | [p p_pr]]; first by rewrite eqxx.
+case/Cauchy=> // x Gx oxp _; move: p_pr; rewrite -oxp orderE.
+have: <[x]> <| G by rewrite -sub_abelian_normal ?cycle_subG.
+by case/simG=> -> //; rewrite cards1.
+Qed.
+
+Lemma charsimple_solvable G : charsimple G -> solvable G -> is_abelem G.
+Proof.
+case/charsimple_dprod=> H [sHG simH [I Aut_I defG]] solG.
+have p_pr: prime #|H| by exact: simple_sol_prime (solvableS sHG solG) simH.
+set p := #|H| in p_pr; apply/is_abelemP; exists p => //.
+elim/big_rec: _ (G) defG => [_ <-|f B If IH_B M defM]; first exact: abelem1.
+have [Af [[_ K _ defB] _ _ _]] := (subsetP Aut_I f If, dprodP defM).
+rewrite (dprod_abelem p defM) defB IH_B // andbT -(autmE Af) -morphimEsub //=.
+rewrite morphim_abelem ?abelemE // exponent_dvdn.
+by rewrite cyclic_abelian ?prime_cyclic.
+Qed.
+
+Lemma minnormal_solvable L G H :
+ minnormal H L -> H \subset G -> solvable G ->
+ [/\ L \subset 'N(H), H :!=: 1 & is_abelem H].
+Proof.
+move=> minH sHG solG; have /andP[ntH nHL] := mingroupp minH.
+split=> //; apply: (charsimple_solvable (minnormal_charsimple minH)).
+exact: solvableS solG.
+Qed.
+
+Lemma solvable_norm_abelem L G :
+ solvable G -> G <| L -> G :!=: 1 ->
+ exists H : {group gT}, [/\ H \subset G, H <| L, H :!=: 1 & is_abelem H].
+Proof.
+move=> solG /andP[sGL nGL] ntG.
+have [H minH sHG]: {H : {group gT} | minnormal H L & H \subset G}.
+ by apply: mingroup_exists; rewrite ntG.
+have [nHL ntH abH] := minnormal_solvable minH sHG solG.
+by exists H; split; rewrite // /normal (subset_trans sHG).
+Qed.
+
+Lemma trivg_Fitting G : solvable G -> ('F(G) == 1) = (G :==: 1).
+Proof.
+move=> solG; apply/idP/idP=> [F1|]; last first.
+ by rewrite -!subG1; apply: subset_trans; exact: Fitting_sub.
+apply/idPn=> /(solvable_norm_abelem solG (normal_refl _))[M [_ nsMG ntM]].
+case/is_abelemP=> p _ /and3P[pM _ _]; case/negP: ntM.
+by rewrite -subG1 -(eqP F1) Fitting_max ?(pgroup_nil pM).
+Qed.
+
+Lemma Fitting_pcore pi G : 'F('O_pi(G)) = 'O_pi('F(G)).
+Proof.
+apply/eqP; rewrite eqEsubset.
+rewrite (subset_trans _ (pcoreS _ (Fitting_sub _))); last first.
+ rewrite subsetI Fitting_sub Fitting_max ?Fitting_nil //.
+ by rewrite (char_normal_trans (Fitting_char _)) ?pcore_normal.
+rewrite (subset_trans _ (FittingS (pcore_sub _ _))) // subsetI pcore_sub.
+rewrite pcore_max ?pcore_pgroup //.
+by rewrite (char_normal_trans (pcore_char _ _)) ?Fitting_normal.
+Qed.
+
+End CharSimple.
+
+Section SolvablePrimeFactor.
+
+Variables (gT : finGroupType) (G : {group gT}).
+
+Lemma index_maxnormal_sol_prime (H : {group gT}) :
+ solvable G -> maxnormal H G G -> prime #|G : H|.
+Proof.
+move=> solG maxH; have nsHG := maxnormal_normal maxH.
+rewrite -card_quotient ?normal_norm // simple_sol_prime ?quotient_sol //.
+by rewrite quotient_simple.
+Qed.
+
+Lemma sol_prime_factor_exists :
+ solvable G -> G :!=: 1 -> {H : {group gT} | H <| G & prime #|G : H| }.
+Proof.
+move=> solG /ex_maxnormal_ntrivg[H maxH].
+by exists H; [exact: maxnormal_normal | exact: index_maxnormal_sol_prime].
+Qed.
+
+End SolvablePrimeFactor.
+
+Section Special.
+
+Variables (gT : finGroupType) (p : nat) (A G : {group gT}).
+
+(* This is Aschbacher (23.7) *)
+Lemma center_special_abelem : p.-group G -> special G -> p.-abelem 'Z(G).
+Proof.
+move=> pG [defPhi defG'].
+have [-> | ntG] := eqsVneq G 1; first by rewrite center1 abelem1.
+have [p_pr _ _] := pgroup_pdiv pG ntG.
+have fM: {in 'Z(G) &, {morph expgn^~ p : x y / x * y}}.
+ by move=> x y /setIP[_ /centP cxG] /setIP[/cxG cxy _]; exact: expgMn.
+rewrite abelemE //= center_abelian; apply/exponentP=> /= z Zz.
+apply: (@kerP _ _ _ (Morphism fM)) => //; apply: subsetP z Zz.
+rewrite -{1}defG' gen_subG; apply/subsetP=> _ /imset2P[x y Gx Gy ->].
+have Zxy: [~ x, y] \in 'Z(G) by rewrite -defG' mem_commg.
+have Zxp: x ^+ p \in 'Z(G).
+ rewrite -defPhi (Phi_joing pG) (MhoE 1 pG) joing_idr mem_gen // !inE.
+ by rewrite expn1 orbC (mem_imset (expgn^~ p)).
+rewrite mem_morphpre /= ?defG' ?Zxy // inE -commXg; last first.
+ by red; case/setIP: Zxy => _ /centP->.
+by apply/commgP; red; case/setIP: Zxp => _ /centP->.
+Qed.
+
+Lemma exponent_special : p.-group G -> special G -> exponent G %| p ^ 2.
+Proof.
+move=> pG spG; have [defPhi _] := spG.
+have /and3P[_ _ expZ] := center_special_abelem pG spG.
+apply/exponentP=> x Gx; rewrite expgM (exponentP expZ) // -defPhi.
+by rewrite (Phi_joing pG) mem_gen // inE orbC (Mho_p_elt 1) ?(mem_p_elt pG).
+Qed.
+
+(* Aschbacher 24.7 (replaces Gorenstein 5.3.7) *)
+Theorem abelian_charsimple_special :
+ p.-group G -> coprime #|G| #|A| -> [~: G, A] = G ->
+ \bigcup_(H : {group gT} | (H \char G) && abelian H) H \subset 'C(A) ->
+ special G /\ 'C_G(A) = 'Z(G).
+Proof.
+move=> pG coGA defG /bigcupsP cChaA.
+have cZA: 'Z(G) \subset 'C_G(A).
+ by rewrite subsetI center_sub cChaA // center_char center_abelian.
+have cChaG (H : {group gT}): H \char G -> abelian H -> H \subset 'Z(G).
+ move=> chH abH; rewrite subsetI char_sub //= centsC -defG.
+ rewrite comm_norm_cent_cent ?(char_norm chH) -?commg_subl ?defG //.
+ by rewrite centsC cChaA ?chH.
+have cZ2GG: [~: 'Z_2(G), G, G] = 1.
+ by apply/commG1P; rewrite (subset_trans (ucn_comm 1 G)) // ucn1 subsetIr.
+have{cZ2GG} cG'Z: 'Z_2(G) \subset 'C(G^`(1)).
+ by rewrite centsC; apply/commG1P; rewrite three_subgroup // (commGC G).
+have{cG'Z} sZ2G'_Z: 'Z_2(G) :&: G^`(1) \subset 'Z(G).
+ apply: cChaG; first by rewrite charI ?ucn_char ?der_char.
+ by rewrite /abelian subIset // (subset_trans cG'Z) // centS ?subsetIr.
+have{sZ2G'_Z} sG'Z: G^`(1) \subset 'Z(G).
+ rewrite der1_min ?gFnorm //; apply/derG1P.
+ have /TI_center_nil: nilpotent (G / 'Z(G)) := quotient_nil _ (pgroup_nil pG).
+ apply; first exact: gFnormal; rewrite /= setIC -ucn1 -ucn_central.
+ rewrite -quotient_der ?gFnorm // -quotientGI ?ucn_subS ?quotientS1 //=.
+ by rewrite ucn1.
+have sCG': 'C_G(A) \subset G^`(1).
+ rewrite -quotient_sub1 //; last by rewrite subIset // char_norm ?der_char.
+ rewrite (subset_trans (quotient_subcent _ G A)) //= -[G in G / _]defG.
+ have nGA: A \subset 'N(G) by rewrite -commg_subl defG.
+ rewrite quotientR ?(char_norm_trans (der_char _ _)) ?normG //.
+ rewrite coprime_abel_cent_TI ?quotient_norms ?coprime_morph //.
+ exact: sub_der1_abelian.
+have defZ: 'Z(G) = G^`(1) by apply/eqP; rewrite eqEsubset (subset_trans cZA).
+split; last by apply/eqP; rewrite eqEsubset cZA defZ sCG'.
+split=> //; apply/eqP; rewrite eqEsubset defZ (Phi_joing pG) joing_subl.
+have:= pG; rewrite -pnat_exponent => /p_natP[n expGpn].
+rewrite join_subG subxx andbT /= -defZ -(subnn n.-1).
+elim: {2}n.-1 => [|m IHm].
+ rewrite (MhoE _ pG) gen_subG; apply/subsetP=> _ /imsetP[x Gx ->].
+ rewrite subn0 -subn1 -add1n -maxnE maxnC maxnE expnD.
+ by rewrite expgM -expGpn expg_exponent ?groupX ?group1.
+rewrite cChaG ?Mho_char //= (MhoE _ pG) /abelian cent_gen gen_subG.
+apply/centsP=> _ /imsetP[x Gx ->] _ /imsetP[y Gy ->].
+move: sG'Z; rewrite subsetI centsC => /andP[_ /centsP cGG'].
+apply/commgP; rewrite {1}expnSr expgM.
+rewrite commXg -?commgX; try by apply: cGG'; rewrite ?mem_commg ?groupX.
+apply/commgP; rewrite subsetI Mho_sub centsC in IHm.
+apply: (centsP IHm); first by rewrite groupX.
+rewrite -add1n -(addn1 m) subnDA -maxnE maxnC maxnE.
+rewrite -expgM -expnSr -addSn expnD expgM groupX //=.
+by rewrite Mho_p_elt ?(mem_p_elt pG).
+Qed.
+
+End Special.
+
+Section Extraspecial.
+
+Variables (p : nat) (gT rT : finGroupType).
+Implicit Types D E F G H K M R S T U : {group gT}.
+
+Section Basic.
+
+Variable S : {group gT}.
+Hypotheses (pS : p.-group S) (esS : extraspecial S).
+
+Let pZ : p.-group 'Z(S) := pgroupS (center_sub S) pS.
+Lemma extraspecial_prime : prime p.
+Proof.
+by case: esS => _ /prime_gt1; rewrite cardG_gt1; case/(pgroup_pdiv pZ).
+Qed.
+
+Lemma card_center_extraspecial : #|'Z(S)| = p.
+Proof. by apply/eqP; apply: (pgroupP pZ); case: esS. Qed.
+
+Lemma min_card_extraspecial : #|S| >= p ^ 3.
+Proof.
+have p_gt1 := prime_gt1 extraspecial_prime.
+rewrite leqNgt (card_pgroup pS) ltn_exp2l // ltnS.
+case: esS => [[_ defS']]; apply: contraL => /(p2group_abelian pS)/derG1P S'1.
+by rewrite -defS' S'1 cards1.
+Qed.
+
+End Basic.
+
+Lemma card_p3group_extraspecial E :
+ prime p -> #|E| = (p ^ 3)%N -> #|'Z(E)| = p -> extraspecial E.
+Proof.
+move=> p_pr oEp3 oZp; have p_gt0 := prime_gt0 p_pr.
+have pE: p.-group E by rewrite /pgroup oEp3 pnat_exp pnat_id.
+have pEq: p.-group (E / 'Z(E))%g by rewrite quotient_pgroup.
+have /andP[sZE nZE] := center_normal E.
+have oEq: #|E / 'Z(E)|%g = (p ^ 2)%N.
+ by rewrite card_quotient -?divgS // oEp3 oZp expnS mulKn.
+have cEEq: abelian (E / 'Z(E))%g by exact: card_p2group_abelian oEq.
+have not_cEE: ~~ abelian E.
+ have: #|'Z(E)| < #|E| by rewrite oEp3 oZp (ltn_exp2l 1) ?prime_gt1.
+ by apply: contraL => cEE; rewrite -leqNgt subset_leq_card // subsetI subxx.
+have defE': E^`(1) = 'Z(E).
+ apply/eqP; rewrite eqEsubset der1_min //=; apply: contraR not_cEE => not_sE'Z.
+ apply/commG1P/(TI_center_nil (pgroup_nil pE) (der_normal 1 _)).
+ by rewrite setIC prime_TIg ?oZp.
+split; [split=> // | by rewrite oZp]; apply/eqP.
+rewrite eqEsubset andbC -{1}defE' {1}(Phi_joing pE) joing_subl.
+rewrite -quotient_sub1 ?(subset_trans (Phi_sub _)) //.
+rewrite subG1 /= (quotient_Phi pE) //= (trivg_Phi pEq); apply/abelemP=> //.
+split=> // Zx EqZx; apply/eqP; rewrite -order_dvdn /order.
+rewrite (card_pgroup (mem_p_elt pEq EqZx)) (@dvdn_exp2l _ _ 1) //.
+rewrite leqNgt -pfactor_dvdn // -oEq; apply: contra not_cEE => sEqZx.
+rewrite cyclic_center_factor_abelian //; apply/cyclicP.
+exists Zx; apply/eqP; rewrite eq_sym eqEcard cycle_subG EqZx -orderE.
+exact: dvdn_leq sEqZx.
+Qed.
+
+Lemma p3group_extraspecial G :
+ p.-group G -> ~~ abelian G -> logn p #|G| <= 3 -> extraspecial G.
+Proof.
+move=> pG not_cGG; have /andP[sZG nZG] := center_normal G.
+have ntG: G :!=: 1 by apply: contraNneq not_cGG => ->; exact: abelian1.
+have ntZ: 'Z(G) != 1 by rewrite (center_nil_eq1 (pgroup_nil pG)).
+have [p_pr _ [n oG]] := pgroup_pdiv pG ntG; rewrite oG pfactorK //.
+have [_ _ [m oZ]] := pgroup_pdiv (pgroupS sZG pG) ntZ.
+have lt_m1_n: m.+1 < n.
+ suffices: 1 < logn p #|(G / 'Z(G))|.
+ rewrite card_quotient // -divgS // logn_div ?cardSg //.
+ by rewrite oG oZ !pfactorK // ltn_subRL addn1.
+ rewrite ltnNge; apply: contra not_cGG => cycGs.
+ apply: cyclic_center_factor_abelian; rewrite (dvdn_prime_cyclic p_pr) //.
+ by rewrite (card_pgroup (quotient_pgroup _ pG)) (dvdn_exp2l _ cycGs).
+rewrite -{lt_m1_n}(subnKC lt_m1_n) !addSn !ltnS leqn0 in oG *.
+case: m => // in oZ oG * => /eqP n2; rewrite {n}n2 in oG.
+exact: card_p3group_extraspecial oZ.
+Qed.
+
+Lemma extraspecial_nonabelian G : extraspecial G -> ~~ abelian G.
+Proof.
+case=> [[_ defG'] oZ]; rewrite /abelian (sameP commG1P eqP).
+by rewrite -derg1 defG' -cardG_gt1 prime_gt1.
+Qed.
+
+Lemma exponent_2extraspecial G : 2.-group G -> extraspecial G -> exponent G = 4.
+Proof.
+move=> p2G esG; have [spG _] := esG.
+case/dvdn_pfactor: (exponent_special p2G spG) => // k.
+rewrite leq_eqVlt ltnS => /predU1P[-> // | lek1] expG.
+case/negP: (extraspecial_nonabelian esG).
+by rewrite (@abelem_abelian _ 2) ?exponent2_abelem // expG pfactor_dvdn.
+Qed.
+
+Lemma injm_special D G (f : {morphism D >-> rT}) :
+ 'injm f -> G \subset D -> special G -> special (f @* G).
+Proof.
+move=> injf sGD [defPhiG defG'].
+by rewrite /special -morphim_der // -injm_Phi // defPhiG defG' injm_center.
+Qed.
+
+Lemma injm_extraspecial D G (f : {morphism D >-> rT}) :
+ 'injm f -> G \subset D -> extraspecial G -> extraspecial (f @* G).
+Proof.
+move=> injf sGD [spG ZG_pr]; split; first exact: injm_special spG.
+by rewrite -injm_center // card_injm // subIset ?sGD.
+Qed.
+
+Lemma isog_special G (R : {group rT}) :
+ G \isog R -> special G -> special R.
+Proof. by case/isogP=> f injf <-; exact: injm_special. Qed.
+
+Lemma isog_extraspecial G (R : {group rT}) :
+ G \isog R -> extraspecial G -> extraspecial R.
+Proof. by case/isogP=> f injf <-; exact: injm_extraspecial. Qed.
+
+Lemma cprod_extraspecial G H K :
+ p.-group G -> H \* K = G -> H :&: K = 'Z(H) ->
+ extraspecial H -> extraspecial K -> extraspecial G.
+Proof.
+move=> pG defG ziHK [[PhiH defH'] ZH_pr] [[PhiK defK'] ZK_pr].
+have [_ defHK cHK]:= cprodP defG.
+have sZHK: 'Z(H) \subset 'Z(K).
+ by rewrite subsetI -{1}ziHK subsetIr subIset // centsC cHK.
+have{sZHK} defZH: 'Z(H) = 'Z(K).
+ by apply/eqP; rewrite eqEcard sZHK leq_eqVlt eq_sym -dvdn_prime2 ?cardSg.
+have defZ: 'Z(G) = 'Z(K).
+ by case/cprodP: (center_cprod defG) => /= _ <- _; rewrite defZH mulGid.
+split; first split; rewrite defZ //.
+ by have /cprodP[_ <- _] := Phi_cprod pG defG; rewrite PhiH PhiK defZH mulGid.
+by have /cprodP[_ <- _] := der_cprod 1 defG; rewrite defH' defK' defZH mulGid.
+Qed.
+
+(* Lemmas bundling Aschbacher (23.10) with (19.1), (19.2), (19.12) and (20.8) *)
+Section ExtraspecialFormspace.
+
+Variable G : {group gT}.
+Hypotheses (pG : p.-group G) (esG : extraspecial G).
+
+Let p_pr := extraspecial_prime pG esG.
+Let oZ := card_center_extraspecial pG esG.
+Let p_gt1 := prime_gt1 p_pr.
+Let p_gt0 := prime_gt0 p_pr.
+
+(* This encasulates Aschbacher (23.10)(1). *)
+Lemma cent1_extraspecial_maximal x :
+ x \in G -> x \notin 'Z(G) -> maximal 'C_G[x] G.
+Proof.
+move=> Gx notZx; pose f y := [~ x, y]; have [[_ defG'] prZ] := esG.
+have{defG'} fZ y: y \in G -> f y \in 'Z(G).
+ by move=> Gy; rewrite -defG' mem_commg.
+have fM: {in G &, {morph f : y z / y * z}}%g.
+ move=> y z Gy Gz; rewrite {1}/f commgMJ conjgCV -conjgM (conjg_fixP _) //.
+ rewrite (sameP commgP cent1P); apply: subsetP (fZ y Gy).
+ by rewrite subIset // orbC -cent_set1 centS // sub1set !(groupM, groupV).
+pose fm := Morphism fM.
+have fmG: fm @* G = 'Z(G).
+ have sfmG: fm @* G \subset 'Z(G).
+ by apply/subsetP=> _ /morphimP[z _ Gz ->]; exact: fZ.
+ apply/eqP; rewrite eqEsubset sfmG; apply: contraR notZx => /(prime_TIg prZ).
+ rewrite (setIidPr _) // => fmG1; rewrite inE Gx; apply/centP=> y Gy.
+ by apply/commgP; rewrite -in_set1 -[[set _]]fmG1; exact: mem_morphim.
+have ->: 'C_G[x] = 'ker fm.
+ apply/setP=> z; rewrite inE (sameP cent1P commgP) !inE.
+ by rewrite -invg_comm eq_invg_mul mulg1.
+rewrite p_index_maximal ?subsetIl // -card_quotient ?ker_norm //.
+by rewrite (card_isog (first_isog fm)) /= fmG.
+Qed.
+
+(* This is the tranposition of the hyperplane dimension theorem (Aschbacher *)
+(* (19.1)) to subgroups of an extraspecial group. *)
+Lemma subcent1_extraspecial_maximal U x :
+ U \subset G -> x \in G :\: 'C(U) -> maximal 'C_U[x] U.
+Proof.
+move=> sUG /setDP[Gx not_cUx]; apply/maxgroupP; split=> [|H ltHU sCxH].
+ by rewrite /proper subsetIl subsetI subxx sub_cent1.
+case/andP: ltHU => sHU not_sHU; have sHG := subset_trans sHU sUG.
+apply/eqP; rewrite eqEsubset sCxH subsetI sHU /= andbT.
+apply: contraR not_sHU => not_sHCx.
+have maxCx: maximal 'C_G[x] G.
+ rewrite cent1_extraspecial_maximal //; apply: contra not_cUx.
+ by rewrite inE Gx; exact: subsetP (centS sUG) _.
+have nsCx := p_maximal_normal pG maxCx.
+rewrite -(setIidPl sUG) -(mulg_normal_maximal nsCx maxCx sHG) ?subsetI ?sHG //.
+by rewrite -group_modr //= setIA (setIidPl sUG) mul_subG.
+Qed.
+
+(* This is the tranposition of the orthogonal subspace dimension theorem *)
+(* (Aschbacher (19.2)) to subgroups of an extraspecial group. *)
+Lemma card_subcent_extraspecial U :
+ U \subset G -> #|'C_G(U)| = (#|'Z(G) :&: U| * #|G : U|)%N.
+Proof.
+move=> sUG; rewrite setIAC (setIidPr sUG).
+elim: {U}_.+1 {-2}U (ltnSn #|U|) sUG => // m IHm U leUm sUG.
+have [cUG | not_cUG]:= orP (orbN (G \subset 'C(U))).
+ by rewrite !(setIidPl _) ?Lagrange // centsC.
+have{not_cUG} [x Gx not_cUx] := subsetPn not_cUG.
+pose W := 'C_U[x]; have sCW_G: 'C_G(W) \subset G := subsetIl G _.
+have maxW: maximal W U by rewrite subcent1_extraspecial_maximal // inE not_cUx.
+have nsWU: W <| U := p_maximal_normal (pgroupS sUG pG) maxW.
+have ltWU: W \proper U by exact: maxgroupp maxW.
+have [sWU [u Uu notWu]] := properP ltWU; have sWG := subset_trans sWU sUG.
+have defU: W * <[u]> = U by rewrite (mulg_normal_maximal nsWU) ?cycle_subG.
+have iCW_CU: #|'C_G(W) : 'C_G(U)| = p.
+ rewrite -defU centM cent_cycle setIA /=; rewrite inE Uu cent1C in notWu.
+ apply: p_maximal_index (pgroupS sCW_G pG) _.
+ apply: subcent1_extraspecial_maximal sCW_G _.
+ rewrite inE andbC (subsetP sUG) //= -sub_cent1.
+ by apply/subsetPn; exists x; rewrite // inE Gx -sub_cent1 subsetIr.
+apply/eqP; rewrite -(eqn_pmul2r p_gt0) -{1}iCW_CU Lagrange ?setIS ?centS //.
+rewrite IHm ?(leq_trans (proper_card ltWU)) // -setIA -mulnA.
+rewrite -(Lagrange_index sUG sWU) (p_maximal_index (pgroupS sUG pG)) //=.
+by rewrite -cent_set1 (setIidPr (centS _)) ?sub1set.
+Qed.
+
+(* This is the tranposition of the proof that a singular vector is contained *)
+(* in a hyperbolic plane (Aschbacher (19.12)) to subgroups of an extraspecial *)
+(* group. *)
+Lemma split1_extraspecial x :
+ x \in G :\: 'Z(G) ->
+ {E : {group gT} & {R : {group gT} |
+ [/\ #|E| = (p ^ 3)%N /\ #|R| = #|G| %/ p ^ 2,
+ E \* R = G /\ E :&: R = 'Z(E),
+ 'Z(E) = 'Z(G) /\ 'Z(R) = 'Z(G),
+ extraspecial E /\ x \in E
+ & if abelian R then R :=: 'Z(G) else extraspecial R]}}.
+Proof.
+case/setDP=> Gx notZx; rewrite inE Gx /= in notZx.
+have [[defPhiG defG'] prZ] := esG.
+have maxCx: maximal 'C_G[x] G.
+ by rewrite subcent1_extraspecial_maximal // inE notZx.
+pose y := repr (G :\: 'C[x]).
+have [Gy not_cxy]: y \in G /\ y \notin 'C[x].
+ move/maxgroupp: maxCx => /properP[_ [t Gt not_cyt]].
+ by apply/setDP; apply: (mem_repr t); rewrite !inE Gt andbT in not_cyt *.
+pose E := <[x]> <*> <[y]>; pose R := 'C_G(E).
+exists [group of E]; exists [group of R] => /=.
+have sEG: E \subset G by rewrite join_subG !cycle_subG Gx.
+have [Ex Ey]: x \in E /\ y \in E by rewrite !mem_gen // inE cycle_id ?orbT.
+have sZE: 'Z(G) \subset E.
+ rewrite (('Z(G) =P E^`(1)) _) ?der_sub // eqEsubset -{2}defG' dergS // andbT.
+ apply: contraR not_cxy => /= not_sZE'.
+ rewrite (sameP cent1P commgP) -in_set1 -[[set 1]](prime_TIg prZ not_sZE').
+ by rewrite /= -defG' inE !mem_commg.
+have ziER: E :&: R = 'Z(E) by rewrite setIA (setIidPl sEG).
+have cER: R \subset 'C(E) by rewrite subsetIr.
+have iCxG: #|G : 'C_G[x]| = p by exact: p_maximal_index.
+have maxR: maximal R 'C_G[x].
+ rewrite /R centY !cent_cycle setIA.
+ rewrite subcent1_extraspecial_maximal ?subsetIl // inE Gy andbT -sub_cent1.
+ by apply/subsetPn; exists x; rewrite 1?cent1C // inE Gx cent1id.
+have sRCx: R \subset 'C_G[x] by rewrite -cent_cycle setIS ?centS ?joing_subl.
+have sCxG: 'C_G[x] \subset G by rewrite subsetIl.
+have sRG: R \subset G by rewrite subsetIl.
+have iRCx: #|'C_G[x] : R| = p by rewrite (p_maximal_index (pgroupS sCxG pG)).
+have defG: E * R = G.
+ rewrite -cent_joinEr //= -/R joingC joingA.
+ have cGx_x: <[x]> \subset 'C_G[x] by rewrite cycle_subG inE Gx cent1id.
+ have nsRcx := p_maximal_normal (pgroupS sCxG pG) maxR.
+ rewrite (norm_joinEr (subset_trans cGx_x (normal_norm nsRcx))).
+ rewrite (mulg_normal_maximal nsRcx) //=; last first.
+ by rewrite centY !cent_cycle cycle_subG !in_setI Gx cent1id cent1C.
+ have nsCxG := p_maximal_normal pG maxCx.
+ have syG: <[y]> \subset G by rewrite cycle_subG.
+ rewrite (norm_joinEr (subset_trans syG (normal_norm nsCxG))).
+ by rewrite (mulg_normal_maximal nsCxG) //= cycle_subG inE Gy.
+have defZR: 'Z(R) = 'Z(G) by rewrite -['Z(R)]setIA -centM defG.
+have defZE: 'Z(E) = 'Z(G).
+ by rewrite -defG -center_prod ?mulGSid //= -ziER subsetI center_sub defZR sZE.
+have [n oG] := p_natP pG.
+have n_gt1: n > 1.
+ by rewrite ltnW // -(@leq_exp2l p) // -oG min_card_extraspecial.
+have oR: #|R| = (p ^ n.-2)%N.
+ apply/eqP; rewrite -(divg_indexS sRCx) iRCx /= -(divg_indexS sCxG) iCxG /= oG.
+ by rewrite -{1}(subnKC n_gt1) subn2 !expnS !mulKn.
+have oE: #|E| = (p ^ 3)%N.
+ apply/eqP; rewrite -(@eqn_pmul2r #|R|) ?cardG_gt0 // mul_cardG defG ziER.
+ by rewrite defZE oZ oG -{1}(subnKC n_gt1) oR -expnSr -expnD subn2.
+rewrite cprodE // oR oG -expnB ?subn2 //; split=> //.
+ by split=> //; apply: card_p3group_extraspecial _ oE _; rewrite // defZE.
+case: ifP => [cRR | not_cRR]; first by rewrite -defZR (center_idP _).
+split; rewrite /special defZR //.
+have ntR': R^`(1) != 1 by rewrite (sameP eqP commG1P) -abelianE not_cRR.
+have pR: p.-group R := pgroupS sRG pG.
+have pR': p.-group R^`(1) := pgroupS (der_sub 1 _) pR.
+have defR': R^`(1) = 'Z(G).
+ apply/eqP; rewrite eqEcard -{1}defG' dergS //= oZ.
+ by have [_ _ [k ->]]:= pgroup_pdiv pR' ntR'; rewrite (leq_exp2l 1).
+split=> //; apply/eqP; rewrite eqEsubset -{1}defPhiG -defR' (PhiS pG) //=.
+by rewrite (Phi_joing pR) joing_subl.
+Qed.
+
+(* This is the tranposition of the proof that the dimension of any maximal *)
+(* totally singular subspace is equal to the Witt index (Aschbacher (20.8)), *)
+(* to subgroups of an extraspecial group (in a slightly more general form, *)
+(* since we allow for p != 2). *)
+(* Note that Aschbacher derives this from the Witt lemma, which we avoid. *)
+Lemma pmaxElem_extraspecial : 'E*_p(G) = 'E_p^('r_p(G))(G).
+Proof.
+have sZmax: {in 'E*_p(G), forall E, 'Z(G) \subset E}.
+ move=> E maxE; have defE := pmaxElem_LdivP p_pr maxE.
+ have abelZ: p.-abelem 'Z(G) by rewrite prime_abelem ?oZ.
+ rewrite -(Ohm1_id abelZ) (OhmE 1 (abelem_pgroup abelZ)) gen_subG -defE.
+ by rewrite setSI // setIS ?centS // -defE !subIset ?subxx.
+suffices card_max: {in 'E*_p(G) &, forall E F, #|E| <= #|F| }.
+ have EprGmax: 'E_p^('r_p(G))(G) \subset 'E*_p(G) := p_rankElem_max p G.
+ have [E EprE]:= p_rank_witness p G; have maxE := subsetP EprGmax E EprE.
+ apply/eqP; rewrite eqEsubset EprGmax andbT; apply/subsetP=> F maxF.
+ rewrite inE; have [-> _]:= pmaxElemP maxF; have [_ _ <-]:= pnElemP EprE.
+ by apply/eqP; congr (logn p _); apply/eqP; rewrite eqn_leq !card_max.
+move=> E F maxE maxF; set U := E :&: F.
+have [sUE sUF]: U \subset E /\ U \subset F by apply/andP; rewrite -subsetI.
+have sZU: 'Z(G) \subset U by rewrite subsetI !sZmax.
+have [EpE _]:= pmaxElemP maxE; have{EpE} [sEG abelE] := pElemP EpE.
+have [EpF _]:= pmaxElemP maxF; have{EpF} [sFG abelF] := pElemP EpF.
+have [V] := abelem_split_dprod abelE sUE; case/dprodP=> _ defE cUV tiUV.
+have [W] := abelem_split_dprod abelF sUF; case/dprodP=> _ defF _ tiUW.
+have [sVE sWF]: V \subset E /\ W \subset F by rewrite -defE -defF !mulG_subr.
+have [sVG sWG] := (subset_trans sVE sEG, subset_trans sWF sFG).
+rewrite -defE -defF !TI_cardMg // leq_pmul2l ?cardG_gt0 //.
+rewrite -(leq_pmul2r (cardG_gt0 'C_G(W))) mul_cardG.
+rewrite card_subcent_extraspecial // mulnCA Lagrange // mulnC.
+rewrite leq_mul ?subset_leq_card //; last by rewrite mul_subG ?subsetIl.
+apply: subset_trans (sub1G _); rewrite -tiUV !subsetI subsetIl subIset ?sVE //=.
+rewrite -(pmaxElem_LdivP p_pr maxF) -defF centM -!setIA -(setICA 'C(W)).
+rewrite setIC setIA setIS // subsetI cUV sub_LdivT.
+by case/and3P: (abelemS sVE abelE).
+Qed.
+
+End ExtraspecialFormspace.
+
+(* This is B & G, Theorem 4.15, as done in Aschbacher (23.8) *)
+Lemma critical_extraspecial R S :
+ p.-group R -> S \subset R -> extraspecial S -> [~: S, R] \subset S^`(1) ->
+ S \* 'C_R(S) = R.
+Proof.
+move=> pR sSR esS sSR_S'; have [[defPhi defS'] _] := esS.
+have [pS [sPS nPS]] := (pgroupS sSR pR, andP (Phi_normal S : 'Phi(S) <| S)).
+have{esS} oZS: #|'Z(S)| = p := card_center_extraspecial pS esS.
+have nSR: R \subset 'N(S) by rewrite -commg_subl (subset_trans sSR_S') ?der_sub.
+have nsCR: 'C_R(S) <| R by rewrite (normalGI nSR) ?cent_normal.
+have nCS: S \subset 'N('C_R(S)) by rewrite cents_norm // centsC subsetIr.
+rewrite cprodE ?subsetIr //= -{2}(quotientGK nsCR) normC -?quotientK //.
+congr (_ @*^-1 _); apply/eqP; rewrite eqEcard quotientS //=.
+rewrite -(card_isog (second_isog nCS)) setIAC (setIidPr sSR) /= -/'Z(S) -defPhi.
+rewrite -ker_conj_aut (card_isog (first_isog_loc _ nSR)) //=; set A := _ @* R.
+have{pS} abelSb := Phi_quotient_abelem pS; have [pSb cSSb _] := and3P abelSb.
+have [/= Xb defSb oXb] := grank_witness (S / 'Phi(S)).
+pose X := (repr \o val : coset_of _ -> gT) @: Xb.
+have sXS: X \subset S; last have nPX := subset_trans sXS nPS.
+ apply/subsetP=> x; case/imsetP=> xb Xxb ->; have nPx := repr_coset_norm xb.
+ rewrite -sub1set -(quotientSGK _ sPS) ?sub1set ?quotient_set1 //= sub1set.
+ by rewrite coset_reprK -defSb mem_gen.
+have defS: <<X>> = S.
+ apply: Phi_nongen; apply/eqP; rewrite eqEsubset join_subG sPS sXS -joing_idr.
+ rewrite -genM_join sub_gen // -quotientSK ?quotient_gen // -defSb genS //.
+ apply/subsetP=> xb Xxb; apply/imsetP; rewrite (setIidPr nPX).
+ by exists (repr xb); rewrite /= ?coset_reprK //; exact: mem_imset.
+pose f (a : {perm gT}) := [ffun x => if x \in X then x^-1 * a x else 1].
+have injf: {in A &, injective f}.
+ move=> _ _ /morphimP[y nSy Ry ->] /morphimP[z nSz Rz ->].
+ move/ffunP=> eq_fyz; apply: (@eq_Aut _ S); rewrite ?Aut_aut //= => x Sx.
+ rewrite !norm_conj_autE //; apply: canRL (conjgKV z) _; rewrite -conjgM.
+ rewrite /conjg -(centP _ x Sx) ?mulKg {x Sx}// -defS cent_gen -sub_cent1.
+ apply/subsetP=> x Xx; have Sx := subsetP sXS x Xx.
+ move/(_ x): eq_fyz; rewrite !ffunE Xx !norm_conj_autE // => /mulgI xy_xz.
+ by rewrite cent1C inE conjg_set1 conjgM xy_xz conjgK.
+have sfA_XS': f @: A \subset pffun_on 1 X S^`(1).
+ apply/subsetP=> _ /imsetP[_ /morphimP[y nSy Ry ->] ->].
+ apply/pffun_onP; split=> [|_ /imageP[x /= Xx ->]].
+ by apply/subsetP=> x; apply: contraR; rewrite ffunE => /negPf->.
+ have Sx := subsetP sXS x Xx.
+ by rewrite ffunE Xx norm_conj_autE // (subsetP sSR_S') ?mem_commg.
+rewrite -(card_in_imset injf) (leq_trans (subset_leq_card sfA_XS')) // defS'.
+rewrite card_pffun_on (card_pgroup pSb) -rank_abelem -?grank_abelian // -oXb.
+by rewrite -oZS ?leq_pexp2l ?cardG_gt0 ?leq_imset_card.
+Qed.
+
+(* This is part of Aschbacher (23.13) and (23.14). *)
+Theorem extraspecial_structure S : p.-group S -> extraspecial S ->
+ {Es | all (fun E => (#|E| == p ^ 3)%N && ('Z(E) == 'Z(S))) Es
+ & \big[cprod/1%g]_(E <- Es) E \* 'Z(S) = S}.
+Proof.
+elim: {S}_.+1 {-2}S (ltnSn #|S|) => // m IHm S leSm pS esS.
+have [x Z'x]: {x | x \in S :\: 'Z(S)}.
+ apply/sigW/set0Pn; rewrite -subset0 subDset setU0.
+ apply: contra (extraspecial_nonabelian esS) => sSZ.
+ exact: abelianS sSZ (center_abelian S).
+have [E [R [[oE oR]]]]:= split1_extraspecial pS esS Z'x.
+case=> defS _ [defZE defZR] _; case: ifP => [_ defR | _ esR].
+ by exists [:: E]; rewrite /= ?oE ?defZE ?eqxx // big_seq1 -defR.
+have sRS: R \subset S by case/cprodP: defS => _ <- _; rewrite mulG_subr.
+have [|Es esEs defR] := IHm _ _ (pgroupS sRS pS) esR.
+ rewrite oR (leq_trans (ltn_Pdiv _ _)) ?cardG_gt0 // (ltn_exp2l 0) //.
+ exact: prime_gt1 (extraspecial_prime pS esS).
+exists (E :: Es); first by rewrite /= oE defZE !eqxx -defZR.
+by rewrite -defZR big_cons -cprodA defR.
+Qed.
+
+Section StructureCorollaries.
+
+Variable S : {group gT}.
+Hypotheses (pS : p.-group S) (esS : extraspecial S).
+
+Let p_pr := extraspecial_prime pS esS.
+Let oZ := card_center_extraspecial pS esS.
+
+(* This is Aschbacher (23.10)(2). *)
+Lemma card_extraspecial : {n | n > 0 & #|S| = (p ^ n.*2.+1)%N}.
+Proof.
+exists (logn p #|S|)./2.
+ rewrite half_gt0 ltnW // -(leq_exp2l _ _ (prime_gt1 p_pr)) -card_pgroup //.
+ exact: min_card_extraspecial.
+have [Es] := extraspecial_structure pS esS.
+elim: Es {3 4 5}S => [_ _ <-| E s IHs T] /=.
+ by rewrite big_nil cprod1g oZ (pfactorK 1).
+rewrite -andbA big_cons -cprodA; case/and3P; move/eqP=> oEp3; move/eqP=> defZE.
+move/IHs=> {IHs}IHs; case/cprodP=> [[_ U _ defU]]; rewrite defU => defT cEU.
+rewrite -(mulnK #|T| (cardG_gt0 (E :&: U))) -defT -mul_cardG /=.
+have ->: E :&: U = 'Z(S).
+ apply/eqP; rewrite eqEsubset subsetI -{1 2}defZE subsetIl setIS //=.
+ by case/cprodP: defU => [[V _ -> _]] <- _; exact: mulG_subr.
+rewrite (IHs U) // oEp3 oZ -expnD addSn expnS mulKn ?prime_gt0 //.
+by rewrite pfactorK //= uphalf_double.
+Qed.
+
+Lemma Aut_extraspecial_full : Aut_in (Aut S) 'Z(S) \isog Aut 'Z(S).
+Proof.
+have [p_gt1 p_gt0] := (prime_gt1 p_pr, prime_gt0 p_pr).
+have [Es] := extraspecial_structure pS esS.
+elim: Es S oZ => [T _ _ <-| E s IHs T oZT] /=.
+ rewrite big_nil cprod1g (center_idP (center_abelian T)).
+ by apply/Aut_sub_fullP=> // g injg gZ; exists g.
+rewrite -andbA big_cons -cprodA; case/and3P; move/eqP=> oE; move/eqP=> defZE.
+move=> es_s; case/cprodP=> [[_ U _ defU]]; rewrite defU => defT cEU.
+have sUT: U \subset T by rewrite -defT mulG_subr.
+have sZU: 'Z(T) \subset U.
+ by case/cprodP: defU => [[V _ -> _] <- _]; exact: mulG_subr.
+have defZU: 'Z(E) = 'Z(U).
+ apply/eqP; rewrite eqEsubset defZE subsetI sZU subIset ?centS ?orbT //=.
+ by rewrite subsetI subIset ?sUT //= -defT centM setSI.
+apply: (Aut_cprod_full _ defZU); rewrite ?cprodE //; last first.
+ by apply: IHs; rewrite -?defZU ?defZE.
+have oZE: #|'Z(E)| = p by rewrite defZE.
+have [p2 | odd_p] := even_prime p_pr.
+ suffices <-: restr_perm 'Z(E) @* Aut E = Aut 'Z(E) by exact: Aut_in_isog.
+ apply/eqP; rewrite eqEcard restr_perm_Aut ?center_sub //=.
+ by rewrite card_Aut_cyclic ?prime_cyclic ?oZE // {1}p2 cardG_gt0.
+have pE: p.-group E by rewrite /pgroup oE pnat_exp pnat_id.
+have nZE: E \subset 'N('Z(E)) by rewrite normal_norm ?center_normal.
+have esE: extraspecial E := card_p3group_extraspecial p_pr oE oZE.
+have [[defPhiE defE'] prZ] := esE.
+have{defPhiE} sEpZ x: x \in E -> (x ^+ p)%g \in 'Z(E).
+ move=> Ex; rewrite -defPhiE (Phi_joing pE) mem_gen // inE orbC.
+ by rewrite (Mho_p_elt 1) // (mem_p_elt pE).
+have ltZE: 'Z(E) \proper E by rewrite properEcard subsetIl oZE oE (ltn_exp2l 1).
+have [x [Ex notZx oxp]]: exists x, [/\ x \in E, x \notin 'Z(E) & #[x] %| p]%N.
+ have [_ [x Ex notZx]] := properP ltZE.
+ case: (prime_subgroupVti <[x ^+ p]> prZ) => [sZxp | ]; last first.
+ move/eqP; rewrite (setIidPl _) ?cycle_subG ?sEpZ //.
+ by rewrite cycle_eq1 -order_dvdn; exists x.
+ have [y Ey notxy]: exists2 y, y \in E & y \notin <[x]>.
+ apply/subsetPn; apply: contra (extraspecial_nonabelian esE) => sEx.
+ by rewrite (abelianS sEx) ?cycle_abelian.
+ have: (y ^+ p)%g \in <[x ^+ p]> by rewrite (subsetP sZxp) ?sEpZ.
+ case/cycleP=> i def_yp; set xi := (x ^- i)%g.
+ have Exi: xi \in E by rewrite groupV groupX.
+ exists (y * xi)%g; split; first by rewrite groupM.
+ have sxpx: <[x ^+ p]> \subset <[x]> by rewrite cycle_subG mem_cycle.
+ apply: contra notxy; move/(subsetP (subset_trans sZxp sxpx)).
+ by rewrite groupMr // groupV mem_cycle.
+ pose z := [~ xi, y]; have Zz: z \in 'Z(E) by rewrite -defE' mem_commg.
+ case: (setIP Zz) => _; move/centP=> cEz.
+ rewrite order_dvdn expMg_Rmul; try by apply: commute_sym; apply: cEz.
+ rewrite def_yp expgVn -!expgM mulnC mulgV mul1g -order_dvdn.
+ by rewrite (dvdn_trans (order_dvdG Zz)) //= oZE bin2odd // dvdn_mulr.
+have{oxp} ox: #[x] = p.
+ apply/eqP; case/primeP: p_pr => _ dvd_p; case/orP: (dvd_p _ oxp) => //.
+ by rewrite order_eq1; case: eqP notZx => // ->; rewrite group1.
+have [y Ey not_cxy]: exists2 y, y \in E & y \notin 'C[x].
+ by apply/subsetPn; rewrite sub_cent1; rewrite inE Ex in notZx.
+have notZy: y \notin 'Z(E).
+ apply: contra not_cxy; rewrite inE Ey; apply: subsetP.
+ by rewrite -cent_set1 centS ?sub1set.
+pose K := 'C_E[y]; have maxK: maximal K E by exact: cent1_extraspecial_maximal.
+have nsKE: K <| E := p_maximal_normal pE maxK; have [sKE nKE] := andP nsKE.
+have oK: #|K| = (p ^ 2)%N.
+ by rewrite -(divg_indexS sKE) oE (p_maximal_index pE) ?mulKn.
+have cKK: abelian K := card_p2group_abelian p_pr oK.
+have sZK: 'Z(E) \subset K by rewrite setIS // -cent_set1 centS ?sub1set.
+have defE: K ><| <[x]> = E.
+ have notKx: x \notin K by rewrite inE Ex cent1C.
+ rewrite sdprodE ?(mulg_normal_maximal nsKE) ?cycle_subG ?(subsetP nKE) //.
+ by rewrite setIC prime_TIg -?orderE ?ox ?cycle_subG.
+have /cyclicP[z defZ]: cyclic 'Z(E) by rewrite prime_cyclic ?oZE.
+apply/(Aut_sub_fullP (center_sub E)); rewrite /= defZ => g injg gZ.
+pose k := invm (injm_Zp_unitm z) (aut injg gZ).
+have fM: {in K &, {morph expgn^~ (val k): u v / u * v}}.
+ by move=> u v Ku Kv; rewrite /= expgMn // /commute (centsP cKK).
+pose f := Morphism fM; have fK: f @* K = K.
+ apply/setP=> u; rewrite morphimEdom.
+ apply/imsetP/idP=> [[v Kv ->] | Ku]; first exact: groupX.
+ exists (u ^+ expg_invn K (val k)); first exact: groupX.
+ rewrite /f /= expgAC expgK // oK coprime_expl // -unitZpE //.
+ by case: (k) => /=; rewrite orderE -defZ oZE => j; rewrite natr_Zp.
+have fMact: {in K & <[x]>, morph_act 'J 'J f (idm <[x]>)}.
+ by move=> u v _ _; rewrite /= conjXg.
+exists (sdprodm_morphism defE fMact).
+rewrite im_sdprodm injm_sdprodm injm_idm -card_im_injm im_idm fK.
+have [_ -> _ ->] := sdprodP defE; rewrite !eqxx; split=> //= u Zu.
+rewrite sdprodmEl ?(subsetP sZK) ?defZ // -(autE injg gZ Zu).
+rewrite -[aut _ _](invmK (injm_Zp_unitm z)); first by rewrite permE Zu.
+by rewrite im_Zp_unitm Aut_aut.
+Qed.
+
+(* These are the parts of Aschbacher (23.12) and exercise 8.5 that are later *)
+(* used in Aschbacher (34.9), which itself replaces the informal discussion *)
+(* quoted from Gorenstein in the proof of B & G, Theorem 2.5. *)
+Lemma center_aut_extraspecial k : coprime k p ->
+ exists2 f, f \in Aut S & forall z, z \in 'Z(S) -> f z = (z ^+ k)%g.
+Proof.
+have /cyclicP[z defZ]: cyclic 'Z(S) by rewrite prime_cyclic ?oZ.
+have oz: #[z] = p by rewrite orderE -defZ.
+rewrite coprime_sym -unitZpE ?prime_gt1 // -oz => u_k.
+pose g := Zp_unitm (FinRing.unit 'Z_#[z] u_k).
+have AutZg: g \in Aut 'Z(S) by rewrite defZ -im_Zp_unitm mem_morphim ?inE.
+have ZSfull := Aut_sub_fullP (center_sub S) Aut_extraspecial_full.
+have [f [injf fS fZ]] := ZSfull _ (injm_autm AutZg) (im_autm AutZg).
+exists (aut injf fS) => [|u Zu]; first exact: Aut_aut.
+have [Su _] := setIP Zu; have z_u: u \in <[z]> by rewrite -defZ.
+by rewrite autE // fZ //= autmE permE /= z_u /cyclem expg_znat.
+Qed.
+
+End StructureCorollaries.
+
+End Extraspecial.
+
+Section SCN.
+
+Variables (gT : finGroupType) (p : nat) (G : {group gT}).
+Implicit Types A Z H : {group gT}.
+
+Lemma SCN_P A : reflect (A <| G /\ 'C_G(A) = A) (A \in 'SCN(G)).
+Proof. by apply: (iffP setIdP) => [] [->]; move/eqP. Qed.
+
+Lemma SCN_abelian A : A \in 'SCN(G) -> abelian A.
+Proof. by case/SCN_P=> _ defA; rewrite /abelian -{1}defA subsetIr. Qed.
+
+Lemma exponent_Ohm1_class2 H :
+ odd p -> p.-group H -> nil_class H <= 2 -> exponent 'Ohm_1(H) %| p.
+Proof.
+move=> odd_p pH; rewrite nil_class2 => sH'Z; apply/exponentP=> x /=.
+rewrite (OhmE 1 pH) expn1 gen_set_id => {x} [/LdivP[] //|].
+apply/group_setP; split=> [|x y]; first by rewrite !inE group1 expg1n //=.
+case/LdivP=> Hx xp1 /LdivP[Hy yp1]; rewrite !inE groupM //=.
+have [_ czH]: [~ y, x] \in H /\ centralises [~ y, x] H.
+ by apply/centerP; rewrite (subsetP sH'Z) ?mem_commg.
+rewrite expMg_Rmul ?xp1 ?yp1 /commute ?czH //= !mul1g.
+by rewrite bin2odd // -commXXg ?yp1 /commute ?czH // comm1g.
+Qed.
+
+(* SCN_max and max_SCN cover Aschbacher 23.15(1) *)
+Lemma SCN_max A : A \in 'SCN(G) -> [max A | A <| G & abelian A].
+Proof.
+case/SCN_P => nAG scA; apply/maxgroupP; split=> [|H].
+ by rewrite nAG /abelian -{1}scA subsetIr.
+do 2![case/andP]=> sHG _ abelH sAH; apply/eqP.
+by rewrite eqEsubset sAH -scA subsetI sHG centsC (subset_trans sAH).
+Qed.
+
+Lemma max_SCN A :
+ p.-group G -> [max A | A <| G & abelian A] -> A \in 'SCN(G).
+Proof.
+move/pgroup_nil=> nilG; rewrite /abelian.
+case/maxgroupP=> /andP[nsAG abelA] maxA; have [sAG nAG] := andP nsAG.
+rewrite inE nsAG eqEsubset /= andbC subsetI abelA normal_sub //=.
+rewrite -quotient_sub1; last by rewrite subIset 1?normal_norm.
+apply/trivgP; apply: (TI_center_nil (quotient_nil A nilG)).
+ by rewrite quotient_normal // /normal subsetIl normsI ?normG ?norms_cent.
+apply/trivgP/subsetP=> _ /setIP[/morphimP[x Nx /setIP[_ Cx]] ->].
+rewrite -cycle_subG in Cx => /setIP[GAx CAx].
+have{CAx GAx}: <[coset A x]> <| G / A.
+ by rewrite /normal cycle_subG GAx cents_norm // centsC cycle_subG.
+case/(inv_quotientN nsAG)=> B /= defB sAB nBG.
+rewrite -cycle_subG defB (maxA B) ?trivg_quotient // nBG.
+have{defB} defB : B :=: A * <[x]>.
+ rewrite -quotientK ?cycle_subG ?quotient_cycle // defB quotientGK //.
+ exact: normalS (normal_sub nBG) nsAG.
+apply/setIidPl; rewrite ?defB -[_ :&: _]center_prod //=.
+rewrite /center !(setIidPl _) //; exact: cycle_abelian.
+Qed.
+
+(* The two other assertions of Aschbacher 23.15 state properties of the *)
+(* normal series 1 <| Z = 'Ohm_1(A) <| A with A \in 'SCN(G). *)
+
+Section SCNseries.
+
+Variables A : {group gT}.
+Hypothesis SCN_A : A \in 'SCN(G).
+
+Let Z := 'Ohm_1(A).
+Let cAA := SCN_abelian SCN_A.
+Let sZA: Z \subset A := Ohm_sub 1 A.
+Let nZA : A \subset 'N(Z) := sub_abelian_norm cAA sZA.
+
+(* This is Aschbacher 23.15(2). *)
+Lemma der1_stab_Ohm1_SCN_series : ('C(Z) :&: 'C_G(A / Z | 'Q))^`(1) \subset A.
+Proof.
+case/SCN_P: SCN_A => /andP[sAG nAG] {4} <-.
+rewrite subsetI {1}setICA comm_subG ?subsetIl //= gen_subG.
+apply/subsetP=> w /imset2P[u v].
+rewrite -groupV -(groupV _ v) /= astabQR //= -/Z !inE groupV.
+case/and4P=> cZu _ _ sRuZ /and4P[cZv' _ _ sRvZ] ->{w}.
+apply/centP=> a Aa; rewrite /commute -!mulgA (commgCV v) (mulgA u).
+rewrite (centP cZu); last by rewrite (subsetP sRvZ) ?mem_commg ?set11 ?groupV.
+rewrite 2!(mulgA v^-1) mulKVg 4!mulgA invgK (commgC u^-1) mulgA.
+rewrite -(mulgA _ _ v^-1) -(centP cZv') ?(subsetP sRuZ) ?mem_commg ?set11//.
+by rewrite -!mulgA invgK mulKVg !mulKg.
+Qed.
+
+(* This is Aschbacher 23.15(3); note that this proof does not depend on the *)
+(* maximality of A. *)
+Lemma Ohm1_stab_Ohm1_SCN_series :
+ odd p -> p.-group G -> 'Ohm_1('C_G(Z)) \subset 'C_G(A / Z | 'Q).
+Proof.
+have [-> | ntG] := eqsVneq G 1; first by rewrite !(setIidPl (sub1G _)) Ohm1.
+move=> p_odd pG; have{ntG} [p_pr _ _] := pgroup_pdiv pG ntG.
+case/SCN_P: SCN_A => /andP[sAG nAG] _; have pA := pgroupS sAG pG.
+have pCGZ : p.-group 'C_G(Z) by rewrite (pgroupS _ pG) // subsetIl.
+rewrite {pCGZ}(OhmE 1 pCGZ) gen_subG; apply/subsetP=> x; rewrite 3!inE -andbA.
+rewrite -!cycle_subG => /and3P[sXG cZX xp1] /=; have cXX := cycle_abelian x.
+have nZX := cents_norm cZX; have{nAG} nAX := subset_trans sXG nAG.
+pose XA := <[x]> <*> A; pose C := 'C(<[x]> / Z | 'Q); pose CA := A :&: C.
+pose Y := <[x]> <*> CA; pose W := 'Ohm_1(Y).
+have sXC: <[x]> \subset C by rewrite sub_astabQ nZX (quotient_cents _ cXX).
+have defY : Y = <[x]> * CA by rewrite -norm_joinEl // normsI ?nAX ?normsG.
+have{nAX} defXA: XA = <[x]> * A := norm_joinEl nAX.
+suffices{sXC}: XA \subset Y.
+ rewrite subsetI sXG /= sub_astabQ nZX centsC defY group_modl //= -/Z -/C.
+ by rewrite subsetI sub_astabQ defXA quotientMl //= !mulG_subG; case/and4P.
+have sZCA: Z \subset CA by rewrite subsetI sZA [C]astabQ sub_cosetpre.
+have cZCA: CA \subset 'C(Z) by rewrite subIset 1?(sub_abelian_cent2 cAA).
+have sZY: Z \subset Y by rewrite (subset_trans sZCA) ?joing_subr.
+have{cZCA cZX} cZY: Y \subset 'C(Z) by rewrite join_subG cZX.
+have{cXX nZX} sY'Z : Y^`(1) \subset Z.
+ rewrite der1_min ?cents_norm //= -/Y defY quotientMl // abelianM /= -/Z -/CA.
+ rewrite !quotient_abelian // ?(abelianS _ cAA) ?subsetIl //=.
+ by rewrite /= quotientGI ?Ohm_sub // quotient_astabQ subsetIr.
+have{sY'Z cZY} nil_classY: nil_class Y <= 2.
+ by rewrite nil_class2 (subset_trans sY'Z ) // subsetI sZY centsC.
+have pY: p.-group Y by rewrite (pgroupS _ pG) // join_subG sXG subIset ?sAG.
+have sXW: <[x]> \subset W.
+ by rewrite [W](OhmE 1 pY) ?genS // sub1set !inE -cycle_subG joing_subl.
+have{nil_classY pY sXW sZY sZCA} defW: W = <[x]> * Z.
+ rewrite -[W](setIidPr (Ohm_sub _ _)) /= -/Y {1}defY -group_modl //= -/Y -/W.
+ congr (_ * _); apply/eqP; rewrite eqEsubset {1}[Z](OhmE 1 pA).
+ rewrite subsetI setIAC subIset //; first by rewrite sZCA -[Z]Ohm_id OhmS.
+ rewrite sub_gen ?setIS //; apply/subsetP=> w Ww; rewrite inE.
+ by apply/eqP; apply: exponentP w Ww; exact: exponent_Ohm1_class2.
+have{sXG sAG} sXAG: XA \subset G by rewrite join_subG sXG.
+have{sXAG} nilXA: nilpotent XA := nilpotentS sXAG (pgroup_nil pG).
+have sYXA: Y \subset XA by rewrite defY defXA mulgS ?subsetIl.
+rewrite -[Y](nilpotent_sub_norm nilXA) {nilXA sYXA}//= -/Y -/XA.
+apply: subset_trans (setIS _ (char_norm_trans (Ohm_char 1 _) (subxx _))) _.
+rewrite {XA}defXA -group_modl ?normsG /= -/W ?{W}defW ?mulG_subl //.
+rewrite {Y}defY mulgS // subsetI subsetIl {CA C}sub_astabQ subIset ?nZA //= -/Z.
+rewrite (subset_trans (quotient_subnorm _ _ _)) //= quotientMidr /= -/Z.
+rewrite -quotient_sub1 ?subIset ?cent_norm ?orbT //.
+rewrite (subset_trans (quotientI _ _ _)) ?coprime_TIg //.
+rewrite (@pnat_coprime p) // -/(pgroup p _) ?quotient_pgroup {pA}//=.
+rewrite -(setIidPr (cent_sub _)) [pnat _ _]p'group_quotient_cent_prime //.
+by rewrite (dvdn_trans (dvdn_quotient _ _)) ?order_dvdn.
+Qed.
+
+End SCNseries.
+
+(* This is Aschbacher 23.16. *)
+Lemma Ohm1_cent_max_normal_abelem Z :
+ odd p -> p.-group G -> [max Z | Z <| G & p.-abelem Z] -> 'Ohm_1('C_G(Z)) = Z.
+Proof.
+move=> p_odd pG; set X := 'Ohm_1('C_G(Z)).
+case/maxgroupP=> /andP[nsZG abelZ] maxZ.
+have [sZG nZG] := andP nsZG; have [_ cZZ expZp] := and3P abelZ.
+have{nZG} nsXG: X <| G.
+ apply: (char_normal_trans (Ohm_char 1 'C_G(Z))).
+ by rewrite /normal subsetIl normsI ?normG ?norms_cent.
+have cZX : X \subset 'C(Z) := subset_trans (Ohm_sub _ _) (subsetIr _ _).
+have{sZG expZp} sZX: Z \subset X.
+ rewrite [X](OhmE 1 (pgroupS _ pG)) ?subsetIl ?sub_gen //.
+ apply/subsetP=> x Zx; rewrite !inE ?(subsetP sZG) ?(subsetP cZZ) //=.
+ by rewrite (exponentP expZp).
+suffices{sZX} expXp: (exponent X %| p).
+ apply/eqP; rewrite eqEsubset sZX andbT -quotient_sub1 ?cents_norm //= -/X.
+ have pGq: p.-group (G / Z) by rewrite quotient_pgroup.
+ rewrite (TI_center_nil (pgroup_nil pGq)) ?quotient_normal //= -/X setIC.
+ apply/eqP/trivgPn=> [[Zd]]; rewrite inE -!cycle_subG -cycle_eq1 -subG1 /= -/X.
+ case/andP=> /sub_center_normal nsZdG.
+ have{nsZdG} [D defD sZD nsDG] := inv_quotientN nsZG nsZdG; rewrite defD.
+ have sDG := normal_sub nsDG; have nsZD := normalS sZD sDG nsZG.
+ rewrite quotientSGK ?quotient_sub1 ?normal_norm //= -/X => sDX; case/negP.
+ rewrite (maxZ D) // nsDG andbA (pgroupS sDG) ?(dvdn_trans (exponentS sDX)) //.
+ have sZZD: Z \subset 'Z(D) by rewrite subsetI sZD centsC (subset_trans sDX).
+ by rewrite (cyclic_factor_abelian sZZD) //= -defD cycle_cyclic.
+pose normal_abelian := [pred A : {group gT} | A <| G & abelian A].
+have{nsZG cZZ} normal_abelian_Z : normal_abelian Z by exact/andP.
+have{normal_abelian_Z} [A maxA sZA] := maxgroup_exists normal_abelian_Z.
+have SCN_A : A \in 'SCN(G) by apply: max_SCN pG maxA.
+move/maxgroupp: maxA => /andP[nsAG cAA] {normal_abelian}.
+have pA := pgroupS (normal_sub nsAG) pG.
+have{abelZ maxZ nsAG cAA sZA} defA1: 'Ohm_1(A) = Z.
+ apply: maxZ; last by rewrite -(Ohm1_id abelZ) OhmS.
+ by rewrite Ohm1_abelem ?(char_normal_trans (Ohm_char _ _) nsAG).
+have{SCN_A} sX'A: X^`(1) \subset A.
+ have sX_CWA1 : X \subset 'C('Ohm_1(A)) :&: 'C_G(A / 'Ohm_1(A) | 'Q).
+ rewrite subsetI /X -defA1 (Ohm1_stab_Ohm1_SCN_series _ p_odd) //= andbT.
+ exact: subset_trans (Ohm_sub _ _) (subsetIr _ _).
+ by apply: subset_trans (der1_stab_Ohm1_SCN_series SCN_A); rewrite commgSS.
+pose genXp := [pred U : {group gT} | 'Ohm_1(U) == U & ~~ (exponent U %| p)].
+apply/idPn=> expXp'; have genXp_X: genXp [group of X] by rewrite /= Ohm_id eqxx.
+have{genXp_X expXp'} [U] := mingroup_exists genXp_X; case/mingroupP; case/andP.
+move/eqP=> defU1 expUp' minU sUX; case/negP: expUp'.
+have{nsXG} pU := pgroupS (subset_trans sUX (normal_sub nsXG)) pG.
+case gsetU1: (group_set 'Ldiv_p(U)).
+ by rewrite -defU1 (OhmE 1 pU) gen_set_id // -sub_LdivT subsetIr.
+move: gsetU1; rewrite /group_set 2!inE group1 expg1n eqxx; case/subsetPn=> xy.
+case/imset2P=> x y; rewrite !inE => /andP[Ux xp1] /andP[Uy yp1] ->{xy}.
+rewrite groupM //= => nt_xyp; pose XY := <[x]> <*> <[y]>.
+have{yp1 nt_xyp} defXY: XY = U.
+ have sXY_U: XY \subset U by rewrite join_subG !cycle_subG Ux Uy.
+ rewrite [XY]minU //= eqEsubset Ohm_sub (OhmE 1 (pgroupS _ pU)) //.
+ rewrite /= joing_idl joing_idr genS; last first.
+ by rewrite subsetI subset_gen subUset !sub1set !inE xp1 yp1.
+ apply: contra nt_xyp => /exponentP-> //.
+ by rewrite groupMl mem_gen // (set21, set22).
+have: <[x]> <|<| U by rewrite nilpotent_subnormal ?(pgroup_nil pU) ?cycle_subG.
+case/subnormalEsupport=> [defU | /=].
+ by apply: dvdn_trans (exponent_dvdn U) _; rewrite -defU order_dvdn.
+set V := <<class_support <[x]> U>>; case/andP=> sVU ltVU.
+have{genXp minU xp1 sVU ltVU} expVp: exponent V %| p.
+ apply: contraR ltVU => expVp'; rewrite [V]minU //= expVp' eqEsubset Ohm_sub.
+ rewrite (OhmE 1 (pgroupS sVU pU)) genS //= subsetI subset_gen class_supportEr.
+ apply/bigcupsP=> z _; apply/subsetP=> v Vv.
+ by rewrite inE -order_dvdn (dvdn_trans (order_dvdG Vv)) // cardJg order_dvdn.
+have{A pA defA1 sX'A V expVp} Zxy: [~ x, y] \in Z.
+ rewrite -defA1 (OhmE 1 pA) mem_gen // !inE (exponentP expVp).
+ by rewrite (subsetP sX'A) //= mem_commg ?(subsetP sUX).
+ by rewrite groupMl -1?[x^-1]conjg1 mem_gen // mem_imset2 // ?groupV cycle_id.
+have{Zxy sUX cZX} cXYxy: [~ x, y] \in 'C(XY).
+ by rewrite centsC in cZX; rewrite defXY (subsetP (centS sUX)) ?(subsetP cZX).
+rewrite -defU1 exponent_Ohm1_class2 // nil_class2 -defXY der1_joing_cycles //.
+by rewrite subsetI {1}defXY !cycle_subG groupR.
+Qed.
+
+Lemma critical_class2 H : critical H G -> nil_class H <= 2.
+Proof.
+case=> [chH _ sRZ _].
+by rewrite nil_class2 (subset_trans _ sRZ) ?commSg // char_sub.
+Qed.
+
+(* This proof of the Thompson critical lemma is adapted from Aschbacher 23.6 *)
+Lemma Thompson_critical : p.-group G -> {K : {group gT} | critical K G}.
+Proof.
+move=> pG; pose qcr A := (A \char G) && ('Phi(A) :|: [~: G, A] \subset 'Z(A)).
+have [|K]:= @maxgroup_exists _ qcr 1 _.
+ by rewrite /qcr char1 center1 commG1 subUset Phi_sub subxx.
+case/maxgroupP; rewrite {}/qcr subUset => /and3P[chK sPhiZ sRZ] maxK _.
+have sKG := char_sub chK; have nKG := char_normal chK.
+exists K; split=> //; apply/eqP; rewrite eqEsubset andbC setSI //=.
+have chZ: 'Z(K) \char G by [exact: subcent_char]; have nZG := char_norm chZ.
+have chC: 'C_G(K) \char G by exact: subcent_char (char_refl G) chK.
+rewrite -quotient_sub1; last by rewrite subIset // char_norm.
+apply/trivgP; apply: (TI_center_nil (quotient_nil _ (pgroup_nil pG))).
+ rewrite quotient_normal // /normal subsetIl normsI ?normG ?norms_cent //.
+ exact: char_norm.
+apply: TI_Ohm1; apply/trivgP; rewrite -trivg_quotient -sub_cosetpre_quo //.
+rewrite morphpreI quotientGK /=; last first.
+ by apply: normalS (char_normal chZ); rewrite ?subsetIl ?setSI.
+set X := _ :&: _; pose gX := [group of X].
+have sXG: X \subset G by rewrite subIset ?subsetIl.
+have cXK: K \subset 'C(gX) by rewrite centsC 2?subIset // subxx orbT.
+rewrite subsetI centsC cXK andbT -(mul1g K) -mulSG mul1g -(cent_joinEr cXK).
+rewrite [_ <*> K]maxK ?joing_subr //= andbC (cent_joinEr cXK).
+rewrite -center_prod // (subset_trans _ (mulG_subr _ _)).
+ rewrite charM 1?charI ?(char_from_quotient (normal_cosetpre _)) //.
+ by rewrite cosetpreK (char_trans _ (center_char _)) ?Ohm_char.
+rewrite (@Phi_mulg p) ?(pgroupS _ pG) // subUset commGC commMG; last first.
+ by rewrite normsR ?(normsG sKG) // cents_norm // centsC.
+rewrite !mul_subG 1?commGC //.
+ apply: subset_trans (commgS _ (subsetIr _ _)) _.
+ rewrite -quotient_cents2 ?subsetIl // centsC // cosetpreK //.
+ by rewrite (subset_trans (Ohm_sub _ _)) // subsetIr.
+have nZX := subset_trans sXG nZG; have pX : p.-group gX by exact: pgroupS pG.
+rewrite -quotient_sub1 ?(subset_trans (Phi_sub _)) //=.
+have pXZ: p.-group (gX / 'Z(K)) by exact: morphim_pgroup.
+rewrite (quotient_Phi pX nZX) subG1 (trivg_Phi pXZ).
+apply: (abelemS (quotientS _ (subsetIr _ _))); rewrite /= cosetpreK /=.
+have pZ: p.-group 'Z(G / 'Z(K)).
+ by rewrite (pgroupS (center_sub _)) ?morphim_pgroup.
+by rewrite Ohm1_abelem ?center_abelian.
+Qed.
+
+Lemma critical_p_stab_Aut H :
+ critical H G -> p.-group G -> p.-group 'C(H | [Aut G]).
+Proof.
+move=> [chH sPhiZ sRZ eqCZ] pG; have sHG := char_sub chH.
+pose G' := (sdpair1 [Aut G] @* G)%G; pose H' := (sdpair1 [Aut G] @* H)%G.
+apply/pgroupP=> q pr_q; case/Cauchy=>//= f cHF; move: (cHF);rewrite astab_ract.
+case/setIP=> Af cHFP ofq; rewrite -cycle_subG in cHF; apply: (pgroupP pG) => //.
+pose F' := (sdpair2 [Aut G] @* <[f]>)%G.
+have trHF: [~: H', F'] = 1.
+ apply/trivgP; rewrite gen_subG; apply/subsetP=> u; case/imset2P=> x' a'.
+ case/morphimP=> x Gx Hx ->; case/morphimP=> a Aa Fa -> -> {u x' a'}.
+ by rewrite inE commgEl -sdpair_act ?(astab_act (subsetP cHF _ Fa) Hx) ?mulVg.
+have sGH_H: [~: G', H'] \subset H'.
+ by rewrite -morphimR ?(char_sub chH) // morphimS // commg_subr char_norm.
+have{trHF sGH_H} trFGH: [~: F', G', H'] = 1.
+ apply: three_subgroup; last by rewrite trHF comm1G.
+ by apply/trivgP; rewrite -trHF commSg.
+apply/negP=> qG; case: (qG); rewrite -ofq.
+suffices ->: f = 1 by rewrite order1 dvd1n.
+apply/permP=> x; rewrite perm1; case Gx: (x \in G); last first.
+ by apply: out_perm (negbT Gx); case/setIdP: Af.
+have Gfx: f x \in G by rewrite -(im_autm Af) -{1}(autmE Af) mem_morphim.
+pose y := x^-1 * f x; have Gy: y \in G by rewrite groupMl ?groupV.
+have [inj1 inj2] := (injm_sdpair1 [Aut G], injm_sdpair2 [Aut G]).
+have Hy: y \in H.
+ rewrite (subsetP (center_sub H)) // -eqCZ -cycle_subG.
+ rewrite -(injmSK inj1) ?cycle_subG // injm_subcent // subsetI.
+ rewrite morphimS ?morphim_cycle ?cycle_subG //=.
+ suffices: sdpair1 [Aut G] y \in [~: G', F'].
+ by rewrite commGC; apply: subsetP; exact/commG1P.
+ rewrite morphM ?groupV ?morphV //= sdpair_act // -commgEl.
+ by rewrite mem_commg ?mem_morphim ?cycle_id.
+have fy: f y = y := astabP cHFP _ Hy.
+have: (f ^+ q) x = x * y ^+ q.
+ elim: (q) => [|i IHi]; first by rewrite perm1 mulg1.
+ rewrite expgSr permM {}IHi -(autmE Af) morphM ?morphX ?groupX //= autmE.
+ by rewrite fy expgS mulgA mulKVg.
+move/eqP; rewrite -{1}ofq expg_order perm1 eq_mulVg1 mulKg -order_dvdn.
+case/primeP: pr_q => _ pr_q /pr_q; rewrite order_eq1 -eq_mulVg1.
+by case: eqP => //= _ /eqP oyq; case: qG; rewrite -oyq order_dvdG.
+Qed.
+
+End SCN.
+
+Implicit Arguments SCN_P [gT G A]. \ No newline at end of file