Fixpoint abelian_type_rec n G :=
if n is n'.+1 then if abelian G && (G :!=: 1) then
exponent G :: abelian_type_rec n' (tag (abelian_type_subproof G))
else [::] else [::].
Definition abelian_type (A : {set gT}) := abelian_type_rec #|A| <<A>>.

(* Specifications: *)
Lemma abelian_type_dvdn_sorted A : sorted [rel m n | n %| m] (abelian_type A).
Lemma abelian_type_gt1 A : all [pred m | m > 1] (abelian_type A).
Lemma abelian_type_sorted A : sorted geq (abelian_type A).
Theorem abelian_structure G :
abelian G ->
{b | \big[dprod/1]_(x <- b) <[x]> = G & map order b = abelian_type G}.
Lemma count_logn_dprod_cycle p n b G :
\big[dprod/1]_(x <- b) <[x]> = G ->
count [pred x | logn p #[x] > n] b = logn p #|'Ohm_n.+1(G) : 'Ohm_n(G)|.
Lemma perm_eq_abelian_type p b G :
p.-group G -> \big[dprod/1]_(x <- b) <[x]> = G -> 1 \notin b ->
perm_eq (map order b) (abelian_type G).
Lemma size_abelian_type G : abelian G -> size (abelian_type G) = 'r(G).
Lemma mul_card_Ohm_Mho_abelian n G :
abelian G -> (#|'Ohm_n(G)| * #|'Mho^n(G)|)%N = #|G|.
Lemma grank_abelian G : abelian G -> 'm(G) = 'r(G).
Lemma rank_cycle (x : gT) : 'r(<[x]>) = (x != 1).
Lemma abelian_rank1_cyclic G : abelian G -> cyclic G = ('r(G) <= 1).
Definition homocyclic A := abelian A && constant (abelian_type A).
Lemma homocyclic_Ohm_Mho n p G :
p.-group G -> homocyclic G -> 'Ohm_n(G) = 'Mho^(logn p (exponent G) - n)(G).
Lemma Ohm_Mho_homocyclic (n p : nat) G :
abelian G -> p.-group G -> 0 < n < logn p (exponent G) ->
'Ohm_n(G) = 'Mho^(logn p (exponent G) - n)(G) -> homocyclic G.
Lemma abelem_homocyclic p G : p.-abelem G -> homocyclic G.
Lemma homocyclic1 : homocyclic [1 gT].
Lemma abelian_type_homocyclic G :
homocyclic G -> abelian_type G = nseq 'r(G) (exponent G).
Lemma abelian_type_abelem p G : p.-abelem G -> abelian_type G = nseq 'r(G) p.
Lemma max_card_abelian G :
abelian G -> #|G| <= exponent G ^ 'r(G) ?= iff homocyclic G.
Lemma card_homocyclic G : homocyclic G -> #|G| = (exponent G ^ 'r(G))%N.
Lemma abelian_type_dprod_homocyclic p K H G :
K \x H = G -> p.-group G -> homocyclic G ->
abelian_type K = nseq 'r(K) (exponent G)
/\ abelian_type H = nseq 'r(H) (exponent G).
Lemma dprod_homocyclic p K H G :
K \x H = G -> p.-group G -> homocyclic G -> homocyclic K /\ homocyclic H.
Lemma exponent_dprod_homocyclic p K H G :
K \x H = G -> p.-group G -> homocyclic G -> K :!=: 1 ->
exponent K = exponent G.