diff options
| author | Enrico Tassi | 2015-03-09 11:07:53 +0100 |
|---|---|---|
| committer | Enrico Tassi | 2015-03-09 11:24:38 +0100 |
| commit | fc84c27eac260dffd8f2fb1cb56d599f1e3486d9 (patch) | |
| tree | c16205f1637c80833a4c4598993c29fa0fd8c373 /mathcomp/character/character.v | |
Initial commit
Diffstat (limited to 'mathcomp/character/character.v')
| -rw-r--r-- | mathcomp/character/character.v | 2976 |
1 files changed, 2976 insertions, 0 deletions
diff --git a/mathcomp/character/character.v b/mathcomp/character/character.v new file mode 100644 index 0000000..ac2f491 --- /dev/null +++ b/mathcomp/character/character.v @@ -0,0 +1,2976 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path div choice. +Require Import fintype tuple finfun bigop prime ssralg poly finset gproduct. +Require Import fingroup morphism perm automorphism quotient finalg action. +Require Import zmodp commutator cyclic center pgroup nilpotent sylow abelian. +Require Import matrix mxalgebra mxpoly mxrepresentation vector ssrnum algC. +Require Import classfun. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Import GroupScope GRing.Theory Num.Theory. +Local Open Scope ring_scope. + +(******************************************************************************) +(* This file contains the basic notions of character theory, based on Isaacs. *) +(* irr G == tuple of the elements of 'CF(G) that are irreducible *) +(* characters of G. *) +(* Nirr G == number of irreducible characters of G. *) +(* Iirr G == index type for the irreducible characters of G. *) +(* := 'I_(Nirr G). *) +(* 'chi_i == the i-th element of irr G, for i : Iirr G. *) +(* 'chi[G]_i Note that 'chi_0 = 1, the principal character of G. *) +(* 'Chi_i == an irreducible representation that affords 'chi_i. *) +(* socle_of_Iirr i == the Wedderburn component of the regular representation *) +(* of G, corresponding to 'Chi_i. *) +(* Iirr_of_socle == the inverse of socle_of_Iirr (which is one-to-one). *) +(* phi.[A]%CF == the image of A \in group_ring G under phi : 'CF(G). *) +(* cfRepr rG == the character afforded by the representation rG of G. *) +(* cfReg G == the regular character, afforded by the regular *) +(* representation of G. *) +(* detRepr rG == the linear character afforded by the determinant of rG. *) +(* cfDet phi == the linear character afforded by the determinant of a *) +(* representation affording phi. *) +(* 'o(phi) == the "determinential order" of phi (the multiplicative *) +(* order of cfDet phi. *) +(* phi \is a character <=> phi : 'CF(G) is a character of G or 0. *) +(* i \in irr_constt phi <=> 'chi_i is an irreducible constituent of phi: phi *) +(* has a non-zero coordinate on 'chi_i over the basis irr G. *) +(* xi \is a linear_char xi <=> xi : 'CF(G) is a linear character of G. *) +(* 'Z(chi)%CF == the center of chi when chi is a character of G, i.e., *) +(* rcenter rG where rG is a representation that affords phi. *) +(* If phi is not a character then 'Z(chi)%CF = cfker phi. *) +(* aut_Iirr u i == the index of cfAut u 'chi_i in irr G. *) +(* conjC_Iirr i == the index of 'chi_i^*%CF in irr G. *) +(* morph_Iirr i == the index of cfMorph 'chi[f @* G]_i in irr G. *) +(* isom_Iirr isoG i == the index of cfIsom isoG 'chi[G]_i in irr R. *) +(* mod_Iirr i == the index of ('chi[G / H]_i %% H)%CF in irr G. *) +(* quo_Iirr i == the index of ('chi[G]_i / H)%CF in irr (G / H). *) +(* Ind_Iirr G i == the index of 'Ind[G, H] 'chi_i, provided it is an *) +(* irreducible character (such as when if H is the inertia *) +(* group of 'chi_i). *) +(* Res_Iirr H i == the index of 'Res[H, G] 'chi_i, provided it is an *) +(* irreducible character (such as when 'chi_i is linear). *) +(* sdprod_Iirr defG i == the index of cfSdprod defG 'chi_i in irr G, given *) +(* defG : K ><| H = G. *) +(* And, for KxK : K \x H = G. *) +(* dprodl_Iirr KxH i == the index of cfDprodl KxH 'chi[K]_i in irr G. *) +(* dprodr_Iirr KxH j == the index of cfDprodr KxH 'chi[H]_j in irr G. *) +(* dprod_Iirr KxH (i, j) == the index of cfDprod KxH 'chi[K]_i 'chi[H]_j. *) +(* inv_dprod_Iirr KxH == the inverse of dprod_Iirr KxH. *) +(* The following are used to define and exploit the character table: *) +(* character_table G == the character table of G, whose i-th row lists the *) +(* values taken by 'chi_i on the conjugacy classes *) +(* of G; this is a square Nirr G x NirrG matrix. *) +(* irr_class i == the conjugacy class of G with index i : Iirr G. *) +(* class_Iirr xG == the index of xG \in classes G, in Iirr G. *) +(******************************************************************************) + +Local Notation algCF := [fieldType of algC]. + +Section AlgC. + +Variable (gT : finGroupType). + +Lemma groupC : group_closure_field algCF gT. +Proof. exact: group_closure_closed_field. Qed. + +End AlgC. + +Section Tensor. + +Variable (F : fieldType). + +Fixpoint trow (n1 : nat) : + forall (A : 'rV[F]_n1) m2 n2 (B : 'M[F]_(m2,n2)), 'M[F]_(m2,n1 * n2) := + if n1 is n'1.+1 + then + fun (A : 'M[F]_(1,(1 + n'1))) m2 n2 (B : 'M[F]_(m2,n2)) => + (row_mx (lsubmx A 0 0 *: B) (trow (rsubmx A) B)) + else (fun _ _ _ _ => 0). + +Lemma trow0 n1 m2 n2 B : @trow n1 0 m2 n2 B = 0. +Proof. +elim: n1=> //= n1 IH. +rewrite !mxE scale0r linear0. +rewrite IH //; apply/matrixP=> i j; rewrite !mxE. +by case: split=> *; rewrite mxE. +Qed. + +Definition trowb n1 m2 n2 B A := @trow n1 A m2 n2 B. + +Lemma trowbE n1 m2 n2 A B : trowb B A = @trow n1 A m2 n2 B. +Proof. by []. Qed. + +Lemma trowb_is_linear n1 m2 n2 (B : 'M_(m2,n2)) : linear (@trowb n1 m2 n2 B). +Proof. +elim: n1=> [|n1 IH] //= k A1 A2 /=; first by rewrite scaler0 add0r. +rewrite linearD /= linearZ. +apply/matrixP=> i j. +rewrite !mxE. +case: split=> a. + by rewrite !mxE mulrDl mulrA. +by rewrite linearD /= linearZ IH !mxE. +Qed. + +Canonical Structure trowb_linear n1 m2 n2 B := + Linear (@trowb_is_linear n1 m2 n2 B). + +Lemma trow_is_linear n1 m2 n2 (A : 'rV_n1) : linear (@trow n1 A m2 n2). +Proof. +elim: n1 A => [|n1 IH] //= A k A1 A2 /=; first by rewrite scaler0 add0r. +rewrite linearD /= linearZ /=. +apply/matrixP=> i j; rewrite !mxE. +by case: split=> a; rewrite ?IH !mxE. +Qed. + +Canonical Structure trow_linear n1 m2 n2 A := + Linear (@trow_is_linear n1 m2 n2 A). + +Fixpoint tprod (m1 : nat) : + forall n1 (A : 'M[F]_(m1,n1)) m2 n2 (B : 'M[F]_(m2,n2)), + 'M[F]_(m1 * m2,n1 * n2) := + if m1 is m'1.+1 + return forall n1 (A : 'M[F]_(m1,n1)) m2 n2 (B : 'M[F]_(m2,n2)), + 'M[F]_(m1 * m2,n1 * n2) + then + fun n1 (A : 'M[F]_(1 + m'1,n1)) m2 n2 B => + (col_mx (trow (usubmx A) B) (tprod (dsubmx A) B)) + else (fun _ _ _ _ _ => 0). + +Lemma dsumx_mul m1 m2 n p A B : + dsubmx ((A *m B) : 'M[F]_(m1 + m2, n)) = dsubmx (A : 'M_(m1 + m2, p)) *m B. +Proof. +apply/matrixP=> i j; rewrite !mxE; apply: eq_bigr=> k _. +by rewrite !mxE. +Qed. + +Lemma usumx_mul m1 m2 n p A B : + usubmx ((A *m B) : 'M[F]_(m1 + m2, n)) = usubmx (A : 'M_(m1 + m2, p)) *m B. +Proof. +by apply/matrixP=> i j; rewrite !mxE; apply: eq_bigr=> k _; rewrite !mxE. +Qed. + +Let trow_mul (m1 m2 n2 p2 : nat) + (A : 'rV_m1) (B1: 'M[F]_(m2,n2)) (B2 :'M[F]_(n2,p2)) : + trow A (B1 *m B2) = B1 *m trow A B2. +Proof. +elim: m1 A => [|m1 IH] A /=; first by rewrite mulmx0. +by rewrite IH mul_mx_row -scalemxAr. +Qed. + +Lemma tprodE m1 n1 p1 (A1 :'M[F]_(m1,n1)) (A2 :'M[F]_(n1,p1)) + m2 n2 p2 (B1 :'M[F]_(m2,n2)) (B2 :'M[F]_(n2,p2)) : + tprod (A1 *m A2) (B1 *m B2) = (tprod A1 B1) *m (tprod A2 B2). +Proof. +elim: m1 n1 p1 A1 A2 m2 n2 p2 B1 B2 => /= [|m1 IH]. + by move=> *; rewrite mul0mx. +move=> n1 p1 A1 A2 m2 n2 p2 B1 B2. +rewrite mul_col_mx -IH. +congr col_mx; last by rewrite dsumx_mul. +rewrite usumx_mul. +elim: n1 {A1}(usubmx (A1: 'M_(1 + m1, n1))) p1 A2=> //= [u p1 A2|]. + by rewrite [A2](flatmx0) !mulmx0 -trowbE linear0. +move=> n1 IH1 A p1 A2 //=. +set Al := lsubmx _; set Ar := rsubmx _. +set Su := usubmx _; set Sd := dsubmx _. +rewrite mul_row_col -IH1. +rewrite -{1}(@hsubmxK F 1 1 n1 A). +rewrite -{1}(@vsubmxK F 1 n1 p1 A2). +rewrite (@mul_row_col F 1 1 n1 p1). +rewrite -trowbE linearD /= trowbE -/Al. +congr (_ + _). +rewrite {1}[Al]mx11_scalar mul_scalar_mx. +by rewrite -trowbE linearZ /= trowbE -/Su trow_mul scalemxAl. +Qed. + +Let tprod_tr m1 n1 (A :'M[F]_(m1, 1 + n1)) m2 n2 (B :'M[F]_(m2, n2)) : + tprod A B = row_mx (trow (lsubmx A)^T B^T)^T (tprod (rsubmx A) B). +Proof. +elim: m1 n1 A m2 n2 B=> [|m1 IH] n1 A m2 n2 B //=. + by rewrite trmx0 row_mx0. +rewrite !IH. +pose A1 := A : 'M_(1 + m1, 1 + n1). +have F1: dsubmx (rsubmx A1) = rsubmx (dsubmx A1). + by apply/matrixP=> i j; rewrite !mxE. +have F2: rsubmx (usubmx A1) = usubmx (rsubmx A1). + by apply/matrixP=> i j; rewrite !mxE. +have F3: lsubmx (dsubmx A1) = dsubmx (lsubmx A1). + by apply/matrixP=> i j; rewrite !mxE. +rewrite tr_row_mx -block_mxEv -block_mxEh !(F1,F2,F3); congr block_mx. +- by rewrite !mxE linearZ /= trmxK. +by rewrite -trmx_dsub. +Qed. + +Lemma tprod1 m n : tprod (1%:M : 'M[F]_(m,m)) (1%:M : 'M[F]_(n,n)) = 1%:M. +Proof. +elim: m n => [|m IH] n //=; first by rewrite [1%:M]flatmx0. +rewrite tprod_tr. +set u := rsubmx _; have->: u = 0. + apply/matrixP=> i j; rewrite !mxE. + by case: i; case: j=> /= j Hj; case. +set v := lsubmx (dsubmx _); have->: v = 0. + apply/matrixP=> i j; rewrite !mxE. + by case: i; case: j; case. +set w := rsubmx _; have->: w = 1%:M. + apply/matrixP=> i j; rewrite !mxE. + by case: i; case: j; case. +rewrite IH -!trowbE !linear0. +rewrite -block_mxEv. +set z := (lsubmx _) 0 0; have->: z = 1. + by rewrite /z !mxE eqxx. +by rewrite scale1r scalar_mx_block. +Qed. + +Lemma mxtrace_prod m n (A :'M[F]_(m)) (B :'M[F]_(n)) : + \tr (tprod A B) = \tr A * \tr B. +Proof. +elim: m n A B => [|m IH] n A B //=. + by rewrite [A]flatmx0 mxtrace0 mul0r. +rewrite tprod_tr -block_mxEv mxtrace_block IH. +rewrite linearZ /= -mulrDl; congr (_ * _). +rewrite -trace_mx11 . +pose A1 := A : 'M_(1 + m). +rewrite -{3}[A](@submxK _ 1 m 1 m A1). +by rewrite (@mxtrace_block _ _ _ (ulsubmx A1)). +Qed. + +End Tensor. + +(* Representation sigma type and standard representations. *) +Section StandardRepresentation. + +Variables (R : fieldType) (gT : finGroupType) (G : {group gT}). +Local Notation reprG := (mx_representation R G). + +Record representation := + Representation {rdegree; mx_repr_of_repr :> reprG rdegree}. + +Lemma mx_repr0 : mx_repr G (fun _ : gT => 1%:M : 'M[R]_0). +Proof. by split=> // g h Hg Hx; rewrite mulmx1. Qed. + +Definition grepr0 := Representation (MxRepresentation mx_repr0). + +Lemma add_mx_repr (rG1 rG2 : representation) : + mx_repr G (fun g => block_mx (rG1 g) 0 0 (rG2 g)). +Proof. +split=> [|x y Hx Hy]; first by rewrite !repr_mx1 -scalar_mx_block. +by rewrite mulmx_block !(mulmx0, mul0mx, addr0, add0r, repr_mxM). +Qed. + +Definition dadd_grepr rG1 rG2 := + Representation (MxRepresentation (add_mx_repr rG1 rG2)). + +Section DsumRepr. + +Variables (n : nat) (rG : reprG n). + +Lemma mx_rsim_dadd (U V W : 'M_n) (rU rV : representation) + (modU : mxmodule rG U) (modV : mxmodule rG V) (modW : mxmodule rG W) : + (U + V :=: W)%MS -> mxdirect (U + V) -> + mx_rsim (submod_repr modU) rU -> mx_rsim (submod_repr modV) rV -> + mx_rsim (submod_repr modW) (dadd_grepr rU rV). +Proof. +case: rU; case: rV=> nV rV nU rU defW dxUV /=. +have tiUV := mxdirect_addsP dxUV. +move=> [fU def_nU]; rewrite -{nU}def_nU in rU fU * => inv_fU hom_fU. +move=> [fV def_nV]; rewrite -{nV}def_nV in rV fV * => inv_fV hom_fV. +pose pU := in_submod U (proj_mx U V) *m fU. +pose pV := in_submod V (proj_mx V U) *m fV. +exists (val_submod 1%:M *m row_mx pU pV) => [||g Gg]. +- by rewrite -defW (mxdirectP dxUV). +- apply/row_freeP. + pose pU' := invmx fU *m val_submod 1%:M. + pose pV' := invmx fV *m val_submod 1%:M. + exists (in_submod _ (col_mx pU' pV')). + rewrite in_submodE mulmxA -in_submodE -mulmxA mul_row_col mulmxDr. + rewrite -[pU *m _]mulmxA -[pV *m _]mulmxA !mulKVmx -?row_free_unit //. + rewrite addrC (in_submodE V) 2![val_submod 1%:M *m _]mulmxA -in_submodE. + rewrite addrC (in_submodE U) 2![val_submod 1%:M *m _]mulmxA -in_submodE. + rewrite -!val_submodE !in_submodK ?proj_mx_sub //. + by rewrite add_proj_mx ?val_submodK // val_submod1 defW. +rewrite mulmxA -val_submodE -[submod_repr _ g]mul1mx val_submodJ //. +rewrite -(mulmxA _ (rG g)) mul_mx_row -mulmxA mul_row_block !mulmx0 addr0 add0r. +rewrite !mul_mx_row; set W' := val_submod 1%:M; congr (row_mx _ _). + rewrite 3!mulmxA in_submodE mulmxA. + have hom_pU: (W' <= dom_hom_mx rG (proj_mx U V))%MS. + by rewrite val_submod1 -defW proj_mx_hom. + rewrite (hom_mxP hom_pU) // -in_submodE (in_submodJ modU) ?proj_mx_sub //. + rewrite -(mulmxA _ _ fU) hom_fU // in_submodE -2!(mulmxA W') -in_submodE. + by rewrite -mulmxA (mulmxA _ fU). +rewrite 3!mulmxA in_submodE mulmxA. +have hom_pV: (W' <= dom_hom_mx rG (proj_mx V U))%MS. + by rewrite val_submod1 -defW addsmxC proj_mx_hom // capmxC. +rewrite (hom_mxP hom_pV) // -in_submodE (in_submodJ modV) ?proj_mx_sub //. +rewrite -(mulmxA _ _ fV) hom_fV // in_submodE -2!(mulmxA W') -in_submodE. +by rewrite -mulmxA (mulmxA _ fV). +Qed. + +Lemma mx_rsim_dsum (I : finType) (P : pred I) U rU (W : 'M_n) + (modU : forall i, mxmodule rG (U i)) (modW : mxmodule rG W) : + let S := (\sum_(i | P i) U i)%MS in (S :=: W)%MS -> mxdirect S -> + (forall i, mx_rsim (submod_repr (modU i)) (rU i : representation)) -> + mx_rsim (submod_repr modW) (\big[dadd_grepr/grepr0]_(i | P i) rU i). +Proof. +move=> /= defW dxW rsimU. +rewrite mxdirectE /= -!(big_filter _ P) in dxW defW *. +elim: {P}(filter P _) => [|i e IHe] in W modW dxW defW *. + rewrite !big_nil /= in defW *. + by exists 0 => [||? _]; rewrite ?mul0mx ?mulmx0 // /row_free -defW !mxrank0. +rewrite !big_cons /= in dxW defW *. +rewrite 2!(big_nth i) !big_mkord /= in IHe dxW defW. +set Wi := (\sum_i _)%MS in defW dxW IHe. +rewrite -mxdirectE mxdirect_addsE !mxdirectE eqxx /= -/Wi in dxW. +have modWi: mxmodule rG Wi by exact: sumsmx_module. +case/andP: dxW; move/(IHe Wi modWi) {IHe}; move/(_ (eqmx_refl _))=> rsimWi. +by move/eqP; move/mxdirect_addsP=> dxUiWi; exact: mx_rsim_dadd (rsimU i) rsimWi. +Qed. + +Definition muln_grepr rW k := \big[dadd_grepr/grepr0]_(i < k) rW. + +Lemma mx_rsim_socle (sG : socleType rG) (W : sG) (rW : representation) : + let modW : mxmodule rG W := component_mx_module rG (socle_base W) in + mx_rsim (socle_repr W) rW -> + mx_rsim (submod_repr modW) (muln_grepr rW (socle_mult W)). +Proof. +set M := socle_base W => modW rsimM. +have simM: mxsimple rG M := socle_simple W. +have rankM_gt0: (\rank M > 0)%N by rewrite lt0n mxrank_eq0; case: simM. +have [I /= U_I simU]: mxsemisimple rG W by exact: component_mx_semisimple. +pose U (i : 'I_#|I|) := U_I (enum_val i). +have reindexI := reindex _ (onW_bij I (enum_val_bij I)). +rewrite mxdirectE /= !reindexI -mxdirectE /= => defW dxW. +have isoU: forall i, mx_iso rG M (U i). + move=> i; have sUiW: (U i <= W)%MS by rewrite -defW (sumsmx_sup i). + exact: component_mx_iso (simU _) sUiW. +have ->: socle_mult W = #|I|. + rewrite -(mulnK #|I| rankM_gt0); congr (_ %/ _)%N. + rewrite -defW (mxdirectP dxW) /= -sum_nat_const reindexI /=. + by apply: eq_bigr => i _; rewrite -(mxrank_iso (isoU i)). +have modU: mxmodule rG (U _) := mxsimple_module (simU _). +suff: mx_rsim (submod_repr (modU _)) rW by exact: mx_rsim_dsum defW dxW. +by move=> i; apply: mx_rsim_trans (mx_rsim_sym _) rsimM; exact/mx_rsim_iso. +Qed. + +End DsumRepr. + +Section ProdRepr. + +Variables (n1 n2 : nat) (rG1 : reprG n1) (rG2 : reprG n2). + +Lemma prod_mx_repr : mx_repr G (fun g => tprod (rG1 g) (rG2 g)). +Proof. +split=>[|i j InG JnG]; first by rewrite !repr_mx1 tprod1. +by rewrite !repr_mxM // tprodE. +Qed. + +Definition prod_repr := MxRepresentation prod_mx_repr. + +End ProdRepr. + +Lemma prod_repr_lin n2 (rG1 : reprG 1) (rG2 : reprG n2) : + {in G, forall x, let cast_n2 := esym (mul1n n2) in + prod_repr rG1 rG2 x = castmx (cast_n2, cast_n2) (rG1 x 0 0 *: rG2 x)}. +Proof. +move=> x Gx /=; set cast_n2 := esym _; rewrite /prod_repr /= !mxE !lshift0. +apply/matrixP=> i j; rewrite castmxE /=. +do 2![rewrite mxE; case: splitP => [? ? | []//]]. +by congr ((_ *: rG2 x) _ _); apply: val_inj. +Qed. + +End StandardRepresentation. + +Implicit Arguments grepr0 [R gT G]. +Prenex Implicits grepr0 dadd_grepr. + +Section Char. + +Variables (gT : finGroupType) (G : {group gT}). + +Fact cfRepr_subproof n (rG : mx_representation algCF G n) : + is_class_fun <<G>> [ffun x => \tr (rG x) *+ (x \in G)]. +Proof. +rewrite genGid; apply: intro_class_fun => [x y Gx Gy | _ /negbTE-> //]. +by rewrite groupJr // !repr_mxM ?groupM ?groupV // mxtrace_mulC repr_mxK. +Qed. +Definition cfRepr n rG := Cfun 0 (@cfRepr_subproof n rG). + +Lemma cfRepr1 n rG : @cfRepr n rG 1%g = n%:R. +Proof. by rewrite cfunE group1 repr_mx1 mxtrace1. Qed. + +Lemma cfRepr_sim n1 n2 rG1 rG2 : + mx_rsim rG1 rG2 -> @cfRepr n1 rG1 = @cfRepr n2 rG2. +Proof. +case/mx_rsim_def=> f12 [f21] fK def_rG1; apply/cfun_inP=> x Gx. +by rewrite !cfunE def_rG1 // mxtrace_mulC mulmxA fK mul1mx. +Qed. + +Lemma cfRepr0 : cfRepr grepr0 = 0. +Proof. by apply/cfun_inP=> x Gx; rewrite !cfunE Gx mxtrace1. Qed. + +Lemma cfRepr_dadd rG1 rG2 : + cfRepr (dadd_grepr rG1 rG2) = cfRepr rG1 + cfRepr rG2. +Proof. by apply/cfun_inP=> x Gx; rewrite !cfunE Gx mxtrace_block. Qed. + +Lemma cfRepr_dsum I r (P : pred I) rG : + cfRepr (\big[dadd_grepr/grepr0]_(i <- r | P i) rG i) + = \sum_(i <- r | P i) cfRepr (rG i). +Proof. exact: (big_morph _ cfRepr_dadd cfRepr0). Qed. + +Lemma cfRepr_muln rG k : cfRepr (muln_grepr rG k) = cfRepr rG *+ k. +Proof. by rewrite cfRepr_dsum /= sumr_const card_ord. Qed. + +Section StandardRepr. + +Variables (n : nat) (rG : mx_representation algCF G n). +Let sG := DecSocleType rG. +Let iG : irrType algCF G := DecSocleType _. + +Definition standard_irr (W : sG) := irr_comp iG (socle_repr W). + +Definition standard_socle i := pick [pred W | standard_irr W == i]. +Local Notation soc := standard_socle. + +Definition standard_irr_coef i := oapp (fun W => socle_mult W) 0%N (soc i). + +Definition standard_grepr := + \big[dadd_grepr/grepr0]_i + muln_grepr (Representation (socle_repr i)) (standard_irr_coef i). + +Lemma mx_rsim_standard : mx_rsim rG standard_grepr. +Proof. +pose W i := oapp val 0 (soc i); pose S := (\sum_i W i)%MS. +have C'G: [char algC]^'.-group G := algC'G G. +have [defS dxS]: (S :=: 1%:M)%MS /\ mxdirect S. + rewrite /S mxdirectE /= !(bigID soc xpredT) /=. + rewrite addsmxC big1 => [|i]; last by rewrite /W; case (soc i). + rewrite adds0mx_id addnC (@big1 nat) ?add0n => [|i]; last first. + by rewrite /W; case: (soc i); rewrite ?mxrank0. + have <-: Socle sG = 1%:M := reducible_Socle1 sG (mx_Maschke rG C'G). + have [W0 _ | noW] := pickP sG; last first. + suff no_i: (soc : pred iG) =1 xpred0 by rewrite /Socle !big_pred0 ?mxrank0. + by move=> i; rewrite /soc; case: pickP => // W0; have:= noW W0. + have irrK Wi: soc (standard_irr Wi) = Some Wi. + rewrite /soc; case: pickP => [W' | /(_ Wi)] /= /eqP // eqWi. + apply/eqP/socle_rsimP. + apply: mx_rsim_trans (rsim_irr_comp iG C'G (socle_irr _)) (mx_rsim_sym _). + by rewrite [irr_comp _ _]eqWi; exact: rsim_irr_comp (socle_irr _). + have bij_irr: {on [pred i | soc i], bijective standard_irr}. + exists (odflt W0 \o soc) => [Wi _ | i]; first by rewrite /= irrK. + by rewrite inE /soc /=; case: pickP => //= Wi; move/eqP. + rewrite !(reindex standard_irr) {bij_irr}//=. + have all_soc Wi: soc (standard_irr Wi) by rewrite irrK. + rewrite (eq_bigr val) => [|Wi _]; last by rewrite /W irrK. + rewrite !(eq_bigl _ _ all_soc); split=> //. + rewrite (eq_bigr (mxrank \o val)) => [|Wi _]; last by rewrite /W irrK. + by rewrite -mxdirectE /= Socle_direct. +pose modW i : mxmodule rG (W i) := + if soc i is Some Wi as oWi return mxmodule rG (oapp val 0 oWi) then + component_mx_module rG (socle_base Wi) + else mxmodule0 rG n. +apply: mx_rsim_trans (mx_rsim_sym (rsim_submod1 (mxmodule1 rG) _)) _ => //. +apply: mx_rsim_dsum (modW) _ defS dxS _ => i. +rewrite /W /standard_irr_coef /modW /soc; case: pickP => [Wi|_] /=; last first. + rewrite /muln_grepr big_ord0. + by exists 0 => [||x _]; rewrite ?mxrank0 ?mulmx0 ?mul0mx. +by move/eqP=> <-; apply: mx_rsim_socle; exact: rsim_irr_comp (socle_irr Wi). +Qed. + +End StandardRepr. + +Definition cfReg (B : {set gT}) : 'CF(B) := #|B|%:R *: '1_[1]. + +Lemma cfRegE x : @cfReg G x = #|G|%:R *+ (x == 1%g). +Proof. by rewrite cfunE cfuniE ?normal1 // inE mulr_natr. Qed. + +(* This is Isaacs, Lemma (2.10). *) +Lemma cfReprReg : cfRepr (regular_repr algCF G) = cfReg G. +Proof. +apply/cfun_inP=> x Gx; rewrite cfRegE. +have [-> | ntx] := altP (x =P 1%g); first by rewrite cfRepr1. +rewrite cfunE Gx [\tr _]big1 // => i _; rewrite 2!mxE /=. +rewrite -(inj_eq enum_val_inj) gring_indexK ?groupM ?enum_valP //. +by rewrite eq_mulVg1 mulKg (negbTE ntx). +Qed. + +Definition xcfun (chi : 'CF(G)) A := + (gring_row A *m (\col_(i < #|G|) chi (enum_val i))) 0 0. + +Lemma xcfun_is_additive phi : additive (xcfun phi). +Proof. by move=> A B; rewrite /xcfun linearB mulmxBl !mxE. Qed. +Canonical xcfun_additive phi := Additive (xcfun_is_additive phi). + +Lemma xcfunZr a phi A : xcfun phi (a *: A) = a * xcfun phi A. +Proof. by rewrite /xcfun linearZ -scalemxAl mxE. Qed. + +(* In order to add a second canonical structure on xcfun *) +Definition xcfun_r_head k A phi := let: tt := k in xcfun phi A. +Local Notation xcfun_r A := (xcfun_r_head tt A). + +Lemma xcfun_rE A chi : xcfun_r A chi = xcfun chi A. Proof. by []. Qed. + +Fact xcfun_r_is_additive A : additive (xcfun_r A). +Proof. +move=> phi psi; rewrite /= /xcfun !mxE -sumrB; apply: eq_bigr => i _. +by rewrite !mxE !cfunE mulrBr. +Qed. +Canonical xcfun_r_additive A := Additive (xcfun_r_is_additive A). + +Lemma xcfunZl a phi A : xcfun (a *: phi) A = a * xcfun phi A. +Proof. +rewrite /xcfun !mxE big_distrr; apply: eq_bigr => i _ /=. +by rewrite !mxE cfunE mulrCA. +Qed. + +Lemma xcfun_repr n rG A : xcfun (@cfRepr n rG) A = \tr (gring_op rG A). +Proof. +rewrite gring_opE [gring_row A]row_sum_delta !linear_sum /xcfun !mxE. +apply: eq_bigr => i _; rewrite !mxE /= !linearZ cfunE enum_valP /=. +by congr (_ * \tr _) => {A} /=; rewrite /gring_mx /= -rowE rowK mxvecK. +Qed. + +End Char. +Notation xcfun_r A := (xcfun_r_head tt A). +Notation "phi .[ A ]" := (xcfun phi A) : cfun_scope. + +Definition pred_Nirr gT B := #|@classes gT B|.-1. +Arguments Scope pred_Nirr [_ group_scope]. +Notation Nirr G := (pred_Nirr G).+1. +Notation Iirr G := 'I_(Nirr G). + +Section IrrClassDef. + +Variables (gT : finGroupType) (G : {group gT}). + +Let sG := DecSocleType (regular_repr algCF G). + +Lemma NirrE : Nirr G = #|classes G|. +Proof. by rewrite /pred_Nirr (cardD1 [1]) classes1. Qed. + +Fact Iirr_cast : Nirr G = #|sG|. +Proof. by rewrite NirrE ?card_irr ?algC'G //; exact: groupC. Qed. + +Let offset := cast_ord (esym Iirr_cast) (enum_rank [1 sG]%irr). + +Definition socle_of_Iirr (i : Iirr G) : sG := + enum_val (cast_ord Iirr_cast (i + offset)). +Definition irr_of_socle (Wi : sG) : Iirr G := + cast_ord (esym Iirr_cast) (enum_rank Wi) - offset. +Local Notation W := socle_of_Iirr. + +Lemma socle_Iirr0 : W 0 = [1 sG]%irr. +Proof. by rewrite /W add0r cast_ordKV enum_rankK. Qed. + +Lemma socle_of_IirrK : cancel W irr_of_socle. +Proof. by move=> i; rewrite /irr_of_socle enum_valK cast_ordK addrK. Qed. + +Lemma irr_of_socleK : cancel irr_of_socle W. +Proof. by move=> Wi; rewrite /W subrK cast_ordKV enum_rankK. Qed. +Hint Resolve socle_of_IirrK irr_of_socleK. + +Lemma irr_of_socle_bij (A : pred (Iirr G)) : {on A, bijective irr_of_socle}. +Proof. by apply: onW_bij; exists W. Qed. + +Lemma socle_of_Iirr_bij (A : pred sG) : {on A, bijective W}. +Proof. by apply: onW_bij; exists irr_of_socle. Qed. + +End IrrClassDef. + +Prenex Implicits socle_of_IirrK irr_of_socleK. +Arguments Scope socle_of_Iirr [_ ring_scope]. + +Notation "''Chi_' i" := (irr_repr (socle_of_Iirr i)) + (at level 8, i at level 2, format "''Chi_' i"). + +Fact irr_key : unit. Proof. by []. Qed. +Definition irr_def gT B : (Nirr B).-tuple 'CF(B) := + let irr_of i := 'Res[B, <<B>>] (@cfRepr gT _ _ 'Chi_(inord i)) in + [tuple of mkseq irr_of (Nirr B)]. +Definition irr := locked_with irr_key irr_def. + +Arguments Scope irr [_ group_scope]. + +Notation "''chi_' i" := (tnth (irr _) i%R) + (at level 8, i at level 2, format "''chi_' i") : ring_scope. +Notation "''chi[' G ]_ i" := (tnth (irr G) i%R) + (at level 8, i at level 2, only parsing) : ring_scope. + +Section IrrClass. + +Variable (gT : finGroupType) (G : {group gT}). +Implicit Types (i : Iirr G) (B : {set gT}). +Open Scope group_ring_scope. + +Lemma congr_irr i1 i2 : i1 = i2 -> 'chi_i1 = 'chi_i2. Proof. by move->. Qed. + +Lemma Iirr1_neq0 : G :!=: 1%g -> inord 1 != 0 :> Iirr G. +Proof. by rewrite -classes_gt1 -NirrE -val_eqE /= => /inordK->. Qed. + +Lemma has_nonprincipal_irr : G :!=: 1%g -> {i : Iirr G | i != 0}. +Proof. by move/Iirr1_neq0; exists (inord 1). Qed. + +Lemma irrRepr i : cfRepr 'Chi_i = 'chi_i. +Proof. +rewrite [irr]unlock (tnth_nth 0) nth_mkseq // -[<<G>>]/(gval _) genGidG. +by rewrite cfRes_id inord_val. +Qed. + +Lemma irr0 : 'chi[G]_0 = 1. +Proof. +apply/cfun_inP=> x Gx; rewrite -irrRepr cfun1E cfunE Gx. +by rewrite socle_Iirr0 irr1_repr // mxtrace1 degree_irr1. +Qed. + +Lemma cfun1_irr : 1 \in irr G. +Proof. by rewrite -irr0 mem_tnth. Qed. + +Lemma mem_irr i : 'chi_i \in irr G. +Proof. exact: mem_tnth. Qed. + +Lemma irrP xi : reflect (exists i, xi = 'chi_i) (xi \in irr G). +Proof. +apply: (iffP idP) => [/(nthP 0)[i] | [i ->]]; last exact: mem_irr. +rewrite size_tuple => lt_i_G <-. +by exists (Ordinal lt_i_G); rewrite (tnth_nth 0). +Qed. + +Let sG := DecSocleType (regular_repr algCF G). +Let C'G := algC'G G. +Let closG := @groupC _ G. +Local Notation W i := (@socle_of_Iirr _ G i). +Local Notation "''n_' i" := 'n_(W i). +Local Notation "''R_' i" := 'R_(W i). +Local Notation "''e_' i" := 'e_(W i). + +Lemma irr1_degree i : 'chi_i 1%g = ('n_i)%:R. +Proof. by rewrite -irrRepr cfRepr1. Qed. + +Lemma Cnat_irr1 i : 'chi_i 1%g \in Cnat. +Proof. by rewrite irr1_degree rpred_nat. Qed. + +Lemma irr1_gt0 i : 0 < 'chi_i 1%g. +Proof. by rewrite irr1_degree ltr0n irr_degree_gt0. Qed. + +Lemma irr1_neq0 i : 'chi_i 1%g != 0. +Proof. by rewrite eqr_le ltr_geF ?irr1_gt0. Qed. + +Lemma irr_neq0 i : 'chi_i != 0. +Proof. by apply: contraNneq (irr1_neq0 i) => ->; rewrite cfunE. Qed. + +Definition cfIirr B (chi : 'CF(B)) : Iirr B := inord (index chi (irr B)). + +Lemma cfIirrE chi : chi \in irr G -> 'chi_(cfIirr chi) = chi. +Proof. +move=> chi_irr; rewrite (tnth_nth 0) inordK ?nth_index //. +by rewrite -index_mem size_tuple in chi_irr. +Qed. + +Lemma cfIirrPE J (f : J -> 'CF(G)) (P : pred J) : + (forall j, P j -> f j \in irr G) -> + forall j, P j -> 'chi_(cfIirr (f j)) = f j. +Proof. by move=> irr_f j /irr_f; apply: cfIirrE. Qed. + +(* This is Isaacs, Corollary (2.7). *) +Corollary irr_sum_square : \sum_i ('chi[G]_i 1%g) ^+ 2 = #|G|%:R. +Proof. +rewrite -(sum_irr_degree sG) // natr_sum (reindex _ (socle_of_Iirr_bij _)) /=. +by apply: eq_bigr => i _; rewrite irr1_degree natrX. +Qed. + +(* This is Isaacs, Lemma (2.11). *) +Lemma cfReg_sum : cfReg G = \sum_i 'chi_i 1%g *: 'chi_i. +Proof. +apply/cfun_inP=> x Gx; rewrite -cfReprReg cfunE Gx (mxtrace_regular sG) //=. +rewrite sum_cfunE (reindex _ (socle_of_Iirr_bij _)); apply: eq_bigr => i _. +by rewrite -irrRepr cfRepr1 !cfunE Gx mulr_natl. +Qed. + +Let aG := regular_repr algCF G. +Let R_G := group_ring algCF G. + +Lemma xcfun_annihilate i j A : i != j -> (A \in 'R_j)%MS -> ('chi_i).[A]%CF = 0. +Proof. +move=> neq_ij RjA; rewrite -irrRepr xcfun_repr. +by rewrite (irr_repr'_op0 _ _ RjA) ?raddf0 // eq_sym (can_eq socle_of_IirrK). +Qed. + +Lemma xcfunG phi x : x \in G -> phi.[aG x]%CF = phi x. +Proof. +by move=> Gx; rewrite /xcfun /gring_row rowK -rowE !mxE !(gring_indexK, mul1g). +Qed. + +Lemma xcfun_mul_id i A : + (A \in R_G)%MS -> ('chi_i).['e_i *m A]%CF = ('chi_i).[A]%CF. +Proof. +move=> RG_A; rewrite -irrRepr !xcfun_repr gring_opM //. +by rewrite op_Wedderburn_id ?mul1mx. +Qed. + +Lemma xcfun_id i j : ('chi_i).['e_j]%CF = 'chi_i 1%g *+ (i == j). +Proof. +have [<-{j} | /xcfun_annihilate->//] := altP eqP; last exact: Wedderburn_id_mem. +by rewrite -xcfunG // repr_mx1 -(xcfun_mul_id _ (envelop_mx1 _)) mulmx1. +Qed. + +Lemma irr_free : free (irr G). +Proof. +apply/freeP=> s s0 i; apply: (mulIf (irr1_neq0 i)). +rewrite mul0r -(raddf0 (xcfun_r_additive 'e_i)) -{}s0 raddf_sum /=. +rewrite (bigD1 i) //= -tnth_nth xcfunZl xcfun_id eqxx big1 ?addr0 // => j ne_ji. +by rewrite -tnth_nth xcfunZl xcfun_id (negbTE ne_ji) mulr0. +Qed. + +Lemma irr_inj : injective (tnth (irr G)). +Proof. by apply/injectiveP/free_uniq; rewrite map_tnth_enum irr_free. Qed. + +Lemma irrK : cancel (tnth (irr G)) (@cfIirr G). +Proof. by move=> i; apply: irr_inj; rewrite cfIirrE ?mem_irr. Qed. + +Lemma irr_eq1 i : ('chi_i == 1) = (i == 0). +Proof. by rewrite -irr0 (inj_eq irr_inj). Qed. + +Lemma cforder_irr_eq1 i : (#['chi_i]%CF == 1%N) = (i == 0). +Proof. by rewrite -dvdn1 dvdn_cforder irr_eq1. Qed. + +Lemma irr_basis : basis_of 'CF(G)%VS (irr G). +Proof. +rewrite /basis_of irr_free andbT -dimv_leqif_eq ?subvf //. +by rewrite dim_cfun (eqnP irr_free) size_tuple NirrE. +Qed. + +Lemma eq_sum_nth_irr a : \sum_i a i *: 'chi[G]_i = \sum_i a i *: (irr G)`_i. +Proof. by apply: eq_bigr => i; rewrite -tnth_nth. Qed. + +(* This is Isaacs, Theorem (2.8). *) +Theorem cfun_irr_sum phi : {a | phi = \sum_i a i *: 'chi[G]_i}. +Proof. +rewrite (coord_basis irr_basis (memvf phi)) -eq_sum_nth_irr. +by exists ((coord (irr G))^~ phi). +Qed. + +Lemma cfRepr_standard n (rG : mx_representation algCF G n) : + cfRepr (standard_grepr rG) + = \sum_i (standard_irr_coef rG (W i))%:R *: 'chi_i. +Proof. +rewrite cfRepr_dsum (reindex _ (socle_of_Iirr_bij _)). +by apply: eq_bigr => i _; rewrite scaler_nat cfRepr_muln irrRepr. +Qed. + +Lemma cfRepr_inj n1 n2 rG1 rG2 : + @cfRepr _ G n1 rG1 = @cfRepr _ G n2 rG2 -> mx_rsim rG1 rG2. +Proof. +move=> eq_repr12; pose c i : algC := (standard_irr_coef _ (W i))%:R. +have [rsim1 rsim2] := (mx_rsim_standard rG1, mx_rsim_standard rG2). +apply: mx_rsim_trans (rsim1) (mx_rsim_sym _). +suffices ->: standard_grepr rG1 = standard_grepr rG2 by []. +apply: eq_bigr => Wi _; congr (muln_grepr _ _); apply/eqP; rewrite -eqC_nat. +rewrite -[Wi]irr_of_socleK -!/(c _ _ _) -!(coord_sum_free (c _ _) _ irr_free). +rewrite -!eq_sum_nth_irr -!cfRepr_standard. +by rewrite -(cfRepr_sim rsim1) -(cfRepr_sim rsim2) eq_repr12. +Qed. + +Lemma cfRepr_rsimP n1 n2 rG1 rG2 : + reflect (mx_rsim rG1 rG2) (@cfRepr _ G n1 rG1 == @cfRepr _ G n2 rG2). +Proof. by apply: (iffP eqP) => [/cfRepr_inj | /cfRepr_sim]. Qed. + +Lemma irr_reprP xi : + reflect (exists2 rG : representation _ G, mx_irreducible rG & xi = cfRepr rG) + (xi \in irr G). +Proof. +apply: (iffP (irrP xi)) => [[i ->] | [[n rG] irr_rG ->]]. + by exists (Representation 'Chi_i); [exact: socle_irr | rewrite irrRepr]. +exists (irr_of_socle (irr_comp sG rG)); rewrite -irrRepr irr_of_socleK /=. +exact/cfRepr_sim/rsim_irr_comp. +Qed. + +(* This is Isaacs, Theorem (2.12). *) +Lemma Wedderburn_id_expansion i : + 'e_i = #|G|%:R^-1 *: \sum_(x in G) 'chi_i 1%g * 'chi_i x^-1%g *: aG x. +Proof. +have Rei: ('e_i \in 'R_i)%MS by exact: Wedderburn_id_mem. +have /envelop_mxP[a def_e]: ('e_i \in R_G)%MS; last rewrite -/aG in def_e. + by move: Rei; rewrite genmxE mem_sub_gring => /andP[]. +apply: canRL (scalerK (neq0CG _)) _; rewrite def_e linear_sum /=. +apply: eq_bigr => x Gx; have Gx' := groupVr Gx; rewrite scalerA; congr (_ *: _). +transitivity (cfReg G).['e_i *m aG x^-1%g]%CF. + rewrite def_e mulmx_suml raddf_sum (bigD1 x) //= -scalemxAl xcfunZr. + rewrite -repr_mxM // mulgV xcfunG // cfRegE eqxx mulrC big1 ?addr0 //. + move=> y /andP[Gy /negbTE neq_xy]; rewrite -scalemxAl xcfunZr -repr_mxM //. + by rewrite xcfunG ?groupM // cfRegE -eq_mulgV1 neq_xy mulr0. +rewrite cfReg_sum -xcfun_rE raddf_sum /= (bigD1 i) //= xcfunZl. +rewrite xcfun_mul_id ?envelop_mx_id ?xcfunG ?groupV ?big1 ?addr0 // => j ne_ji. +rewrite xcfunZl (xcfun_annihilate ne_ji) ?mulr0 //. +have /andP[_ /(submx_trans _)-> //] := Wedderburn_ideal (W i). +by rewrite mem_mulsmx // envelop_mx_id ?groupV. +Qed. + +End IrrClass. + +Arguments Scope cfReg [_ group_scope]. +Prenex Implicits cfIirr. +Implicit Arguments irr_inj [[gT] [G] x1 x2]. + +Section IsChar. + +Variable gT : finGroupType. + +Definition character {G : {set gT}} := + [qualify a phi : 'CF(G) | [forall i, coord (irr G) i phi \in Cnat]]. +Fact character_key G : pred_key (@character G). Proof. by []. Qed. +Canonical character_keyed G := KeyedQualifier (character_key G). + +Variable G : {group gT}. +Implicit Types (phi chi xi : 'CF(G)) (i : Iirr G). + +Lemma irr_char i : 'chi_i \is a character. +Proof. +by apply/forallP=> j; rewrite (tnth_nth 0) coord_free ?irr_free ?isNatC_nat. +Qed. + +Lemma cfun1_char : (1 : 'CF(G)) \is a character. +Proof. by rewrite -irr0 irr_char. Qed. + +Lemma cfun0_char : (0 : 'CF(G)) \is a character. +Proof. by apply/forallP=> i; rewrite linear0 rpred0. Qed. + +Fact add_char : addr_closed (@character G). +Proof. +split=> [|chi xi /forallP-Nchi /forallP-Nxi]; first exact: cfun0_char. +by apply/forallP=> i; rewrite linearD rpredD /=. +Qed. +Canonical character_addrPred := AddrPred add_char. + +Lemma char_sum_irrP {phi} : + reflect (exists n, phi = \sum_i (n i)%:R *: 'chi_i) (phi \is a character). +Proof. +apply: (iffP idP)=> [/forallP-Nphi | [n ->]]; last first. + by apply: rpred_sum => i _; rewrite scaler_nat rpredMn // irr_char. +do [have [a ->] := cfun_irr_sum phi] in Nphi *; exists (truncC \o a). +apply: eq_bigr => i _; congr (_ *: _); have:= eqP (Nphi i). +by rewrite eq_sum_nth_irr coord_sum_free ?irr_free. +Qed. + +Lemma char_sum_irr chi : + chi \is a character -> {r | chi = \sum_(i <- r) 'chi_i}. +Proof. +move=> Nchi; apply: sig_eqW; case/char_sum_irrP: Nchi => n {chi}->. +elim/big_rec: _ => [|i _ _ [r ->]]; first by exists nil; rewrite big_nil. +exists (ncons (n i) i r); rewrite scaler_nat. +by elim: {n}(n i) => [|n IHn]; rewrite ?add0r //= big_cons mulrS -addrA IHn. +Qed. + +Lemma Cnat_char1 chi : chi \is a character -> chi 1%g \in Cnat. +Proof. +case/char_sum_irr=> r ->{chi}. +by elim/big_rec: _ => [|i chi _ Nchi1]; rewrite cfunE ?rpredD // Cnat_irr1. +Qed. + +Lemma char1_ge0 chi : chi \is a character -> 0 <= chi 1%g. +Proof. by move/Cnat_char1/Cnat_ge0. Qed. + +Lemma char1_eq0 chi : chi \is a character -> (chi 1%g == 0) = (chi == 0). +Proof. +case/char_sum_irr=> r ->; apply/idP/idP=> [|/eqP->]; last by rewrite cfunE. +case: r => [|i r]; rewrite ?big_nil // sum_cfunE big_cons. +rewrite paddr_eq0 ?sumr_ge0 => // [||j _]; rewrite 1?ltrW ?irr1_gt0 //. +by rewrite (negbTE (irr1_neq0 i)). +Qed. + +Lemma char1_gt0 chi : chi \is a character -> (0 < chi 1%g) = (chi != 0). +Proof. by move=> Nchi; rewrite -char1_eq0 // Cnat_gt0 ?Cnat_char1. Qed. + +Lemma char_reprP phi : + reflect (exists rG : representation algCF G, phi = cfRepr rG) + (phi \is a character). +Proof. +apply: (iffP char_sum_irrP) => [[n ->] | [[n rG] ->]]; last first. + exists (fun i => standard_irr_coef rG (socle_of_Iirr i)). + by rewrite -cfRepr_standard (cfRepr_sim (mx_rsim_standard rG)). +exists (\big[dadd_grepr/grepr0]_i muln_grepr (Representation 'Chi_i) (n i)). +rewrite cfRepr_dsum; apply: eq_bigr => i _. +by rewrite cfRepr_muln irrRepr scaler_nat. +Qed. + +Local Notation reprG := (mx_representation algCF G). + +Lemma cfRepr_char n (rG : reprG n) : cfRepr rG \is a character. +Proof. by apply/char_reprP; exists (Representation rG). Qed. + +Lemma cfReg_char : cfReg G \is a character. +Proof. by rewrite -cfReprReg cfRepr_char. Qed. + +Lemma cfRepr_prod n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) : + cfRepr rG1 * cfRepr rG2 = cfRepr (prod_repr rG1 rG2). +Proof. by apply/cfun_inP=> x Gx; rewrite !cfunE /= Gx mxtrace_prod. Qed. + +Lemma mul_char : mulr_closed (@character G). +Proof. +split=> [|_ _ /char_reprP[rG1 ->] /char_reprP[rG2 ->]]; first exact: cfun1_char. +apply/char_reprP; exists (Representation (prod_repr rG1 rG2)). +by rewrite cfRepr_prod. +Qed. +Canonical char_mulrPred := MulrPred mul_char. +Canonical char_semiringPred := SemiringPred mul_char. + +End IsChar. +Prenex Implicits character. +Implicit Arguments char_reprP [gT G phi]. + +Section AutChar. + +Variables (gT : finGroupType) (G : {group gT}). +Implicit Type u : {rmorphism algC -> algC}. + +Lemma cfRepr_map u n (rG : mx_representation algCF G n) : + cfRepr (map_repr u rG) = cfAut u (cfRepr rG). +Proof. by apply/cfun_inP=> x Gx; rewrite !cfunE Gx map_reprE trace_map_mx. Qed. + +Lemma cfAut_char u (chi : 'CF(G)) : + chi \is a character -> cfAut u chi \is a character. +Proof. +case/char_reprP=> rG ->; apply/char_reprP. +by exists (Representation (map_repr u rG)); rewrite cfRepr_map. +Qed. + +Lemma cfConjC_char (chi : 'CF(G)) : + chi \is a character -> chi^*%CF \is a character. +Proof. exact: cfAut_char. Qed. + +Lemma cfAut_char1 u (chi : 'CF(G)) : + chi \is a character -> cfAut u chi 1%g = chi 1%g. +Proof. by move/Cnat_char1=> Nchi1; rewrite cfunE aut_Cnat. Qed. + +Lemma cfAut_irr1 u i : (cfAut u 'chi[G]_i) 1%g = 'chi_i 1%g. +Proof. exact: cfAut_char1 (irr_char i). Qed. + +Lemma cfConjC_char1 (chi : 'CF(G)) : + chi \is a character -> chi^*%CF 1%g = chi 1%g. +Proof. exact: cfAut_char1. Qed. + +Lemma cfConjC_irr1 u i : ('chi[G]_i)^*%CF 1%g = 'chi_i 1%g. +Proof. exact: cfAut_irr1. Qed. + +End AutChar. + +Section Linear. + +Variables (gT : finGroupType) (G : {group gT}). + +Definition linear_char {B : {set gT}} := + [qualify a phi : 'CF(B) | (phi \is a character) && (phi 1%g == 1)]. + +Section OneChar. + +Variable xi : 'CF(G). +Hypothesis CFxi : xi \is a linear_char. + +Lemma lin_char1: xi 1%g = 1. +Proof. by case/andP: CFxi => _ /eqP. Qed. + +Lemma lin_charW : xi \is a character. +Proof. by case/andP: CFxi. Qed. + +Lemma cfun1_lin_char : (1 : 'CF(G)) \is a linear_char. +Proof. by rewrite qualifE cfun1_char /= cfun11. Qed. + +Lemma lin_charM : {in G &, {morph xi : x y / (x * y)%g >-> x * y}}. +Proof. +move=> x y Gx Gy; case/andP: CFxi => /char_reprP[[n rG] -> /=]. +rewrite cfRepr1 pnatr_eq1 => /eqP n1; rewrite {n}n1 in rG *. +rewrite !cfunE Gx Gy groupM //= !mulr1n repr_mxM //. +by rewrite [rG x]mx11_scalar [rG y]mx11_scalar -scalar_mxM !mxtrace_scalar. +Qed. + +Lemma lin_char_prod I r (P : pred I) (x : I -> gT) : + (forall i, P i -> x i \in G) -> + xi (\prod_(i <- r | P i) x i)%g = \prod_(i <- r | P i) xi (x i). +Proof. +move=> Gx; elim/(big_load (fun y => y \in G)): _. +elim/big_rec2: _ => [|i a y Pi [Gy <-]]; first by rewrite lin_char1. +by rewrite groupM ?lin_charM ?Gx. +Qed. + +Let xiMV x : x \in G -> xi x * xi (x^-1)%g = 1. +Proof. by move=> Gx; rewrite -lin_charM ?groupV // mulgV lin_char1. Qed. + +Lemma lin_char_neq0 x : x \in G -> xi x != 0. +Proof. +by move/xiMV/(congr1 (predC1 0)); rewrite /= oner_eq0 mulf_eq0 => /norP[]. +Qed. + +Lemma lin_charV x : x \in G -> xi x^-1%g = (xi x)^-1. +Proof. by move=> Gx; rewrite -[_^-1]mulr1 -(xiMV Gx) mulKf ?lin_char_neq0. Qed. + +Lemma lin_charX x n : x \in G -> xi (x ^+ n)%g = xi x ^+ n. +Proof. +move=> Gx; elim: n => [|n IHn]; first exact: lin_char1. +by rewrite expgS exprS lin_charM ?groupX ?IHn. +Qed. + +Lemma lin_char_unity_root x : x \in G -> xi x ^+ #[x] = 1. +Proof. by move=> Gx; rewrite -lin_charX // expg_order lin_char1. Qed. + +Lemma normC_lin_char x : x \in G -> `|xi x| = 1. +Proof. +move=> Gx; apply/eqP; rewrite -(@pexpr_eq1 _ _ #[x]) ?normr_ge0 //. +by rewrite -normrX // lin_char_unity_root ?normr1. +Qed. + +Lemma lin_charV_conj x : x \in G -> xi x^-1%g = (xi x)^*. +Proof. +move=> Gx; rewrite lin_charV // invC_norm mulrC normC_lin_char //. +by rewrite expr1n divr1. +Qed. + +Lemma lin_char_irr : xi \in irr G. +Proof. +case/andP: CFxi => /char_reprP[rG ->]; rewrite cfRepr1 pnatr_eq1 => /eqP n1. +by apply/irr_reprP; exists rG => //; exact/mx_abs_irrW/linear_mx_abs_irr. +Qed. + +Lemma mul_conjC_lin_char : xi * xi^*%CF = 1. +Proof. +apply/cfun_inP=> x Gx. +by rewrite !cfunE cfun1E Gx -normCK normC_lin_char ?expr1n. +Qed. + +Lemma lin_char_unitr : xi \in GRing.unit. +Proof. by apply/unitrPr; exists xi^*%CF; apply: mul_conjC_lin_char. Qed. + +Lemma invr_lin_char : xi^-1 = xi^*%CF. +Proof. by rewrite -[_^-1]mulr1 -mul_conjC_lin_char mulKr ?lin_char_unitr. Qed. + +Lemma cfAut_lin_char u : cfAut u xi \is a linear_char. +Proof. by rewrite qualifE cfunE lin_char1 rmorph1 cfAut_char ?lin_charW /=. Qed. + +Lemma cfConjC_lin_char : xi^*%CF \is a linear_char. +Proof. exact: cfAut_lin_char. Qed. + +Lemma fful_lin_char_inj : cfaithful xi -> {in G &, injective xi}. +Proof. +move=> fful_phi x y Gx Gy xi_xy; apply/eqP; rewrite eq_mulgV1 -in_set1. +rewrite (subsetP fful_phi) // inE groupM ?groupV //=; apply/forallP=> z. +have [Gz | G'z] := boolP (z \in G); last by rewrite !cfun0 ?groupMl ?groupV. +by rewrite -mulgA lin_charM ?xi_xy -?lin_charM ?groupM ?groupV // mulKVg. +Qed. + +End OneChar. + +Lemma card_Iirr_abelian : abelian G -> #|Iirr G| = #|G|. +Proof. by rewrite card_ord NirrE card_classes_abelian => /eqP. Qed. + +Lemma card_Iirr_cyclic : cyclic G -> #|Iirr G| = #|G|. +Proof. by move/cyclic_abelian/card_Iirr_abelian. Qed. + +Lemma char_abelianP : + reflect (forall i : Iirr G, 'chi_i \is a linear_char) (abelian G). +Proof. +apply: (iffP idP) => [cGG i | CF_G]. + rewrite qualifE irr_char /= irr1_degree. + by rewrite irr_degree_abelian //; last exact: groupC. +rewrite card_classes_abelian -NirrE -eqC_nat -irr_sum_square //. +rewrite -{1}[Nirr G]card_ord -sumr_const; apply/eqP/eq_bigr=> i _. +by rewrite lin_char1 ?expr1n ?CF_G. +Qed. + +Lemma irr_repr_lin_char (i : Iirr G) x : + x \in G -> 'chi_i \is a linear_char -> + irr_repr (socle_of_Iirr i) x = ('chi_i x)%:M. +Proof. +move=> Gx CFi; rewrite -irrRepr cfunE Gx. +move: (_ x); rewrite -[irr_degree _]natCK -irr1_degree lin_char1 //. +by rewrite (natCK 1) => A; rewrite trace_mx11 -mx11_scalar. +Qed. + +Fact linear_char_key B : pred_key (@linear_char B). Proof. by []. Qed. +Canonical linear_char_keted B := KeyedQualifier (linear_char_key B). +Fact linear_char_divr : divr_closed (@linear_char G). +Proof. +split=> [|chi xi Lchi Lxi]; first exact: cfun1_lin_char. +rewrite invr_lin_char // qualifE cfunE. +by rewrite rpredM ?lin_char1 ?mulr1 ?lin_charW //= cfConjC_lin_char. +Qed. +Canonical lin_char_mulrPred := MulrPred linear_char_divr. +Canonical lin_char_divrPred := DivrPred linear_char_divr. + +Lemma irr_cyclic_lin i : cyclic G -> 'chi[G]_i \is a linear_char. +Proof. by move/cyclic_abelian/char_abelianP. Qed. + +Lemma irr_prime_lin i : prime #|G| -> 'chi[G]_i \is a linear_char. +Proof. by move/prime_cyclic/irr_cyclic_lin. Qed. + +End Linear. + +Prenex Implicits linear_char. + +Section Restrict. + +Variable (gT : finGroupType) (G H : {group gT}). + +Lemma cfRepr_sub n (rG : mx_representation algCF G n) (sHG : H \subset G) : + cfRepr (subg_repr rG sHG) = 'Res[H] (cfRepr rG). +Proof. +by apply/cfun_inP => x Hx; rewrite cfResE // !cfunE Hx (subsetP sHG). +Qed. + +Lemma cfRes_char chi : chi \is a character -> 'Res[H, G] chi \is a character. +Proof. +have [sHG | not_sHG] := boolP (H \subset G). + by case/char_reprP=> rG ->; rewrite -(cfRepr_sub rG sHG) cfRepr_char. +by move/Cnat_char1=> Nchi1; rewrite cfResEout // rpredZ_Cnat ?rpred1. +Qed. + +Lemma cfRes_eq0 phi : phi \is a character -> ('Res[H, G] phi == 0) = (phi == 0). +Proof. by move=> Nchi; rewrite -!char1_eq0 ?cfRes_char // cfRes1. Qed. + +Lemma cfRes_lin_char chi : + chi \is a linear_char -> 'Res[H, G] chi \is a linear_char. +Proof. by case/andP=> Nchi; rewrite qualifE cfRes_char ?cfRes1. Qed. + +Lemma Res_irr_neq0 i : 'Res[H, G] 'chi_i != 0. +Proof. by rewrite cfRes_eq0 ?irr_neq0 ?irr_char. Qed. + +Lemma cfRes_lin_lin (chi : 'CF(G)) : + chi \is a character -> 'Res[H] chi \is a linear_char -> chi \is a linear_char. +Proof. by rewrite !qualifE cfRes1 => -> /andP[]. Qed. + +Lemma cfRes_irr_irr chi : + chi \is a character -> 'Res[H] chi \in irr H -> chi \in irr G. +Proof. +have [sHG /char_reprP[rG ->] | not_sHG Nchi] := boolP (H \subset G). + rewrite -(cfRepr_sub _ sHG) => /irr_reprP[rH irrH def_rH]; apply/irr_reprP. + suffices /subg_mx_irr: mx_irreducible (subg_repr rG sHG) by exists rG. + by apply: mx_rsim_irr irrH; exact/cfRepr_rsimP/eqP. +rewrite cfResEout // => /irrP[j Dchi_j]; apply/lin_char_irr/cfRes_lin_lin=> //. +suffices j0: j = 0 by rewrite cfResEout // Dchi_j j0 irr0 rpred1. +apply: contraNeq (irr1_neq0 j) => nz_j. +have:= xcfun_id j 0; rewrite -Dchi_j cfunE xcfunZl -irr0 xcfun_id eqxx => ->. +by rewrite (negPf nz_j). +Qed. + +Definition Res_Iirr (A B : {set gT}) i := cfIirr ('Res[B, A] 'chi_i). + +Lemma Res_Iirr0 : Res_Iirr H (0 : Iirr G) = 0. +Proof. by rewrite /Res_Iirr irr0 rmorph1 -irr0 irrK. Qed. + +Lemma lin_Res_IirrE i : 'chi[G]_i 1%g = 1 -> 'chi_(Res_Iirr H i) = 'Res 'chi_i. +Proof. +move=> chi1; rewrite cfIirrE ?lin_char_irr ?cfRes_lin_char //. +by rewrite qualifE irr_char /= chi1. +Qed. + +End Restrict. + +Arguments Scope Res_Iirr [_ group_scope group_scope ring_scope]. + +Section Morphim. + +Variables (aT rT : finGroupType) (G D : {group aT}) (f : {morphism D >-> rT}). +Implicit Type chi : 'CF(f @* G). + +Lemma cfRepr_morphim n (rfG : mx_representation algCF (f @* G) n) sGD : + cfRepr (morphim_repr rfG sGD) = cfMorph (cfRepr rfG). +Proof. +apply/cfun_inP=> x Gx; have Dx: x \in D := subsetP sGD x Gx. +by rewrite cfMorphE // !cfunE ?mem_morphim ?Gx. +Qed. + +Lemma cfMorph_char chi : chi \is a character -> cfMorph chi \is a character. +Proof. +have [sGD /char_reprP[rG ->] | outGD Nchi] := boolP (G \subset D); last first. + by rewrite cfMorphEout // rpredZ_Cnat ?rpred1 ?Cnat_char1. +apply/char_reprP; exists (Representation (morphim_repr rG sGD)). +by rewrite cfRepr_morphim. +Qed. + +Lemma cfMorph_lin_char chi : + chi \is a linear_char -> cfMorph chi \is a linear_char. +Proof. by case/andP=> Nchi; rewrite qualifE cfMorph_char ?cfMorph1. Qed. + +Lemma cfMorph_irr chi : + G \subset D -> chi \in irr (f @* G) -> cfMorph chi \in irr G. +Proof. +move=> sGD /irr_reprP[rG irrG ->]; apply/irr_reprP. +exists (Representation (morphim_repr rG sGD)); first exact/morphim_mx_irr. +apply/cfun_inP=> x Gx; rewrite !cfunElock /= sGD Gx. +by rewrite mem_morphim ?(subsetP sGD). +Qed. + +Definition morph_Iirr i := cfIirr (cfMorph 'chi[f @* G]_i). + +Lemma morph_Iirr0 : morph_Iirr 0 = 0. +Proof. by rewrite /morph_Iirr irr0 rmorph1 -irr0 irrK. Qed. + +Hypothesis sGD : G \subset D. + +Lemma morph_IirrE i : 'chi_(morph_Iirr i) = cfMorph 'chi_i. +Proof. by rewrite cfIirrE ?cfMorph_irr ?mem_irr. Qed. + +Lemma morph_Iirr_inj : injective morph_Iirr. +Proof. +by move=> i j eq_ij; apply/irr_inj/cfMorph_inj; rewrite // -!morph_IirrE eq_ij. +Qed. + +Lemma morph_Iirr_eq0 i : (morph_Iirr i == 0) = (i == 0). +Proof. by rewrite -!irr_eq1 morph_IirrE cfMorph_eq1. Qed. + +End Morphim. + +Section Isom. + +Variables (aT rT : finGroupType) (G : {group aT}) (f : {morphism G >-> rT}). +Variables (R : {group rT}) (isoGR : isom G R f). +Implicit Type chi : 'CF(G). + +Lemma cfIsom_char chi : chi \is a character -> cfIsom isoGR chi \is a character. +Proof. +by move=> Nchi; rewrite [cfIsom _]locked_withE cfMorph_char ?cfRes_char. +Qed. + +Lemma cfIsom_lin_char chi : + chi \is a linear_char -> cfIsom isoGR chi \is a linear_char. +Proof. by case/andP=> Nchi; rewrite qualifE cfIsom_char ?cfIsom1. Qed. + +Lemma cfIsom_irr chi : chi \in irr G -> cfIsom isoGR chi \in irr R. +Proof. +move=> irr_chi; rewrite [cfIsom _]locked_withE cfMorph_irr //. +by rewrite (isom_im (isom_sym isoGR)) cfRes_id. +Qed. + +Definition isom_Iirr i := cfIirr (cfIsom isoGR 'chi_i). + +Lemma isom_IirrE i : 'chi_(isom_Iirr i) = cfIsom isoGR 'chi_i. +Proof. by rewrite cfIirrE ?cfIsom_irr ?mem_irr. Qed. + +Lemma isom_Iirr_inj : injective isom_Iirr. +Proof. +by move=> i j eqij; apply/irr_inj/(cfIsom_inj isoGR); rewrite -!isom_IirrE eqij. +Qed. + +Lemma isom_Iirr_eq0 i : (isom_Iirr i == 0) = (i == 0). +Proof. by rewrite -!irr_eq1 isom_IirrE cfIsom_eq1. Qed. + +Lemma isom_Iirr0 : isom_Iirr 0 = 0. +Proof. by apply/eqP; rewrite isom_Iirr_eq0. Qed. + +End Isom. + +Implicit Arguments isom_Iirr_inj [aT rT G f R x1 x2]. + +Section IsomInv. + +Variables (aT rT : finGroupType) (G : {group aT}) (f : {morphism G >-> rT}). +Variables (R : {group rT}) (isoGR : isom G R f). + +Lemma isom_IirrK : cancel (isom_Iirr isoGR) (isom_Iirr (isom_sym isoGR)). +Proof. by move=> i; apply: irr_inj; rewrite !isom_IirrE cfIsomK. Qed. + +Lemma isom_IirrKV : cancel (isom_Iirr (isom_sym isoGR)) (isom_Iirr isoGR). +Proof. by move=> i; apply: irr_inj; rewrite !isom_IirrE cfIsomKV. Qed. + +End IsomInv. + +Section OrthogonalityRelations. + +Variables aT gT : finGroupType. + +(* This is Isaacs, Lemma (2.15) *) +Lemma repr_rsim_diag (G : {group gT}) f (rG : mx_representation algCF G f) x : + x \in G -> let chi := cfRepr rG in + exists e, + [/\ (*a*) exists2 B, B \in unitmx & rG x = invmx B *m diag_mx e *m B, + (*b*) (forall i, e 0 i ^+ #[x] = 1) /\ (forall i, `|e 0 i| = 1), + (*c*) chi x = \sum_i e 0 i /\ `|chi x| <= chi 1%g + & (*d*) chi x^-1%g = (chi x)^*]. +Proof. +move=> Gx; without loss cGG: G rG Gx / abelian G. + have sXG: <[x]> \subset G by rewrite cycle_subG. + move/(_ _ (subg_repr rG sXG) (cycle_id x) (cycle_abelian x)). + by rewrite /= !cfunE !groupV Gx (cycle_id x) !group1. +have [I U W simU W1 dxW]: mxsemisimple rG 1%:M. + rewrite -(reducible_Socle1 (DecSocleType rG) (mx_Maschke _ (algC'G G))). + exact: Socle_semisimple. +have linU i: \rank (U i) = 1%N. + by apply: mxsimple_abelian_linear cGG (simU i); exact: groupC. +have castI: f = #|I|. + by rewrite -(mxrank1 algCF f) -W1 (eqnP dxW) /= -sum1_card; exact/eq_bigr. +pose B := \matrix_j nz_row (U (enum_val (cast_ord castI j))). +have rowU i: (nz_row (U i) :=: U i)%MS. + apply/eqmxP; rewrite -(geq_leqif (mxrank_leqif_eq (nz_row_sub _))) linU. + by rewrite lt0n mxrank_eq0 (nz_row_mxsimple (simU i)). +have unitB: B \in unitmx. + rewrite -row_full_unit -sub1mx -W1; apply/sumsmx_subP=> i _. + pose j := cast_ord (esym castI) (enum_rank i). + by rewrite (submx_trans _ (row_sub j B)) // rowK cast_ordKV enum_rankK rowU. +pose e := \row_j row j (B *m rG x *m invmx B) 0 j. +have rGx: rG x = invmx B *m diag_mx e *m B. + rewrite -mulmxA; apply: canRL (mulKmx unitB) _. + apply/row_matrixP=> j; rewrite 2!row_mul; set u := row j B. + have /sub_rVP[a def_ux]: (u *m rG x <= u)%MS. + rewrite /u rowK rowU (eqmxMr _ (rowU _)). + exact: (mxmoduleP (mxsimple_module (simU _))). + rewrite def_ux [u]rowE scalemxAl; congr (_ *m _). + apply/rowP=> k; rewrite 5!mxE !row_mul def_ux [u]rowE scalemxAl mulmxK //. + by rewrite !mxE !eqxx !mulr_natr eq_sym. +have exp_e j: e 0 j ^+ #[x] = 1. + suffices: (diag_mx e j j) ^+ #[x] = (B *m rG (x ^+ #[x])%g *m invmx B) j j. + by rewrite expg_order repr_mx1 mulmx1 mulmxV // [e]lock !mxE eqxx. + elim: #[x] => [|n IHn]; first by rewrite repr_mx1 mulmx1 mulmxV // !mxE eqxx. + rewrite expgS repr_mxM ?groupX // {1}rGx -!mulmxA mulKVmx //. + by rewrite mul_diag_mx mulmxA [M in _ = M]mxE -IHn exprS {1}mxE eqxx. +have norm1_e j: `|e 0 j| = 1. + apply/eqP; rewrite -(@pexpr_eq1 _ _ #[x]) ?normr_ge0 //. + by rewrite -normrX exp_e normr1. +exists e; split=> //; first by exists B. + rewrite cfRepr1 !cfunE Gx rGx mxtrace_mulC mulKVmx // mxtrace_diag. + split=> //=; apply: (ler_trans (ler_norm_sum _ _ _)). + by rewrite (eq_bigr _ (in1W norm1_e)) sumr_const card_ord lerr. +rewrite !cfunE groupV !mulrb Gx rGx mxtrace_mulC mulKVmx //. +rewrite -trace_map_mx map_diag_mx; set d' := diag_mx _. +rewrite -[d'](mulKVmx unitB) mxtrace_mulC -[_ *m _](repr_mxK rG Gx) rGx. +rewrite -!mulmxA mulKVmx // (mulmxA d'). +suffices->: d' *m diag_mx e = 1%:M by rewrite mul1mx mulKmx. +rewrite mulmx_diag -diag_const_mx; congr diag_mx; apply/rowP=> j. +by rewrite [e]lock !mxE mulrC -normCK -lock norm1_e expr1n. +Qed. + +Variables (A : {group aT}) (G : {group gT}). + +(* This is Isaacs, Lemma (2.15) (d). *) +Lemma char_inv (chi : 'CF(G)) x : chi \is a character -> chi x^-1%g = (chi x)^*. +Proof. +case Gx: (x \in G); last by rewrite !cfun0 ?rmorph0 ?groupV ?Gx. +by case/char_reprP=> rG ->; have [e [_ _ _]] := repr_rsim_diag rG Gx. +Qed. + +Lemma irr_inv i x : 'chi[G]_i x^-1%g = ('chi_i x)^*. +Proof. exact/char_inv/irr_char. Qed. + +(* This is Isaacs, Theorem (2.13). *) +Theorem generalized_orthogonality_relation y (i j : Iirr G) : + #|G|%:R^-1 * (\sum_(x in G) 'chi_i (x * y)%g * 'chi_j x^-1%g) + = (i == j)%:R * ('chi_i y / 'chi_i 1%g). +Proof. +pose W := @socle_of_Iirr _ G; pose e k := Wedderburn_id (W k). +pose aG := regular_repr algCF G. +have [Gy | notGy] := boolP (y \in G); last first. + rewrite cfun0 // mul0r big1 ?mulr0 // => x Gx. + by rewrite cfun0 ?groupMl ?mul0r. +transitivity (('chi_i).[e j *m aG y]%CF / 'chi_j 1%g). + rewrite [e j]Wedderburn_id_expansion -scalemxAl xcfunZr -mulrA; congr (_ * _). + rewrite mulmx_suml raddf_sum big_distrl; apply: eq_bigr => x Gx /=. + rewrite -scalemxAl xcfunZr -repr_mxM // xcfunG ?groupM // mulrAC mulrC. + by congr (_ * _); rewrite mulrC mulKf ?irr1_neq0. +rewrite mulr_natl mulrb; have [<-{j} | neq_ij] := altP eqP. + by congr (_ / _); rewrite xcfun_mul_id ?envelop_mx_id ?xcfunG. +rewrite (xcfun_annihilate neq_ij) ?mul0r //. +case/andP: (Wedderburn_ideal (W j)) => _; apply: submx_trans. +by rewrite mem_mulsmx ?Wedderburn_id_mem ?envelop_mx_id. +Qed. + +(* This is Isaacs, Corollary (2.14). *) +Corollary first_orthogonality_relation (i j : Iirr G) : + #|G|%:R^-1 * (\sum_(x in G) 'chi_i x * 'chi_j x^-1%g) = (i == j)%:R. +Proof. +have:= generalized_orthogonality_relation 1 i j. +rewrite mulrA mulfK ?irr1_neq0 // => <-; congr (_ * _). +by apply: eq_bigr => x; rewrite mulg1. +Qed. + +(* The character table. *) + +Definition irr_class i := enum_val (cast_ord (NirrE G) i). +Definition class_Iirr xG := + cast_ord (esym (NirrE G)) (enum_rank_in (classes1 G) xG). + +Local Notation c := irr_class. +Local Notation g i := (repr (c i)). +Local Notation iC := class_Iirr. + +Definition character_table := \matrix_(i, j) 'chi[G]_i (g j). +Local Notation X := character_table. + +Lemma irr_classP i : c i \in classes G. +Proof. exact: enum_valP. Qed. + +Lemma repr_irr_classK i : g i ^: G = c i. +Proof. by case/repr_classesP: (irr_classP i). Qed. + +Lemma irr_classK : cancel c iC. +Proof. by move=> i; rewrite /iC enum_valK_in cast_ordK. Qed. + +Lemma class_IirrK : {in classes G, cancel iC c}. +Proof. by move=> xG GxG; rewrite /c cast_ordKV enum_rankK_in. Qed. + +Lemma reindex_irr_class R idx (op : @Monoid.com_law R idx) F : + \big[op/idx]_(xG in classes G) F xG = \big[op/idx]_i F (c i). +Proof. +rewrite (reindex c); first by apply: eq_bigl => i; exact: enum_valP. +by exists iC; [apply: in1W; exact: irr_classK | exact: class_IirrK]. +Qed. + +(* The explicit value of the inverse is needed for the proof of the second *) +(* orthogonality relation. *) +Let X' := \matrix_(i, j) (#|'C_G[g i]|%:R^-1 * ('chi[G]_j (g i))^*). +Let XX'_1: X *m X' = 1%:M. +Proof. +apply/matrixP=> i j; rewrite !mxE -first_orthogonality_relation mulr_sumr. +rewrite sum_by_classes => [|u v Gu Gv]; last by rewrite -conjVg !cfunJ. +rewrite reindex_irr_class /=; apply/esym/eq_bigr=> k _. +rewrite !mxE irr_inv // -/(g k) -divg_index -indexgI /=. +rewrite (char0_natf_div Cchar) ?dvdn_indexg // index_cent1 invfM invrK. +by rewrite repr_irr_classK mulrCA mulrA mulrCA. +Qed. + +Lemma character_table_unit : X \in unitmx. +Proof. by case/mulmx1_unit: XX'_1. Qed. +Let uX := character_table_unit. + +(* This is Isaacs, Theorem (2.18). *) +Theorem second_orthogonality_relation x y : + y \in G -> + \sum_i 'chi[G]_i x * ('chi_i y)^* = #|'C_G[x]|%:R *+ (x \in y ^: G). +Proof. +move=> Gy; pose i_x := iC (x ^: G); pose i_y := iC (y ^: G). +have [Gx | notGx] := boolP (x \in G); last first. + rewrite (contraNF (subsetP _ x) notGx) ?class_subG ?big1 // => i _. + by rewrite cfun0 ?mul0r. +transitivity ((#|'C_G[repr (y ^: G)]|%:R *: (X' *m X)) i_y i_x). + rewrite scalemxAl !mxE; apply: eq_bigr => k _; rewrite !mxE mulrC -!mulrA. + by rewrite !class_IirrK ?mem_classes // !cfun_repr mulVKf ?neq0CG. +rewrite mulmx1C // !mxE -!divg_index !(index_cent1, =^~ indexgI). +rewrite (class_transr (mem_repr y _)) ?class_refl // mulr_natr. +rewrite (can_in_eq class_IirrK) ?mem_classes //. +have [-> | not_yGx] := altP eqP; first by rewrite class_refl. +by rewrite [x \in _](contraNF _ not_yGx) // => /class_transr->. +Qed. + +Lemma eq_irr_mem_classP x y : + y \in G -> reflect (forall i, 'chi[G]_i x = 'chi_i y) (x \in y ^: G). +Proof. +move=> Gy; apply: (iffP idP) => [/imsetP[z Gz ->] i | xGy]; first exact: cfunJ. +have Gx: x \in G. + congr is_true: Gy; apply/eqP; rewrite -(can_eq oddb) -eqC_nat -!cfun1E. + by rewrite -irr0 xGy. +congr is_true: (class_refl G x); apply/eqP; rewrite -(can_eq oddb). +rewrite -(eqn_pmul2l (cardG_gt0 'C_G[x])) -eqC_nat !mulrnA; apply/eqP. +by rewrite -!second_orthogonality_relation //; apply/eq_bigr=> i _; rewrite xGy. +Qed. + +(* This is Isaacs, Theorem (6.32) (due to Brauer). *) +Lemma card_afix_irr_classes (ito : action A (Iirr G)) (cto : action A _) a : + a \in A -> [acts A, on classes G | cto] -> + (forall i x y, x \in G -> y \in cto (x ^: G) a -> + 'chi_i x = 'chi_(ito i a) y) -> + #|'Fix_ito[a]| = #|'Fix_(classes G | cto)[a]|. +Proof. +move=> Aa actsAG stabAchi; apply/eqP; rewrite -eqC_nat; apply/eqP. +have [[cP cK] iCK] := (irr_classP, irr_classK, class_IirrK). +pose icto b i := iC (cto (c i) b). +have Gca i: cto (c i) a \in classes G by rewrite (acts_act actsAG). +have inj_qa: injective (icto a). + by apply: can_inj (icto a^-1%g) _ => i; rewrite /icto iCK ?actKin ?cK. +pose Pa : 'M[algC]_(Nirr G) := perm_mx (actperm ito a). +pose qa := perm inj_qa; pose Qa : 'M[algC]_(Nirr G) := perm_mx qa^-1^-1%g. +transitivity (\tr Pa). + rewrite -sumr_const big_mkcond; apply: eq_bigr => i _. + by rewrite !mxE permE inE sub1set inE; case: ifP. +symmetry; transitivity (\tr Qa). + rewrite cardsE -sumr_const -big_filter_cond big_mkcond big_filter /=. + rewrite reindex_irr_class; apply: eq_bigr => i _; rewrite !mxE invgK permE. + by rewrite inE sub1set inE -(can_eq cK) iCK //; case: ifP. +rewrite -[Pa](mulmxK uX) -[Qa](mulKmx uX) mxtrace_mulC; congr (\tr(_ *m _)). +rewrite -row_permE -col_permE; apply/matrixP=> i j; rewrite !mxE. +rewrite -{2}[j](permKV qa); move: {j}(_ j) => j; rewrite !permE iCK //. +apply: stabAchi; first by case/repr_classesP: (cP j). +by rewrite repr_irr_classK (mem_repr_classes (Gca _)). +Qed. + +End OrthogonalityRelations. + +Arguments Scope character_table [_ group_scope]. + +Section InnerProduct. + +Variable (gT : finGroupType) (G : {group gT}). + +Lemma cfdot_irr i j : '['chi_i, 'chi_j]_G = (i == j)%:R. +Proof. +rewrite -first_orthogonality_relation; congr (_ * _). +by apply: eq_bigr => x Gx; rewrite irr_inv. +Qed. + +Lemma cfnorm_irr i : '['chi[G]_i] = 1. +Proof. by rewrite cfdot_irr eqxx. Qed. + +Lemma irr_orthonormal : orthonormal (irr G). +Proof. +apply/orthonormalP; split; first exact: free_uniq (irr_free G). +move=> _ _ /irrP[i ->] /irrP[j ->]. +by rewrite cfdot_irr (inj_eq (@irr_inj _ G)). +Qed. + +Lemma coord_cfdot phi i : coord (irr G) i phi = '[phi, 'chi_i]. +Proof. +rewrite {2}(coord_basis (irr_basis G) (memvf phi)). +rewrite cfdot_suml (bigD1 i) // cfdotZl /= -tnth_nth cfdot_irr eqxx mulr1. +rewrite big1 ?addr0 // => j neq_ji; rewrite cfdotZl /= -tnth_nth cfdot_irr. +by rewrite (negbTE neq_ji) mulr0. +Qed. + +Lemma cfun_sum_cfdot phi : phi = \sum_i '[phi, 'chi_i]_G *: 'chi_i. +Proof. +rewrite {1}(coord_basis (irr_basis G) (memvf phi)). +by apply: eq_bigr => i _; rewrite coord_cfdot -tnth_nth. +Qed. + +Lemma cfdot_sum_irr phi psi : + '[phi, psi]_G = \sum_i '[phi, 'chi_i] * '[psi, 'chi_i]^*. +Proof. +rewrite {1}[phi]cfun_sum_cfdot cfdot_suml; apply: eq_bigr => i _. +by rewrite cfdotZl -cfdotC. +Qed. + +Lemma Cnat_cfdot_char_irr i phi : + phi \is a character -> '[phi, 'chi_i]_G \in Cnat. +Proof. by move/forallP/(_ i); rewrite coord_cfdot. Qed. + +Lemma cfdot_char_r phi chi : + chi \is a character -> '[phi, chi]_G = \sum_i '[phi, 'chi_i] * '[chi, 'chi_i]. +Proof. +move=> Nchi; rewrite cfdot_sum_irr; apply: eq_bigr => i _; congr (_ * _). +by rewrite conj_Cnat ?Cnat_cfdot_char_irr. +Qed. + +Lemma Cnat_cfdot_char chi xi : + chi \is a character -> xi \is a character -> '[chi, xi]_G \in Cnat. +Proof. +move=> Nchi Nxi; rewrite cfdot_char_r ?rpred_sum // => i _. +by rewrite rpredM ?Cnat_cfdot_char_irr. +Qed. + +Lemma cfdotC_char chi xi : + chi \is a character-> xi \is a character -> '[chi, xi]_G = '[xi, chi]. +Proof. by move=> Nchi Nxi; rewrite cfdotC conj_Cnat ?Cnat_cfdot_char. Qed. + +Lemma irrEchar chi : (chi \in irr G) = (chi \is a character) && ('[chi] == 1). +Proof. +apply/irrP/andP=> [[i ->] | [Nchi]]; first by rewrite irr_char cfnorm_irr. +rewrite cfdot_sum_irr => /eqP/Cnat_sum_eq1[i _| i [_ ci1 cj0]]. + by rewrite rpredM // ?conj_Cnat ?Cnat_cfdot_char_irr. +exists i; rewrite [chi]cfun_sum_cfdot (bigD1 i) //=. +rewrite -(@normr_idP _ _ (@Cnat_ge0 _ (Cnat_cfdot_char_irr i Nchi))). +rewrite normC_def {}ci1 sqrtC1 scale1r big1 ?addr0 // => j neq_ji. +by rewrite (('[_] =P 0) _) ?scale0r // -normr_eq0 normC_def cj0 ?sqrtC0. +Qed. + +Lemma irrWchar chi : chi \in irr G -> chi \is a character. +Proof. by rewrite irrEchar => /andP[]. Qed. + +Lemma irrWnorm chi : chi \in irr G -> '[chi] = 1. +Proof. by rewrite irrEchar => /andP[_ /eqP]. Qed. + +Lemma mul_lin_irr xi chi : + xi \is a linear_char -> chi \in irr G -> xi * chi \in irr G. +Proof. +move=> Lxi; rewrite !irrEchar => /andP[Nphi /eqP <-]. +rewrite rpredM // ?lin_charW //=; apply/eqP; congr (_ * _). +apply: eq_bigr => x Gx; rewrite !cfunE rmorphM mulrACA -(lin_charV_conj Lxi) //. +by rewrite -lin_charM ?groupV // mulgV lin_char1 ?mul1r. +Qed. + +Lemma eq_scaled_irr a b i j : + (a *: 'chi[G]_i == b *: 'chi_j) = (a == b) && ((a == 0) || (i == j)). +Proof. +apply/eqP/andP=> [|[/eqP-> /pred2P[]-> //]]; last by rewrite !scale0r. +move/(congr1 (cfdotr 'chi__)) => /= eq_ai_bj. +move: {eq_ai_bj}(eq_ai_bj i) (esym (eq_ai_bj j)); rewrite !cfdotZl !cfdot_irr. +by rewrite !mulr_natr !mulrb !eqxx eq_sym orbC; case: ifP => _ -> //= ->. +Qed. + +Lemma eq_signed_irr (s t : bool) i j : + ((-1) ^+ s *: 'chi[G]_i == (-1) ^+ t *: 'chi_j) = (s == t) && (i == j). +Proof. by rewrite eq_scaled_irr signr_eq0 (inj_eq (@signr_inj _)). Qed. + +Lemma eq_scale_irr a (i j : Iirr G) : + (a *: 'chi_i == a *: 'chi_j) = (a == 0) || (i == j). +Proof. by rewrite eq_scaled_irr eqxx. Qed. + +Lemma eq_addZ_irr a b (i j r t : Iirr G) : + (a *: 'chi_i + b *: 'chi_j == a *: 'chi_r + b *: 'chi_t) + = [|| [&& (a == 0) || (i == r) & (b == 0) || (j == t)], + [&& i == t, j == r & a == b] | [&& i == j, r == t & a == - b]]. +Proof. +rewrite -!eq_scale_irr; apply/eqP/idP; last first. + case/orP; first by case/andP=> /eqP-> /eqP->. + case/orP=> /and3P[/eqP-> /eqP-> /eqP->]; first by rewrite addrC. + by rewrite !scaleNr !addNr. +have [-> /addrI/eqP-> // | /= ] := altP eqP. +rewrite eq_scale_irr => /norP[/negP nz_a /negPf neq_ir]. +move/(congr1 (cfdotr 'chi__))/esym/eqP => /= eq_cfdot. +move: {eq_cfdot}(eq_cfdot i) (eq_cfdot r); rewrite eq_sym !cfdotDl !cfdotZl. +rewrite !cfdot_irr !mulr_natr !mulrb !eqxx -!(eq_sym i) neq_ir !add0r. +have [<- _ | _] := i =P t; first by rewrite neq_ir addr0; case: ifP => // _ ->. +rewrite 2!fun_if if_arg addr0 addr_eq0; case: eqP => //= <- ->. +by rewrite neq_ir 2!fun_if if_arg eq_sym addr0; case: ifP. +Qed. + +Lemma eq_subZnat_irr (a b : nat) (i j r t : Iirr G) : + (a%:R *: 'chi_i - b%:R *: 'chi_j == a%:R *: 'chi_r - b%:R *: 'chi_t) + = [|| a == 0%N | i == r] && [|| b == 0%N | j == t] + || [&& i == j, r == t & a == b]. +Proof. +rewrite -!scaleNr eq_addZ_irr oppr_eq0 opprK -addr_eq0 -natrD eqr_nat. +by rewrite !pnatr_eq0 addn_eq0; case: a b => [|a] [|b]; rewrite ?andbF. +Qed. + +End InnerProduct. + +Section Sdprod. + +Variables (gT : finGroupType) (K H G : {group gT}). +Hypothesis defG : K ><| H = G. + +Lemma cfSdprod_char chi : + chi \is a character -> cfSdprod defG chi \is a character. +Proof. by move=> Nchi; rewrite unlock cfMorph_char ?cfIsom_char. Qed. + +Lemma cfSdprod_lin_char chi : + chi \is a linear_char -> cfSdprod defG chi \is a linear_char. +Proof. by move=> Nphi; rewrite unlock cfMorph_lin_char ?cfIsom_lin_char. Qed. + +Lemma cfSdprod_irr chi : chi \in irr H -> cfSdprod defG chi \in irr G. +Proof. +have [/andP[_ nKG] _ _ _ _] := sdprod_context defG. +by move=> Nphi; rewrite unlock cfMorph_irr ?cfIsom_irr. +Qed. + +Definition sdprod_Iirr j := cfIirr (cfSdprod defG 'chi_j). + +Lemma sdprod_IirrE j : 'chi_(sdprod_Iirr j) = cfSdprod defG 'chi_j. +Proof. by rewrite cfIirrE ?cfSdprod_irr ?mem_irr. Qed. + +Lemma sdprod_IirrK : cancel sdprod_Iirr (Res_Iirr H). +Proof. by move=> j; rewrite /Res_Iirr sdprod_IirrE cfSdprodK irrK. Qed. + +Lemma sdprod_Iirr_inj : injective sdprod_Iirr. +Proof. exact: can_inj sdprod_IirrK. Qed. + +Lemma sdprod_Iirr_eq0 i : (sdprod_Iirr i == 0) = (i == 0). +Proof. by rewrite -!irr_eq1 sdprod_IirrE cfSdprod_eq1. Qed. + +Lemma sdprod_Iirr0 : sdprod_Iirr 0 = 0. +Proof. by apply/eqP; rewrite sdprod_Iirr_eq0. Qed. + +Lemma Res_sdprod_irr phi : + K \subset cfker phi -> phi \in irr G -> 'Res phi \in irr H. +Proof. +move=> kerK /irrP[i Dphi]; rewrite irrEchar -(cfSdprod_iso defG). +by rewrite cfRes_sdprodK // Dphi cfnorm_irr cfRes_char ?irr_char /=. +Qed. + +Lemma sdprod_Res_IirrE i : + K \subset cfker 'chi[G]_i -> 'chi_(Res_Iirr H i) = 'Res 'chi_i. +Proof. by move=> kerK; rewrite cfIirrE ?Res_sdprod_irr ?mem_irr. Qed. + +Lemma sdprod_Res_IirrK i : + K \subset cfker 'chi_i -> sdprod_Iirr (Res_Iirr H i) = i. +Proof. +by move=> kerK; rewrite /sdprod_Iirr sdprod_Res_IirrE ?cfRes_sdprodK ?irrK. +Qed. + +End Sdprod. + +Implicit Arguments sdprod_Iirr_inj [gT K H G x1 x2]. + +Section DProd. + +Variables (gT : finGroupType) (G K H : {group gT}). +Hypothesis KxH : K \x H = G. + +Lemma cfDprodKl_abelian j : abelian H -> cancel ((cfDprod KxH)^~ 'chi_j) 'Res. +Proof. by move=> cHH; apply: cfDprodKl; apply/lin_char1/char_abelianP. Qed. + +Lemma cfDprodKr_abelian i : abelian K -> cancel (cfDprod KxH 'chi_i) 'Res. +Proof. by move=> cKK; apply: cfDprodKr; apply/lin_char1/char_abelianP. Qed. + +Lemma cfDprodl_char phi : + phi \is a character -> cfDprodl KxH phi \is a character. +Proof. exact: cfSdprod_char. Qed. + +Lemma cfDprodr_char psi : + psi \is a character -> cfDprodr KxH psi \is a character. +Proof. exact: cfSdprod_char. Qed. + +Lemma cfDprod_char phi psi : + phi \is a character -> psi \is a character -> + cfDprod KxH phi psi \is a character. +Proof. by move=> /cfDprodl_char Nphi /cfDprodr_char; apply: rpredM. Qed. + +Lemma cfDprod_eq1 phi psi : + phi \is a character -> psi \is a character -> + (cfDprod KxH phi psi == 1) = (phi == 1) && (psi == 1). +Proof. +move=> /Cnat_char1 Nphi /Cnat_char1 Npsi. +apply/eqP/andP=> [phi_psi_1 | [/eqP-> /eqP->]]; last by rewrite cfDprod_cfun1. +have /andP[/eqP phi1 /eqP psi1]: (phi 1%g == 1) && (psi 1%g == 1). + by rewrite -Cnat_mul_eq1 // -(cfDprod1 KxH) phi_psi_1 cfun11. +rewrite -[phi](cfDprodKl KxH psi1) -{2}[psi](cfDprodKr KxH phi1) phi_psi_1. +by rewrite !rmorph1. +Qed. + +Lemma cfDprodl_lin_char phi : + phi \is a linear_char -> cfDprodl KxH phi \is a linear_char. +Proof. exact: cfSdprod_lin_char. Qed. + +Lemma cfDprodr_lin_char psi : + psi \is a linear_char -> cfDprodr KxH psi \is a linear_char. +Proof. exact: cfSdprod_lin_char. Qed. + +Lemma cfDprod_lin_char phi psi : + phi \is a linear_char -> psi \is a linear_char -> + cfDprod KxH phi psi \is a linear_char. +Proof. by move=> /cfDprodl_lin_char Lphi /cfDprodr_lin_char; apply: rpredM. Qed. + +Lemma cfDprodl_irr chi : chi \in irr K -> cfDprodl KxH chi \in irr G. +Proof. exact: cfSdprod_irr. Qed. + +Lemma cfDprodr_irr chi : chi \in irr H -> cfDprodr KxH chi \in irr G. +Proof. exact: cfSdprod_irr. Qed. + +Definition dprodl_Iirr i := cfIirr (cfDprodl KxH 'chi_i). + +Lemma dprodl_IirrE i : 'chi_(dprodl_Iirr i) = cfDprodl KxH 'chi_i. +Proof. exact: sdprod_IirrE. Qed. +Lemma dprodl_IirrK : cancel dprodl_Iirr (Res_Iirr K). +Proof. exact: sdprod_IirrK. Qed. +Lemma dprodl_Iirr_eq0 i : (dprodl_Iirr i == 0) = (i == 0). +Proof. exact: sdprod_Iirr_eq0. Qed. +Lemma dprodl_Iirr0 : dprodl_Iirr 0 = 0. +Proof. exact: sdprod_Iirr0. Qed. + +Definition dprodr_Iirr j := cfIirr (cfDprodr KxH 'chi_j). + +Lemma dprodr_IirrE j : 'chi_(dprodr_Iirr j) = cfDprodr KxH 'chi_j. +Proof. exact: sdprod_IirrE. Qed. +Lemma dprodr_IirrK : cancel dprodr_Iirr (Res_Iirr H). +Proof. exact: sdprod_IirrK. Qed. +Lemma dprodr_Iirr_eq0 j : (dprodr_Iirr j == 0) = (j == 0). +Proof. exact: sdprod_Iirr_eq0. Qed. +Lemma dprodr_Iirr0 : dprodr_Iirr 0 = 0. +Proof. exact: sdprod_Iirr0. Qed. + +Lemma cfDprod_irr i j : cfDprod KxH 'chi_i 'chi_j \in irr G. +Proof. +rewrite irrEchar cfDprod_char ?irr_char //=. +by rewrite cfdot_dprod !cfdot_irr !eqxx mul1r. +Qed. + +Definition dprod_Iirr ij := cfIirr (cfDprod KxH 'chi_ij.1 'chi_ij.2). + +Lemma dprod_IirrE i j : 'chi_(dprod_Iirr (i, j)) = cfDprod KxH 'chi_i 'chi_j. +Proof. by rewrite cfIirrE ?cfDprod_irr. Qed. + +Lemma dprod_IirrEl i : 'chi_(dprod_Iirr (i, 0)) = cfDprodl KxH 'chi_i. +Proof. by rewrite dprod_IirrE /cfDprod irr0 rmorph1 mulr1. Qed. + +Lemma dprod_IirrEr j : 'chi_(dprod_Iirr (0, j)) = cfDprodr KxH 'chi_j. +Proof. by rewrite dprod_IirrE /cfDprod irr0 rmorph1 mul1r. Qed. + +Lemma dprod_Iirr_inj : injective dprod_Iirr. +Proof. +move=> [i1 j1] [i2 j2] /eqP; rewrite -[_ == _]oddb -(natCK (_ == _)). +rewrite -cfdot_irr !dprod_IirrE cfdot_dprod !cfdot_irr -natrM mulnb. +by rewrite natCK oddb -xpair_eqE => /eqP. +Qed. + +Lemma dprod_Iirr0 : dprod_Iirr (0, 0) = 0. +Proof. by apply/irr_inj; rewrite dprod_IirrE !irr0 cfDprod_cfun1. Qed. + +Lemma dprod_Iirr0l j : dprod_Iirr (0, j) = dprodr_Iirr j. +Proof. +by apply/irr_inj; rewrite dprod_IirrE irr0 dprodr_IirrE cfDprod_cfun1l. +Qed. + +Lemma dprod_Iirr0r i : dprod_Iirr (i, 0) = dprodl_Iirr i. +Proof. +by apply/irr_inj; rewrite dprod_IirrE irr0 dprodl_IirrE cfDprod_cfun1r. +Qed. + +Lemma dprod_Iirr_eq0 i j : (dprod_Iirr (i, j) == 0) = (i == 0) && (j == 0). +Proof. by rewrite -xpair_eqE -(inj_eq dprod_Iirr_inj) dprod_Iirr0. Qed. + +Lemma cfdot_dprod_irr i1 i2 j1 j2 : + '['chi_(dprod_Iirr (i1, j1)), 'chi_(dprod_Iirr (i2, j2))] + = ((i1 == i2) && (j1 == j2))%:R. +Proof. by rewrite cfdot_irr (inj_eq dprod_Iirr_inj). Qed. + +Lemma dprod_Iirr_onto k : k \in codom dprod_Iirr. +Proof. +set D := codom _; have Df: dprod_Iirr _ \in D := codom_f dprod_Iirr _. +have: 'chi_k 1%g ^+ 2 != 0 by rewrite mulf_neq0 ?irr1_neq0. +apply: contraR => notDk; move/eqP: (irr_sum_square G). +rewrite (bigID (mem D)) (reindex _ (bij_on_codom dprod_Iirr_inj (0, 0))) /=. +have ->: #|G|%:R = \sum_i \sum_j 'chi_(dprod_Iirr (i, j)) 1%g ^+ 2. + rewrite -(dprod_card KxH) natrM. + do 2![rewrite -irr_sum_square (mulr_suml, mulr_sumr); apply: eq_bigr => ? _]. + by rewrite dprod_IirrE -exprMn -{3}(mulg1 1%g) cfDprodE. +rewrite (eq_bigl _ _ Df) pair_bigA addrC -subr_eq0 addrK. +by move/eqP/psumr_eq0P=> -> //= i _; rewrite irr1_degree -natrX ler0n. +Qed. + +Definition inv_dprod_Iirr i := iinv (dprod_Iirr_onto i). + +Lemma dprod_IirrK : cancel dprod_Iirr inv_dprod_Iirr. +Proof. by move=> p; exact: (iinv_f dprod_Iirr_inj). Qed. + +Lemma inv_dprod_IirrK : cancel inv_dprod_Iirr dprod_Iirr. +Proof. by move=> i; exact: f_iinv. Qed. + +Lemma inv_dprod_Iirr0 : inv_dprod_Iirr 0 = (0, 0). +Proof. by apply/(canLR dprod_IirrK); rewrite dprod_Iirr0. Qed. + +End DProd. + +Implicit Arguments dprod_Iirr_inj [gT G K H x1 x2]. + +Lemma dprod_IirrC (gT : finGroupType) (G K H : {group gT}) + (KxH : K \x H = G) (HxK : H \x K = G) i j : + dprod_Iirr KxH (i, j) = dprod_Iirr HxK (j, i). +Proof. by apply: irr_inj; rewrite !dprod_IirrE; apply: cfDprodC. Qed. + +Section BigDprod. + +Variables (gT : finGroupType) (I : finType) (P : pred I). +Variables (A : I -> {group gT}) (G : {group gT}). +Hypothesis defG : \big[dprod/1%g]_(i | P i) A i = G. + +Let sAG i : P i -> A i \subset G. +Proof. by move=> Pi; rewrite -(bigdprodWY defG) (bigD1 i) ?joing_subl. Qed. + +Lemma cfBigdprodi_char i (phi : 'CF(A i)) : + phi \is a character -> cfBigdprodi defG phi \is a character. +Proof. by move=> Nphi; rewrite cfDprodl_char ?cfRes_char. Qed. + +Lemma cfBigdprod_char phi : + (forall i, P i -> phi i \is a character) -> + cfBigdprod defG phi \is a character. +Proof. +by move=> Nphi; apply: rpred_prod => i /Nphi; apply: cfBigdprodi_char. +Qed. + +Lemma cfBigdprodi_lin_char i (phi : 'CF(A i)) : + phi \is a linear_char -> cfBigdprodi defG phi \is a linear_char. +Proof. by move=> Lphi; rewrite cfDprodl_lin_char ?cfRes_lin_char. Qed. + +Lemma cfBigdprod_lin_char phi : + (forall i, P i -> phi i \is a linear_char) -> + cfBigdprod defG phi \is a linear_char. +Proof. +by move=> Lphi; apply/rpred_prod=> i /Lphi; apply: cfBigdprodi_lin_char. +Qed. + +Lemma cfBigdprodi_irr i chi : + P i -> chi \in irr (A i) -> cfBigdprodi defG chi \in irr G. +Proof. by move=> Pi Nchi; rewrite cfDprodl_irr // Pi cfRes_id. Qed. + +Lemma cfBigdprod_irr chi : + (forall i, P i -> chi i \in irr (A i)) -> cfBigdprod defG chi \in irr G. +Proof. +move=> Nchi; rewrite irrEchar cfBigdprod_char => [|i /Nchi/irrWchar] //=. +by rewrite cfdot_bigdprod big1 // => i /Nchi/irrWnorm. +Qed. + +Lemma cfBigdprod_eq1 phi : + (forall i, P i -> phi i \is a character) -> + (cfBigdprod defG phi == 1) = [forall (i | P i), phi i == 1]. +Proof. +move=> Nphi; set Phi := cfBigdprod defG phi. +apply/eqP/eqfun_inP=> [Phi1 i Pi | phi1]; last first. + by apply: big1 => i /phi1->; rewrite rmorph1. +have Phi1_1: Phi 1%g = 1 by rewrite Phi1 cfun1E group1. +have nz_Phi1: Phi 1%g != 0 by rewrite Phi1_1 oner_eq0. +have [_ <-] := cfBigdprodK nz_Phi1 Pi. +rewrite Phi1_1 divr1 -/Phi Phi1 rmorph1. +rewrite prod_cfunE // in Phi1_1; have := Cnat_prod_eq1 _ Phi1_1 Pi. +rewrite -(cfRes1 (A i)) cfBigdprodiK // => ->; first by rewrite scale1r. +by move=> {i Pi} j /Nphi Nphi_j; rewrite Cnat_char1 ?cfBigdprodi_char. +Qed. + +Lemma cfBigdprod_Res_lin chi : + chi \is a linear_char -> cfBigdprod defG (fun i => 'Res[A i] chi) = chi. +Proof. +move=> Lchi; apply/cfun_inP=> _ /(mem_bigdprod defG)[x [Ax -> _]]. +rewrite (lin_char_prod Lchi) ?cfBigdprodE // => [|i Pi]; last first. + by rewrite (subsetP (sAG Pi)) ?Ax. +by apply/eq_bigr=> i Pi; rewrite cfResE ?sAG ?Ax. +Qed. + +Lemma cfBigdprodKlin phi : + (forall i, P i -> phi i \is a linear_char) -> + forall i, P i -> 'Res (cfBigdprod defG phi) = phi i. +Proof. +move=> Lphi i Pi; have Lpsi := cfBigdprod_lin_char Lphi. +have [_ <-] := cfBigdprodK (lin_char_neq0 Lpsi (group1 G)) Pi. +by rewrite !lin_char1 ?Lphi // divr1 scale1r. +Qed. + +Lemma cfBigdprodKabelian Iphi (phi := fun i => 'chi_(Iphi i)) : + abelian G -> forall i, P i -> 'Res (cfBigdprod defG phi) = 'chi_(Iphi i). +Proof. +move=> /(abelianS _) cGG. +by apply: cfBigdprodKlin => i /sAG/cGG/char_abelianP->. +Qed. + +End BigDprod. + +Section Aut. + +Variables (gT : finGroupType) (G : {group gT}). +Implicit Type u : {rmorphism algC -> algC}. + +Lemma conjC_charAut u (chi : 'CF(G)) x : + chi \is a character -> (u (chi x))^* = u (chi x)^*. +Proof. +have [Gx | /cfun0->] := boolP (x \in G); last by rewrite !rmorph0. +case/char_reprP=> rG ->; have [e [_ [en1 _] [-> _] _]] := repr_rsim_diag rG Gx. +by rewrite !rmorph_sum; apply: eq_bigr => i _; exact: aut_unity_rootC (en1 i). +Qed. + +Lemma conjC_irrAut u i x : (u ('chi[G]_i x))^* = u ('chi_i x)^*. +Proof. exact: conjC_charAut (irr_char i). Qed. + +Lemma cfdot_aut_char u (phi chi : 'CF(G)) : + chi \is a character -> '[cfAut u phi, cfAut u chi] = u '[phi, chi]. +Proof. by move/conjC_charAut=> Nchi; apply: cfdot_cfAut => _ /mapP[x _ ->]. Qed. + +Lemma cfdot_aut_irr u phi i : + '[cfAut u phi, cfAut u 'chi[G]_i] = u '[phi, 'chi_i]. +Proof. exact: cfdot_aut_char (irr_char i). Qed. + +Lemma cfAut_irr u chi : chi \in irr G -> cfAut u chi \in irr G. +Proof. +case/irrP=> i ->; rewrite irrEchar cfAut_char ?irr_char //=. +by rewrite cfdot_aut_irr // cfdot_irr eqxx rmorph1. +Qed. + +Lemma cfConjC_irr i : (('chi_i)^*)%CF \in irr G. +Proof. by rewrite cfAut_irr ?mem_irr. Qed. + +Lemma irr_aut_closed u : cfAut_closed u (irr G). +Proof. exact: cfAut_irr. Qed. + +Definition aut_Iirr u i := cfIirr (cfAut u 'chi[G]_i). + +Lemma aut_IirrE u i : 'chi_(aut_Iirr u i) = cfAut u 'chi_i. +Proof. by rewrite cfIirrE ?cfAut_irr ?mem_irr. Qed. + +Definition conjC_Iirr := aut_Iirr conjC. + +Lemma conjC_IirrE i : 'chi[G]_(conjC_Iirr i) = ('chi_i)^*%CF. +Proof. exact: aut_IirrE. Qed. + +Lemma conjC_IirrK : involutive conjC_Iirr. +Proof. by move=> i; apply: irr_inj; rewrite !conjC_IirrE cfConjCK. Qed. + +Lemma aut_Iirr0 u : aut_Iirr u 0 = 0 :> Iirr G. +Proof. by apply/irr_inj; rewrite aut_IirrE irr0 cfAut_cfun1. Qed. + +Lemma conjC_Iirr0 : conjC_Iirr 0 = 0 :> Iirr G. +Proof. exact: aut_Iirr0. Qed. + +Lemma aut_Iirr_eq0 u i : (aut_Iirr u i == 0) = (i == 0). +Proof. by rewrite -!irr_eq1 aut_IirrE cfAut_eq1. Qed. + +Lemma conjC_Iirr_eq0 i : (conjC_Iirr i == 0 :> Iirr G) = (i == 0). +Proof. exact: aut_Iirr_eq0. Qed. + +Lemma aut_Iirr_inj u : injective (aut_Iirr u). +Proof. +by move=> i j eq_ij; apply/irr_inj/(cfAut_inj u); rewrite -!aut_IirrE eq_ij. +Qed. + +Lemma char_aut u (chi : 'CF(G)) : + (cfAut u chi \is a character) = (chi \is a character). +Proof. +apply/idP/idP=> [Nuchi|]; last exact: cfAut_char. +rewrite [chi]cfun_sum_cfdot rpred_sum // => i _. +rewrite rpredZ_Cnat ?irr_char // -(Cnat_aut u) -cfdot_aut_irr. +by rewrite -aut_IirrE Cnat_cfdot_char_irr. +Qed. + +Lemma irr_aut u chi : (cfAut u chi \in irr G) = (chi \in irr G). +Proof. +rewrite !irrEchar char_aut; apply/andb_id2l=> /cfdot_aut_char->. +by rewrite fmorph_eq1. +Qed. + +End Aut. + +Section IrrConstt. + +Variable (gT : finGroupType) (G H : {group gT}). + +Lemma char1_ge_norm (chi : 'CF(G)) x : + chi \is a character -> `|chi x| <= chi 1%g. +Proof. +case/char_reprP=> rG ->; case Gx: (x \in G); last first. + by rewrite cfunE cfRepr1 Gx normr0 ler0n. +by have [e [_ _ []]] := repr_rsim_diag rG Gx. +Qed. + +Lemma max_cfRepr_norm_scalar n (rG : mx_representation algCF G n) x : + x \in G -> `|cfRepr rG x| = cfRepr rG 1%g -> + exists2 c, `|c| = 1 & rG x = c%:M. +Proof. +move=> Gx; have [e [[B uB def_x] [_ e1] [-> _] _]] := repr_rsim_diag rG Gx. +rewrite cfRepr1 -[n in n%:R]card_ord -sumr_const -(eq_bigr _ (in1W e1)). +case/normC_sum_eq1=> [i _ | c /eqP norm_c_1 def_e]; first by rewrite e1. +have{def_e} def_e: e = const_mx c by apply/rowP=> i; rewrite mxE def_e ?andbT. +by exists c => //; rewrite def_x def_e diag_const_mx scalar_mxC mulmxKV. +Qed. + +Lemma max_cfRepr_mx1 n (rG : mx_representation algCF G n) x : + x \in G -> cfRepr rG x = cfRepr rG 1%g -> rG x = 1%:M. +Proof. +move=> Gx kerGx; have [|c _ def_x] := @max_cfRepr_norm_scalar n rG x Gx. + by rewrite kerGx cfRepr1 normr_nat. +move/eqP: kerGx; rewrite cfRepr1 cfunE Gx {rG}def_x mxtrace_scalar. +case: n => [_|n]; first by rewrite ![_%:M]flatmx0. +rewrite mulrb -subr_eq0 -mulrnBl -mulr_natl mulf_eq0 pnatr_eq0 /=. +by rewrite subr_eq0 => /eqP->. +Qed. + +Definition irr_constt (B : {set gT}) phi := [pred i | '[phi, 'chi_i]_B != 0]. + +Lemma irr_consttE i phi : (i \in irr_constt phi) = ('[phi, 'chi_i]_G != 0). +Proof. by []. Qed. + +Lemma constt_charP (i : Iirr G) chi : + chi \is a character -> + reflect (exists2 chi', chi' \is a character & chi = 'chi_i + chi') + (i \in irr_constt chi). +Proof. +move=> Nchi; apply: (iffP idP) => [i_in_chi| [chi' Nchi' ->]]; last first. + rewrite inE /= cfdotDl cfdot_irr eqxx -(eqP (Cnat_cfdot_char_irr i Nchi')). + by rewrite -natrD pnatr_eq0. +exists (chi - 'chi_i); last by rewrite addrC subrK. +apply/forallP=> j; rewrite coord_cfdot cfdotBl cfdot_irr. +have [<- | _] := eqP; last by rewrite subr0 Cnat_cfdot_char_irr. +have := i_in_chi; rewrite inE /= -(eqP (Cnat_cfdot_char_irr i Nchi)) pnatr_eq0. +by case: (truncC _) => // n _; rewrite mulrSr addrK ?isNatC_nat. +Qed. + +Lemma cfun_sum_constt (phi : 'CF(G)) : + phi = \sum_(i in irr_constt phi) '[phi, 'chi_i] *: 'chi_i. +Proof. +rewrite {1}[phi]cfun_sum_cfdot (bigID [pred i | '[phi, 'chi_i] == 0]) /=. +by rewrite big1 ?add0r // => i /eqP->; rewrite scale0r. +Qed. + +Lemma neq0_has_constt (phi : 'CF(G)) : + phi != 0 -> exists i, i \in irr_constt phi. +Proof. +move=> nz_phi; apply/existsP; apply: contra nz_phi => /pred0P phi0. +by rewrite [phi]cfun_sum_constt big_pred0. +Qed. + +Lemma constt_irr i : irr_constt 'chi[G]_i =i pred1 i. +Proof. +by move=> j; rewrite !inE cfdot_irr pnatr_eq0 (eq_sym j); case: (i == j). +Qed. + +Lemma char1_ge_constt (i : Iirr G) chi : + chi \is a character -> i \in irr_constt chi -> 'chi_i 1%g <= chi 1%g. +Proof. +move=> {chi} _ /constt_charP[// | chi Nchi ->]. +by rewrite cfunE addrC -subr_ge0 addrK char1_ge0. +Qed. + +Lemma constt_ortho_char (phi psi : 'CF(G)) i j : + phi \is a character -> psi \is a character -> + i \in irr_constt phi -> j \in irr_constt psi -> + '[phi, psi] = 0 -> '['chi_i, 'chi_j] = 0. +Proof. +move=> _ _ /constt_charP[//|phi1 Nphi1 ->] /constt_charP[//|psi1 Npsi1 ->]. +rewrite cfdot_irr; case: eqP => // -> /eqP/idPn[]. +rewrite cfdotDl !cfdotDr cfnorm_irr -addrA gtr_eqF ?ltr_paddr ?ltr01 //. +by rewrite Cnat_ge0 ?rpredD ?Cnat_cfdot_char ?irr_char. +Qed. + +End IrrConstt. + +Arguments Scope irr_constt [_ group_scope cfun_scope]. +Implicit Arguments aut_Iirr_inj [gT G x1 x2]. + +Section MoreConstt. + +Variables (gT : finGroupType) (G H : {group gT}). + +Lemma constt_Ind_Res i j : + i \in irr_constt ('Ind[G] 'chi_j) = (j \in irr_constt ('Res[H] 'chi_i)). +Proof. by rewrite !irr_consttE cfdotC conjC_eq0 -cfdot_Res_l. Qed. + +Lemma cfdot_Res_ge_constt i j psi : + psi \is a character -> j \in irr_constt psi -> + '['Res[H, G] 'chi_j, 'chi_i] <= '['Res[H] psi, 'chi_i]. +Proof. +move=> {psi} _ /constt_charP[// | psi Npsi ->]. +rewrite linearD cfdotDl addrC -subr_ge0 addrK Cnat_ge0 //=. +by rewrite Cnat_cfdot_char_irr // cfRes_char. +Qed. + +Lemma constt_Res_trans j psi : + psi \is a character -> j \in irr_constt psi -> + {subset irr_constt ('Res[H, G] 'chi_j) <= irr_constt ('Res[H] psi)}. +Proof. +move=> Npsi Cj i; apply: contraNneq; rewrite eqr_le => {1}<-. +rewrite cfdot_Res_ge_constt ?Cnat_ge0 ?Cnat_cfdot_char_irr //. +by rewrite cfRes_char ?irr_char. +Qed. + +End MoreConstt. + +Section Kernel. + +Variable (gT : finGroupType) (G : {group gT}). +Implicit Types (phi chi xi : 'CF(G)) (H : {group gT}). + +Lemma cfker_repr n (rG : mx_representation algCF G n) : + cfker (cfRepr rG) = rker rG. +Proof. +apply/esym/setP=> x; rewrite inE mul1mx /=. +case Gx: (x \in G); last by rewrite inE Gx. +apply/eqP/idP=> Kx; last by rewrite max_cfRepr_mx1 // cfker1. +rewrite inE Gx; apply/forallP=> y; rewrite !cfunE !mulrb groupMl //. +by case: ifP => // Gy; rewrite repr_mxM // Kx mul1mx. +Qed. + +Lemma cfkerEchar chi : + chi \is a character -> cfker chi = [set x in G | chi x == chi 1%g]. +Proof. +move=> Nchi; apply/setP=> x; apply/idP/setIdP=> [Kx | [Gx /eqP chi_x]]. + by rewrite (subsetP (cfker_sub chi)) // cfker1. +case/char_reprP: Nchi => rG -> in chi_x *; rewrite inE Gx; apply/forallP=> y. +rewrite !cfunE groupMl // !mulrb; case: ifP => // Gy. +by rewrite repr_mxM // max_cfRepr_mx1 ?mul1mx. +Qed. + +Lemma cfker_nzcharE chi : + chi \is a character -> chi != 0 -> cfker chi = [set x | chi x == chi 1%g]. +Proof. +move=> Nchi nzchi; apply/setP=> x; rewrite cfkerEchar // !inE andb_idl //. +by apply: contraLR => /cfun0-> //; rewrite eq_sym char1_eq0. +Qed. + +Lemma cfkerEirr i : cfker 'chi[G]_i = [set x | 'chi_i x == 'chi_i 1%g]. +Proof. by rewrite cfker_nzcharE ?irr_char ?irr_neq0. Qed. + +Lemma cfker_irr0 : cfker 'chi[G]_0 = G. +Proof. by rewrite irr0 cfker_cfun1. Qed. + +Lemma cfaithful_reg : cfaithful (cfReg G). +Proof. +apply/subsetP=> x; rewrite cfkerEchar ?cfReg_char // !inE !cfRegE eqxx. +by case/andP=> _; apply: contraLR => /negbTE->; rewrite eq_sym neq0CG. +Qed. + +Lemma cfkerE chi : + chi \is a character -> + cfker chi = G :&: \bigcap_(i in irr_constt chi) cfker 'chi_i. +Proof. +move=> Nchi; rewrite cfkerEchar //; apply/setP=> x; rewrite !inE. +apply: andb_id2l => Gx; rewrite {1 2}[chi]cfun_sum_constt !sum_cfunE. +apply/eqP/bigcapP=> [Kx i Ci | Kx]; last first. + by apply: eq_bigr => i /Kx Kx_i; rewrite !cfunE cfker1. +rewrite cfkerEirr inE /= -(inj_eq (mulfI Ci)). +have:= (normC_sum_upper _ Kx) i; rewrite !cfunE => -> // {i Ci} i _. +have chi_i_ge0: 0 <= '[chi, 'chi_i]. + by rewrite Cnat_ge0 ?Cnat_cfdot_char_irr. +by rewrite !cfunE normrM (normr_idP _) ?ler_wpmul2l ?char1_ge_norm ?irr_char. +Qed. + +Lemma TI_cfker_irr : \bigcap_i cfker 'chi[G]_i = [1]. +Proof. +apply/trivgP; apply: subset_trans cfaithful_reg; rewrite cfkerE ?cfReg_char //. +rewrite subsetI (bigcap_min 0) //=; last by rewrite cfker_irr0. +by apply/bigcapsP=> i _; rewrite bigcap_inf. +Qed. + +Lemma cfker_constt i chi : + chi \is a character -> i \in irr_constt chi -> + cfker chi \subset cfker 'chi[G]_i. +Proof. by move=> Nchi Ci; rewrite cfkerE ?subIset ?(bigcap_min i) ?orbT. Qed. + +Section KerLin. + +Variable xi : 'CF(G). +Hypothesis lin_xi : xi \is a linear_char. +Let Nxi: xi \is a character. Proof. by have [] := andP lin_xi. Qed. + +Lemma lin_char_der1 : G^`(1)%g \subset cfker xi. +Proof. +rewrite gen_subG /=; apply/subsetP=> _ /imset2P[x y Gx Gy ->]. +rewrite cfkerEchar // inE groupR //= !lin_charM ?lin_charV ?in_group //. +by rewrite mulrCA mulKf ?mulVf ?lin_char_neq0 // lin_char1. +Qed. + +Lemma cforder_lin_char : #[xi]%CF = exponent (G / cfker xi)%g. +Proof. +apply/eqP; rewrite eqn_dvd; apply/andP; split. + apply/dvdn_cforderP=> x Gx; rewrite -lin_charX // -cfQuoEker ?groupX //. + rewrite morphX ?(subsetP (cfker_norm xi)) //= expg_exponent ?mem_quotient //. + by rewrite cfQuo1 ?cfker_normal ?lin_char1. +have abGbar: abelian (G / cfker xi) := sub_der1_abelian lin_char_der1. +have [_ /morphimP[x Nx Gx ->] ->] := exponent_witness (abelian_nil abGbar). +rewrite order_dvdn -morphX //= coset_id cfkerEchar // !inE groupX //=. +by rewrite lin_charX ?lin_char1 // (dvdn_cforderP _ _ _). +Qed. + +Lemma cforder_lin_char_dvdG : #[xi]%CF %| #|G|. +Proof. +by rewrite cforder_lin_char (dvdn_trans (exponent_dvdn _)) ?dvdn_morphim. +Qed. + +Lemma cforder_lin_char_gt0 : (0 < #[xi]%CF)%N. +Proof. by rewrite cforder_lin_char exponent_gt0. Qed. + +End KerLin. + +End Kernel. + +Section Coset. + +Variable (gT : finGroupType). + +Implicit Types G H : {group gT}. + +Lemma cfQuo_char G H (chi : 'CF(G)) : + chi \is a character -> (chi / H)%CF \is a character. +Proof. +move=> Nchi; case KchiH: (H \subset cfker chi); last first. + suffices ->: (chi / H)%CF = (chi 1%g)%:A. + by rewrite rpredZ_Cnat ?Cnat_char1 ?rpred1. + by apply/cfunP=> x; rewrite cfunE cfun1E mulr_natr cfunElock KchiH. +have sHG := subset_trans KchiH (cfker_sub _). +pose N := 'N_G(H); pose phi := 'Res[N] chi. +have nsHN: H <| N by [rewrite normal_subnorm]; have [sHN nHN] := andP nsHN. +have{Nchi} Nphi: phi \is a character by apply: cfRes_char. +have KphiH: H \subset cfker phi. + apply/subsetP=> x Hx; have [Kx Nx] := (subsetP KchiH x Hx, subsetP sHN x Hx). + by rewrite cfkerEchar // inE Nx cfRes1 cfResE ?subsetIl //= cfker1. +pose psi := 'Res[(N / H)%g] (chi / H)%CF. +have ->: (chi / H)%CF = 'Res psi by rewrite /psi quotientInorm !cfRes_id. +have{KchiH} ->: psi = (phi / H)%CF. + apply/cfun_inP => _ /morphimP[x nHx Nx ->]; have [Gx _] := setIP Nx. + rewrite cfResE ?mem_quotient ?quotientS ?subsetIl // cfQuoEnorm //. + by rewrite cfQuoE ?cfResE ?subsetIl. +have [rG Dphi] := char_reprP Nphi; rewrite {phi Nphi}Dphi cfker_repr in KphiH *. +apply/cfRes_char/char_reprP; exists (Representation (quo_repr KphiH nHN)). +apply/cfun_inP=> _ /morphimP[x nHx Nx ->]; rewrite cfQuoE ?cfker_repr //=. +by rewrite !cfunE Nx quo_repr_coset ?mem_quotient. +Qed. + +Lemma cfQuo_lin_char G H (chi : 'CF(G)) : + chi \is a linear_char -> (chi / H)%CF \is a linear_char. +Proof. by case/andP=> Nchi; rewrite qualifE cfQuo_char ?cfQuo1. Qed. + +Lemma cfMod_char G H (chi : 'CF(G / H)) : + chi \is a character -> (chi %% H)%CF \is a character. +Proof. exact: cfMorph_char. Qed. + +Lemma cfMod_lin_char G H (chi : 'CF(G / H)) : + chi \is a linear_char -> (chi %% H)%CF \is a linear_char. +Proof. exact: cfMorph_lin_char. Qed. + +Lemma cfMod_irr G H chi : + H <| G -> chi \in irr (G / H) -> (chi %% H)%CF \in irr G. +Proof. by case/andP=> _; apply: cfMorph_irr. Qed. + +Definition mod_Iirr G H i := cfIirr ('chi[G / H]_i %% H)%CF. + +Lemma mod_Iirr0 G H : mod_Iirr (0 : Iirr (G / H)) = 0. +Proof. exact: morph_Iirr0. Qed. + +Lemma mod_IirrE G H i : H <| G -> 'chi_(mod_Iirr i) = ('chi[G / H]_i %% H)%CF. +Proof. by move=> nsHG; rewrite cfIirrE ?cfMod_irr ?mem_irr. Qed. + +Lemma mod_Iirr_eq0 G H i : + H <| G -> (mod_Iirr i == 0) = (i == 0 :> Iirr (G / H)). +Proof. by case/andP=> _ /morph_Iirr_eq0->. Qed. + +Lemma cfQuo_irr G H chi : + H <| G -> H \subset cfker chi -> chi \in irr G -> + (chi / H)%CF \in irr (G / H). +Proof. +move=> nsHG sHK /irr_reprP[rG irrG Dchi]; have [sHG nHG] := andP nsHG. +have sHKr: H \subset rker rG by rewrite -cfker_repr -Dchi. +apply/irr_reprP; exists (Representation (quo_repr sHKr nHG)). + exact/quo_mx_irr. +apply/cfun_inP=> _ /morphimP[x Nx Gx ->]. +by rewrite cfQuoE //= Dchi !cfunE Gx quo_repr_coset ?mem_quotient. +Qed. + +Definition quo_Iirr G H i := cfIirr ('chi[G]_i / H)%CF. + +Lemma quo_Iirr0 G H : quo_Iirr H (0 : Iirr G) = 0. +Proof. by rewrite /quo_Iirr irr0 cfQuo_cfun1 -irr0 irrK. Qed. + +Lemma quo_IirrE G H i : + H <| G -> H \subset cfker 'chi[G]_i -> 'chi_(quo_Iirr H i) = ('chi_i / H)%CF. +Proof. by move=> nsHG kerH; rewrite cfIirrE ?cfQuo_irr ?mem_irr. Qed. + +Lemma quo_Iirr_eq0 G H i : + H <| G -> H \subset cfker 'chi[G]_i -> (quo_Iirr H i == 0) = (i == 0). +Proof. by move=> nsHG kerH; rewrite -!irr_eq1 quo_IirrE ?cfQuo_eq1. Qed. + +Lemma mod_IirrK G H : H <| G -> cancel (@mod_Iirr G H) (@quo_Iirr G H). +Proof. +move=> nsHG i; apply: irr_inj. +by rewrite quo_IirrE ?mod_IirrE ?cfker_mod // cfModK. +Qed. + +Lemma quo_IirrK G H i : + H <| G -> H \subset cfker 'chi[G]_i -> mod_Iirr (quo_Iirr H i) = i. +Proof. +by move=> nsHG kerH; apply: irr_inj; rewrite mod_IirrE ?quo_IirrE ?cfQuoK. +Qed. + +Lemma quo_IirrKeq G H : + H <| G -> + forall i, (mod_Iirr (quo_Iirr H i) == i) = (H \subset cfker 'chi[G]_i). +Proof. +move=> nsHG i; apply/eqP/idP=> [<- | ]; last exact: quo_IirrK. +by rewrite mod_IirrE ?cfker_mod. +Qed. + +Lemma mod_Iirr_bij H G : + H <| G -> {on [pred i | H \subset cfker 'chi_i], bijective (@mod_Iirr G H)}. +Proof. +by exists (quo_Iirr H) => [i _ | i]; [exact: mod_IirrK | exact: quo_IirrK]. +Qed. + +Lemma sum_norm_irr_quo H G x : + x \in G -> H <| G -> + \sum_i `|'chi[G / H]_i (coset H x)| ^+ 2 + = \sum_(i | H \subset cfker 'chi_i) `|'chi[G]_i x| ^+ 2. +Proof. +move=> Gx nsHG; rewrite (reindex _ (mod_Iirr_bij nsHG)) /=. +by apply/esym/eq_big=> [i | i _]; rewrite mod_IirrE ?cfker_mod ?cfModE. +Qed. + +Lemma cap_cfker_normal G H : + H <| G -> \bigcap_(i | H \subset cfker 'chi[G]_i) (cfker 'chi_i) = H. +Proof. +move=> nsHG; have [sHG nHG] := andP nsHG; set lhs := \bigcap_(i | _) _. +have nHlhs: lhs \subset 'N(H) by rewrite (bigcap_min 0) ?cfker_irr0. +apply/esym/eqP; rewrite eqEsubset (introT bigcapsP) //= -quotient_sub1 //. +rewrite -(TI_cfker_irr (G / H)); apply/bigcapsP=> i _. +rewrite sub_quotient_pre // (bigcap_min (mod_Iirr i)) ?mod_IirrE ?cfker_mod //. +by rewrite cfker_morph ?subsetIr. +Qed. + +Lemma cfker_reg_quo G H : H <| G -> cfker (cfReg (G / H)%g %% H) = H. +Proof. +move=> nsHG; have [sHG nHG] := andP nsHG. +apply/setP=> x; rewrite cfkerEchar ?cfMod_char ?cfReg_char //. +rewrite -[in RHS in _ = RHS](setIidPr sHG) !inE; apply: andb_id2l => Gx. +rewrite !cfModE // !cfRegE // morph1 eqxx. +rewrite (sameP eqP (kerP _ (subsetP nHG x Gx))) ker_coset. +by rewrite -!mulrnA eqr_nat eqn_pmul2l ?cardG_gt0 // (can_eq oddb) eqb_id. +Qed. + +End Coset. + +Section Derive. + +Variable gT : finGroupType. +Implicit Types G H : {group gT}. + +Lemma lin_irr_der1 G i : + ('chi_i \is a linear_char) = (G^`(1)%g \subset cfker 'chi[G]_i). +Proof. +apply/idP/idP=> [|sG'K]; first by apply: lin_char_der1. +have nsG'G: G^`(1) <| G := der_normal 1 G. +rewrite qualifE irr_char -[i](quo_IirrK nsG'G) // mod_IirrE //=. +by rewrite cfModE // morph1 lin_char1 //; exact/char_abelianP/der_abelian. +Qed. + +Lemma subGcfker G i : (G \subset cfker 'chi[G]_i) = (i == 0). +Proof. +rewrite -irr_eq1; apply/idP/eqP=> [chiG1 | ->]; last by rewrite cfker_cfun1. +apply/cfun_inP=> x Gx; rewrite cfun1E Gx cfker1 ?(subsetP chiG1) ?lin_char1 //. +by rewrite lin_irr_der1 (subset_trans (der_sub 1 G)). +Qed. + +Lemma irr_prime_injP G i : + prime #|G| -> reflect {in G &, injective 'chi[G]_i} (i != 0). +Proof. +move=> pr_G; apply: (iffP idP) => [nz_i | inj_chi]. + apply: fful_lin_char_inj (irr_prime_lin i pr_G) _. + by rewrite cfaithfulE -(setIidPr (cfker_sub _)) prime_TIg // subGcfker. +have /trivgPn[x Gx ntx]: G :!=: 1%g by rewrite -cardG_gt1 prime_gt1. +apply: contraNneq ntx => i0; apply/eqP/inj_chi=> //. +by rewrite i0 irr0 !cfun1E Gx group1. +Qed. + +(* This is Isaacs (2.23)(a). *) +Lemma cap_cfker_lin_irr G : + \bigcap_(i | 'chi[G]_i \is a linear_char) (cfker 'chi_i) = G^`(1)%g. +Proof. +rewrite -(cap_cfker_normal (der_normal 1 G)). +by apply: eq_bigl => i; rewrite lin_irr_der1. +Qed. + +(* This is Isaacs (2.23)(b) *) +Lemma card_lin_irr G : + #|[pred i | 'chi[G]_i \is a linear_char]| = #|G : G^`(1)%g|. +Proof. +have nsG'G := der_normal 1 G; rewrite (eq_card (@lin_irr_der1 G)). +rewrite -(on_card_preimset (mod_Iirr_bij nsG'G)). +rewrite -card_quotient ?normal_norm //. +move: (der_abelian 0 G); rewrite card_classes_abelian; move/eqP<-. +rewrite -NirrE -[X in _ = X]card_ord. +by apply: eq_card => i; rewrite !inE mod_IirrE ?cfker_mod. +(* Alternative: use the equivalent result in modular representation theory +transitivity #|@socle_of_Iirr _ G @^-1: linear_irr _|; last first. + rewrite (on_card_preimset (socle_of_Iirr_bij _)). + by rewrite card_linear_irr ?algC'G; last exact: groupC. +by apply: eq_card => i; rewrite !inE /lin_char irr_char irr1_degree -eqC_nat. +*) +Qed. + +(* A non-trivial solvable group has a nonprincipal linear character. *) +Lemma solvable_has_lin_char G : + G :!=: 1%g -> solvable G -> + exists2 i, 'chi[G]_i \is a linear_char & 'chi_i != 1. +Proof. +move=> ntG solG. +suff /subsetPn[i]: ~~ ([pred i | 'chi[G]_i \is a linear_char] \subset pred1 0). + by rewrite !inE -(inj_eq irr_inj) irr0; exists i. +rewrite (contra (@subset_leq_card _ _ _)) // -ltnNge card1 card_lin_irr. +by rewrite indexg_gt1 proper_subn // (sol_der1_proper solG). +Qed. + +(* A combinatorial group isommorphic to the linear characters. *) +Lemma lin_char_group G : + {linG : finGroupType & {cF : linG -> 'CF(G) | + [/\ injective cF, #|linG| = #|G : G^`(1)|, + forall u, cF u \is a linear_char + & forall phi, phi \is a linear_char -> exists u, phi = cF u] + & [/\ cF 1%g = 1%R, + {morph cF : u v / (u * v)%g >-> (u * v)%R}, + forall k, {morph cF : u / (u^+ k)%g >-> u ^+ k}, + {morph cF: u / u^-1%g >-> u^-1%CF} + & {mono cF: u / #[u]%g >-> #[u]%CF} ]}}. +Proof. +pose linT := {i : Iirr G | 'chi_i \is a linear_char}. +pose cF (u : linT) := 'chi_(sval u). +have cFlin u: cF u \is a linear_char := svalP u. +have cFinj: injective cF := inj_comp irr_inj val_inj. +have inT xi : xi \is a linear_char -> {u | cF u = xi}. + move=> lin_xi; have /irrP/sig_eqW[i Dxi] := lin_char_irr lin_xi. + by apply: (exist _ (Sub i _)) => //; rewrite -Dxi. +have [one cFone] := inT 1 (rpred1 _). +pose inv u := sval (inT _ (rpredVr (cFlin u))). +pose mul u v := sval (inT _ (rpredM (cFlin u) (cFlin v))). +have cFmul u v: cF (mul u v) = cF u * cF v := svalP (inT _ _). +have cFinv u: cF (inv u) = (cF u)^-1 := svalP (inT _ _). +have mulA: associative mul by move=> u v w; apply: cFinj; rewrite !cFmul mulrA. +have mul1: left_id one mul by move=> u; apply: cFinj; rewrite cFmul cFone mul1r. +have mulV: left_inverse one inv mul. + by move=> u; apply: cFinj; rewrite cFmul cFinv cFone mulVr ?lin_char_unitr. +pose linGm := FinGroup.Mixin mulA mul1 mulV. +pose linG := @FinGroupType (BaseFinGroupType linT linGm) mulV. +have cFexp k: {morph cF : u / ((u : linG) ^+ k)%g >-> u ^+ k}. + by move=> u; elim: k => // k IHk; rewrite expgS exprS cFmul IHk. +do [exists linG, cF; split=> //] => [|xi /inT[u <-]|u]; first 2 [by exists u]. + have inj_cFI: injective (cfIirr \o cF). + apply: can_inj (insubd one) _ => u; apply: val_inj. + by rewrite insubdK /= ?irrK //; apply: cFlin. + rewrite -(card_image inj_cFI) -card_lin_irr. + apply/eq_card=> i; rewrite inE; apply/codomP/idP=> [[u ->] | /inT[u Du]]. + by rewrite /= irrK; apply: cFlin. + by exists u; apply: irr_inj; rewrite /= irrK. +apply/eqP; rewrite eqn_dvd; apply/andP; split. + by rewrite dvdn_cforder; rewrite -cFexp expg_order cFone. +by rewrite order_dvdn -(inj_eq cFinj) cFone cFexp exp_cforder. +Qed. + +Lemma cfExp_prime_transitive G (i j : Iirr G) : + prime #|G| -> i != 0 -> j != 0 -> + exists2 k, coprime k #['chi_i]%CF & 'chi_j = 'chi_i ^+ k. +Proof. +set p := #|G| => pr_p nz_i nz_j; have cycG := prime_cyclic pr_p. +have [L [h [injh oL Lh h_ontoL]] [h1 hM hX _ o_h]] := lin_char_group G. +rewrite (derG1P (cyclic_abelian cycG)) indexg1 -/p in oL. +have /fin_all_exists[h' h'K] := h_ontoL _ (irr_cyclic_lin _ cycG). +have o_h' k: k != 0 -> #[h' k] = p. + rewrite -cforder_irr_eq1 h'K -o_h => nt_h'k. + by apply/prime_nt_dvdP=> //; rewrite cforder_lin_char_dvdG. +have{oL} genL k: k != 0 -> generator [set: L] (h' k). + move=> /o_h' o_h'k; rewrite /generator eq_sym eqEcard subsetT /=. + by rewrite cardsT oL -o_h'k. +have [/(_ =P <[_]>)-> gen_j] := (genL i nz_i, genL j nz_j). +have /cycleP[k Dj] := cycle_generator gen_j. +by rewrite !h'K Dj o_h hX generator_coprime coprime_sym in gen_j *; exists k. +Qed. + +(* This is Isaacs (2.24). *) +Lemma card_subcent1_coset G H x : + x \in G -> H <| G -> (#|'C_(G / H)[coset H x]| <= #|'C_G[x]|)%N. +Proof. +move=> Gx nsHG; rewrite -leC_nat. +move: (second_orthogonality_relation x Gx); rewrite mulrb class_refl => <-. +have GHx: coset H x \in (G / H)%g by apply: mem_quotient. +move: (second_orthogonality_relation (coset H x) GHx). +rewrite mulrb class_refl => <-. +rewrite -2!(eq_bigr _ (fun _ _ => normCK _)) sum_norm_irr_quo // -subr_ge0. +rewrite (bigID (fun i => H \subset cfker 'chi[G]_i)) //= addrC addKr. +by apply: sumr_ge0 => i _; rewrite normCK mul_conjC_ge0. +Qed. + +End Derive. + +Implicit Arguments irr_prime_injP [gT G i]. + +(* Determinant characters and determinential order. *) +Section DetOrder. + +Variables (gT : finGroupType) (G : {group gT}). + +Section DetRepr. + +Variables (n : nat) (rG : mx_representation [fieldType of algC] G n). + +Definition det_repr_mx x : 'M_1 := (\det (rG x))%:M. + +Fact det_is_repr : mx_repr G det_repr_mx. +Proof. +split=> [|g h Gg Gh]; first by rewrite /det_repr_mx repr_mx1 det1. +by rewrite /det_repr_mx repr_mxM // det_mulmx !mulmxE scalar_mxM. +Qed. + +Canonical det_repr := MxRepresentation det_is_repr. +Definition detRepr := cfRepr det_repr. + +Lemma detRepr_lin_char : detRepr \is a linear_char. +Proof. +by rewrite qualifE cfRepr_char cfunE group1 repr_mx1 mxtrace1 mulr1n /=. +Qed. + +End DetRepr. + +Definition cfDet phi := \prod_i detRepr 'Chi_i ^+ truncC '[phi, 'chi[G]_i]. + +Lemma cfDet_lin_char phi : cfDet phi \is a linear_char. +Proof. by apply: rpred_prod => i _; apply: rpredX; apply: detRepr_lin_char. Qed. + +Lemma cfDetD : + {in character &, {morph cfDet : phi psi / phi + psi >-> phi * psi}}. +Proof. +move=> phi psi Nphi Npsi; rewrite /= -big_split; apply: eq_bigr => i _ /=. +by rewrite -exprD cfdotDl truncCD ?nnegrE ?Cnat_ge0 // Cnat_cfdot_char_irr. +Qed. + +Lemma cfDet0 : cfDet 0 = 1. +Proof. by rewrite /cfDet big1 // => i _; rewrite cfdot0l truncC0. Qed. + +Lemma cfDetMn k : + {in character, {morph cfDet : phi / phi *+ k >-> phi ^+ k}}. +Proof. +move=> phi Nphi; elim: k => [|k IHk]; rewrite ?cfDet0 // mulrS exprS -{}IHk. +by rewrite cfDetD ?rpredMn. +Qed. + +Lemma cfDetRepr n rG : cfDet (cfRepr rG) = @detRepr n rG. +Proof. +transitivity (\prod_W detRepr (socle_repr W) ^+ standard_irr_coef rG W). + rewrite (reindex _ (socle_of_Iirr_bij _)) /cfDet /=. + apply: eq_bigr => i _; congr (_ ^+ _). + rewrite (cfRepr_sim (mx_rsim_standard rG)) cfRepr_standard. + rewrite cfdot_suml (bigD1 i) ?big1 //= => [|j i'j]; last first. + by rewrite cfdotZl cfdot_irr (negPf i'j) mulr0. + by rewrite cfdotZl cfnorm_irr mulr1 addr0 natCK. +apply/cfun_inP=> x Gx; rewrite prod_cfunE //. +transitivity (detRepr (standard_grepr rG) x); last first. + rewrite !cfunE Gx !trace_mx11 !mxE eqxx !mulrb. + case: (standard_grepr rG) (mx_rsim_standard rG) => /= n1 rG1 [B Dn1]. + rewrite -{n1}Dn1 in rG1 B *; rewrite row_free_unit => uB rG_B. + by rewrite -[rG x](mulmxK uB) rG_B // !det_mulmx mulrC -!det_mulmx mulKmx. +rewrite /standard_grepr; elim/big_rec2: _ => [|W y _ _ ->]. + by rewrite cfunE trace_mx11 mxE Gx det1. +rewrite !cfunE Gx /= !{1}trace_mx11 !{1}mxE det_ublock; congr (_ * _). +rewrite exp_cfunE //; elim: (standard_irr_coef rG W) => /= [|k IHk]. + by rewrite /muln_grepr big_ord0 det1. +rewrite exprS /muln_grepr big_ord_recl det_ublock -IHk; congr (_ * _). +by rewrite cfunE trace_mx11 mxE Gx. +Qed. + +Lemma cfDet_id xi : xi \is a linear_char -> cfDet xi = xi. +Proof. +move=> lin_xi; have /irrP[i Dxi] := lin_char_irr lin_xi. +apply/cfun_inP=> x Gx; rewrite Dxi -irrRepr cfDetRepr !cfunE trace_mx11 mxE. +move: lin_xi (_ x) => /andP[_]; rewrite Dxi irr1_degree pnatr_eq1 => /eqP-> X. +by rewrite {1}[X]mx11_scalar det_scalar1 trace_mx11. +Qed. + +Definition cfDet_order phi := #[cfDet phi]%CF. + +Definition cfDet_order_lin xi : + xi \is a linear_char -> cfDet_order xi = #[xi]%CF. +Proof. by rewrite /cfDet_order => /cfDet_id->. Qed. + +Definition cfDet_order_dvdG phi : cfDet_order phi %| #|G|. +Proof. by rewrite cforder_lin_char_dvdG ?cfDet_lin_char. Qed. + +End DetOrder. + +Notation "''o' ( phi )" := (cfDet_order phi) + (at level 8, format "''o' ( phi )") : cfun_scope. + +Section CfDetOps. + +Implicit Types gT aT rT : finGroupType. + +Lemma cfDetRes gT (G H : {group gT}) phi : + phi \is a character -> cfDet ('Res[H, G] phi) = 'Res (cfDet phi). +Proof. +move=> Nphi; have [sGH | not_sHG] := boolP (H \subset G); last first. + have /CnatP[n Dphi1] := Cnat_char1 Nphi. + rewrite !cfResEout // Dphi1 lin_char1 ?cfDet_lin_char // scale1r. + by rewrite scaler_nat cfDetMn ?cfDet_id ?rpred1 // expr1n. +have [rG ->] := char_reprP Nphi; rewrite !(=^~ cfRepr_sub, cfDetRepr) //. +apply: cfRepr_sim; exists 1%:M; rewrite ?row_free_unit ?unitmx1 // => x Hx. +by rewrite mulmx1 mul1mx. +Qed. + +Lemma cfDetMorph aT rT (D G : {group aT}) (f : {morphism D >-> rT}) + (phi : 'CF(f @* G)) : + phi \is a character -> cfDet (cfMorph phi) = cfMorph (cfDet phi). +Proof. +move=> Nphi; have [sGD | not_sGD] := boolP (G \subset D); last first. + have /CnatP[n Dphi1] := Cnat_char1 Nphi. + rewrite !cfMorphEout // Dphi1 lin_char1 ?cfDet_lin_char // scale1r. + by rewrite scaler_nat cfDetMn ?cfDet_id ?rpred1 // expr1n. +have [rG ->] := char_reprP Nphi; rewrite !(=^~ cfRepr_morphim, cfDetRepr) //. +apply: cfRepr_sim; exists 1%:M; rewrite ?row_free_unit ?unitmx1 // => x Hx. +by rewrite mulmx1 mul1mx. +Qed. + +Lemma cfDetIsom aT rT (G : {group aT}) (R : {group rT}) + (f : {morphism G >-> rT}) (isoGR : isom G R f) phi : + cfDet (cfIsom isoGR phi) = cfIsom isoGR (cfDet phi). +Proof. +rewrite rmorph_prod /cfDet (reindex (isom_Iirr isoGR)); last first. + by exists (isom_Iirr (isom_sym isoGR)) => i; rewrite ?isom_IirrK ?isom_IirrKV. +apply: eq_bigr => i; rewrite -!cfDetRepr !irrRepr isom_IirrE rmorphX cfIsom_iso. +by rewrite /= ![in cfIsom _]unlock cfDetMorph ?cfRes_char ?cfDetRes ?irr_char. +Qed. + +Lemma cfDet_mul_lin gT (G : {group gT}) (lambda phi : 'CF(G)) : + lambda \is a linear_char -> phi \is a character -> + cfDet (lambda * phi) = lambda ^+ truncC (phi 1%g) * cfDet phi. +Proof. +case/andP=> /char_reprP[[n1 rG1] ->] /= n1_1 /char_reprP[[n2 rG2] ->] /=. +do [rewrite !cfRepr1 pnatr_eq1 natCK; move/eqP] in n1_1 *. +rewrite {n1}n1_1 in rG1 *; rewrite cfRepr_prod cfDetRepr. +apply/cfun_inP=> x Gx; rewrite !cfunE cfDetRepr cfunE Gx !mulrb !trace_mx11. +rewrite !mxE prod_repr_lin ?mulrb //=; case: _ / (esym _); rewrite detZ. +congr (_ * _); case: {rG2}n2 => [|n2]; first by rewrite cfun1E Gx. +by rewrite expS_cfunE //= cfunE Gx trace_mx11. +Qed. + +End CfDetOps. + +Definition cfcenter (gT : finGroupType) (G : {set gT}) (phi : 'CF(G)) := + if phi \is a character then [set g in G | `|phi g| == phi 1%g] else cfker phi. + +Notation "''Z' ( phi )" := (cfcenter phi) : cfun_scope. + +Section Center. + +Variable (gT : finGroupType) (G : {group gT}). +Implicit Types (phi chi : 'CF(G)) (H : {group gT}). + +(* This is Isaacs (2.27)(a). *) +Lemma cfcenter_repr n (rG : mx_representation algCF G n) : + 'Z(cfRepr rG)%CF = rcenter rG. +Proof. +rewrite /cfcenter /rcenter cfRepr_char /=. +apply/setP=> x; rewrite !inE; apply/andb_id2l=> Gx. +apply/eqP/is_scalar_mxP=> [|[c rG_c]]. + by case/max_cfRepr_norm_scalar=> // c; exists c. +rewrite -(sqrCK (char1_ge0 (cfRepr_char rG))) normC_def; congr (sqrtC _). +rewrite expr2 -{2}(mulgV x) -char_inv ?cfRepr_char ?cfunE ?groupM ?groupV //. +rewrite Gx group1 repr_mx1 repr_mxM ?repr_mxV ?groupV // !mulrb rG_c. +by rewrite invmx_scalar -scalar_mxM !mxtrace_scalar mulrnAr mulrnAl mulr_natl. +Qed. + +(* This is part of Isaacs (2.27)(b). *) +Fact cfcenter_group_set phi : group_set ('Z(phi))%CF. +Proof. +have [[rG ->] | /negbTE notNphi] := altP (@char_reprP _ G phi). + by rewrite cfcenter_repr groupP. +by rewrite /cfcenter notNphi groupP. +Qed. +Canonical cfcenter_group f := Group (cfcenter_group_set f). + +Lemma char_cfcenterE chi x : + chi \is a character -> x \in G -> + (x \in ('Z(chi))%CF) = (`|chi x| == chi 1%g). +Proof. by move=> Nchi Gx; rewrite /cfcenter Nchi inE Gx. Qed. + +Lemma irr_cfcenterE i x : + x \in G -> (x \in 'Z('chi[G]_i)%CF) = (`|'chi_i x| == 'chi_i 1%g). +Proof. by move/char_cfcenterE->; rewrite ?irr_char. Qed. + +(* This is also Isaacs (2.27)(b). *) +Lemma cfcenter_sub phi : ('Z(phi))%CF \subset G. +Proof. by rewrite /cfcenter /cfker !setIdE -fun_if subsetIl. Qed. + +Lemma cfker_center_normal phi : cfker phi <| 'Z(phi)%CF. +Proof. +apply: normalS (cfcenter_sub phi) (cfker_normal phi). +rewrite /= /cfcenter; case: ifP => // Hphi; rewrite cfkerEchar //. +apply/subsetP=> x; rewrite !inE => /andP[-> /eqP->] /=. +by rewrite ger0_norm ?char1_ge0. +Qed. + +Lemma cfcenter_normal phi : 'Z(phi)%CF <| G. +Proof. +have [[rG ->] | /negbTE notNphi] := altP (@char_reprP _ _ phi). + by rewrite cfcenter_repr rcenter_normal. +by rewrite /cfcenter notNphi cfker_normal. +Qed. + +(* This is Isaacs (2.27)(c). *) +Lemma cfcenter_Res chi : + exists2 chi1, chi1 \is a linear_char & 'Res['Z(chi)%CF] chi = chi 1%g *: chi1. +Proof. +have [[rG ->] | /negbTE notNphi] := altP (@char_reprP _ _ chi); last first. + exists 1; first exact: cfun1_lin_char. + rewrite /cfcenter notNphi; apply/cfun_inP=> x Kx. + by rewrite cfunE cfun1E Kx mulr1 cfResE ?cfker_sub // cfker1. +rewrite cfcenter_repr -(cfRepr_sub _ (normal_sub (rcenter_normal _))). +case: rG => [[|n] rG] /=; rewrite cfRepr1. + exists 1; first exact: cfun1_lin_char. + by apply/cfun_inP=> x Zx; rewrite scale0r !cfunE flatmx0 raddf0 Zx. +pose rZmx x := ((rG x 0 0)%:M : 'M_(1,1)). +have rZmxP: mx_repr [group of rcenter rG] rZmx. + split=> [|x y]; first by rewrite /rZmx repr_mx1 mxE eqxx. + move=> /setIdP[Gx /is_scalar_mxP[a rGx]] /setIdP[Gy /is_scalar_mxP[b rGy]]. + by rewrite /rZmx repr_mxM // rGx rGy -!scalar_mxM !mxE. +exists (cfRepr (MxRepresentation rZmxP)). + by rewrite qualifE cfRepr_char cfRepr1 eqxx. +apply/cfun_inP=> x Zx; rewrite !cfunE Zx /= /rZmx mulr_natl. +by case/setIdP: Zx => Gx /is_scalar_mxP[a ->]; rewrite mxE !mxtrace_scalar. +Qed. + +(* This is Isaacs (2.27)(d). *) +Lemma cfcenter_cyclic chi : cyclic ('Z(chi)%CF / cfker chi)%g. +Proof. +case Nchi: (chi \is a character); last first. + by rewrite /cfcenter Nchi trivg_quotient cyclic1. +have [-> | nz_chi] := eqVneq chi 0. + rewrite quotientS1 ?cyclic1 //= /cfcenter cfkerEchar ?cfun0_char //. + by apply/subsetP=> x /setIdP[Gx _]; rewrite inE Gx /= !cfunE. +have [xi Lxi def_chi] := cfcenter_Res chi. +set Z := ('Z(_))%CF in xi Lxi def_chi *. +have sZG: Z \subset G by exact: cfcenter_sub. +have ->: cfker chi = cfker xi. + rewrite -(setIidPr (normal_sub (cfker_center_normal _))) -/Z. + rewrite !cfkerEchar // ?lin_charW //= -/Z. + apply/setP=> x; rewrite !inE; apply: andb_id2l => Zx. + rewrite (subsetP sZG) //= -!(cfResE chi sZG) ?group1 // def_chi !cfunE. + by rewrite (inj_eq (mulfI _)) ?char1_eq0. +have: abelian (Z / cfker xi) by rewrite sub_der1_abelian ?lin_char_der1. +have [rG irrG ->] := irr_reprP _ (lin_char_irr Lxi); rewrite cfker_repr. +apply: mx_faithful_irr_abelian_cyclic (kquo_mx_faithful rG) _. +exact/quo_mx_irr. +Qed. + +(* This is Isaacs (2.27)(e). *) +Lemma cfcenter_subset_center chi : + ('Z(chi)%CF / cfker chi)%g \subset 'Z(G / cfker chi)%g. +Proof. +case Nchi: (chi \is a character); last first. + by rewrite /cfcenter Nchi trivg_quotient sub1G. +rewrite subsetI quotientS ?cfcenter_sub // quotient_cents2r //=. +case/char_reprP: Nchi => rG ->{chi}; rewrite cfker_repr cfcenter_repr gen_subG. +apply/subsetP=> _ /imset2P[x y /setIdP[Gx /is_scalar_mxP[c rGx]] Gy ->]. +rewrite inE groupR //= !repr_mxM ?groupM ?groupV // rGx -(scalar_mxC c) -rGx. +by rewrite !mulmxA !repr_mxKV. +Qed. + +(* This is Isaacs (2.27)(f). *) +Lemma cfcenter_eq_center (i : Iirr G) : + ('Z('chi_i)%CF / cfker 'chi_i)%g = 'Z(G / cfker 'chi_i)%g. +Proof. +apply/eqP; rewrite eqEsubset; rewrite cfcenter_subset_center ?irr_char //. +apply/subsetP=> _ /setIP[/morphimP[x /= _ Gx ->] cGx]; rewrite mem_quotient //=. +rewrite -irrRepr cfker_repr cfcenter_repr inE Gx in cGx *. +apply: mx_abs_irr_cent_scalar 'Chi_i _ _ _. + by apply: groupC; apply: socle_irr. +have nKG: G \subset 'N(rker 'Chi_i) by exact: rker_norm. +(* GG -- locking here is critical to prevent Coq kernel divergence. *) +apply/centgmxP=> y Gy; rewrite [eq]lock -2?(quo_repr_coset (subxx _) nKG) //. +move: (quo_repr _ _) => rG; rewrite -2?repr_mxM ?mem_quotient // -lock. +by rewrite (centP cGx) // mem_quotient. +Qed. + +(* This is Isaacs (2.28). *) +Lemma cap_cfcenter_irr : \bigcap_i 'Z('chi[G]_i)%CF = 'Z(G). +Proof. +apply/esym/eqP; rewrite eqEsubset (introT bigcapsP) /= => [|i _]; last first. + rewrite -(quotientSGK _ (normal_sub (cfker_center_normal _))). + by rewrite cfcenter_eq_center morphim_center. + by rewrite subIset // normal_norm // cfker_normal. +set Z := \bigcap_i _. +have sZG: Z \subset G by rewrite (bigcap_min 0) ?cfcenter_sub. +rewrite subsetI sZG (sameP commG1P trivgP) -(TI_cfker_irr G). +apply/bigcapsP=> i _; have nKiG := normal_norm (cfker_normal 'chi_i). +rewrite -quotient_cents2 ?(subset_trans sZG) //. +rewrite (subset_trans (quotientS _ (bigcap_inf i _))) //. +by rewrite cfcenter_eq_center subsetIr. +Qed. + +(* This is Isaacs (2.29). *) +Lemma cfnorm_Res_lerif H phi : + H \subset G -> + '['Res[H] phi] <= #|G : H|%:R * '[phi] ?= iff (phi \in 'CF(G, H)). +Proof. +move=> sHG; rewrite cfun_onE mulrCA natf_indexg // -mulrA mulKf ?neq0CG //. +rewrite (big_setID H) (setIidPr sHG) /= addrC. +rewrite (mono_lerif (ler_pmul2l _)) ?invr_gt0 ?gt0CG // -lerif_subLR -sumrB. +rewrite big1 => [|x Hx]; last by rewrite !cfResE ?subrr. +have ->: (support phi \subset H) = (G :\: H \subset [set x | phi x == 0]). + rewrite subDset setUC -subDset; apply: eq_subset => x. + by rewrite !inE (andb_idr (contraR _)) // => /cfun0->. +rewrite (sameP subsetP forall_inP); apply: lerif_0_sum => x _. +by rewrite !inE /<?=%R mul_conjC_ge0 eq_sym mul_conjC_eq0. +Qed. + +(* This is Isaacs (2.30). *) +Lemma irr1_bound (i : Iirr G) : + ('chi_i 1%g) ^+ 2 <= #|G : 'Z('chi_i)%CF|%:R + ?= iff ('chi_i \in 'CF(G, 'Z('chi_i)%CF)). +Proof. +congr (_ <= _ ?= iff _): (cfnorm_Res_lerif 'chi_i (cfcenter_sub 'chi_i)). + have [xi Lxi ->] := cfcenter_Res 'chi_i. + have /irrP[j ->] := lin_char_irr Lxi; rewrite cfdotZl cfdotZr cfdot_irr eqxx. + by rewrite mulr1 irr1_degree conjC_nat. +by rewrite cfdot_irr eqxx mulr1. +Qed. + +(* This is Isaacs (2.31). *) +Lemma irr1_abelian_bound (i : Iirr G) : + abelian (G / 'Z('chi_i)%CF) -> ('chi_i 1%g) ^+ 2 = #|G : 'Z('chi_i)%CF|%:R. +Proof. +move=> AbGc; apply/eqP; rewrite irr1_bound cfun_onE; apply/subsetP=> x nz_chi_x. +have Gx: x \in G by apply: contraR nz_chi_x => /cfun0->. +have nKx := subsetP (normal_norm (cfker_normal 'chi_i)) _ Gx. +rewrite -(quotientGK (cfker_center_normal _)) inE nKx inE /=. +rewrite cfcenter_eq_center inE mem_quotient //=. +apply/centP=> _ /morphimP[y nKy Gy ->]; apply/commgP; rewrite -morphR //=. +set z := [~ x, y]; rewrite coset_id //. +have: z \in 'Z('chi_i)%CF. + apply: subsetP (mem_commg Gx Gy). + by rewrite der1_min // normal_norm ?cfcenter_normal. +rewrite -irrRepr cfker_repr cfcenter_repr !inE in nz_chi_x *. +case/andP=> Gz /is_scalar_mxP[c Chi_z]; rewrite Gz Chi_z mul1mx /=. +apply/eqP; congr _%:M; apply: (mulIf nz_chi_x); rewrite mul1r. +rewrite -{2}(cfunJ _ x Gy) conjg_mulR -/z !cfunE Gx groupM // !{1}mulrb. +by rewrite repr_mxM // Chi_z mul_mx_scalar mxtraceZ. +Qed. + +(* This is Isaacs (2.32)(a). *) +Lemma irr_faithful_center i : cfaithful 'chi[G]_i -> cyclic 'Z(G). +Proof. +rewrite (isog_cyclic (isog_center (quotient1_isog G))) /=. +by move/trivgP <-; rewrite -cfcenter_eq_center cfcenter_cyclic. +Qed. + +Lemma cfcenter_fful_irr i : cfaithful 'chi[G]_i -> 'Z('chi_i)%CF = 'Z(G). +Proof. +move/trivgP=> Ki1; have:= cfcenter_eq_center i; rewrite {}Ki1. +have inj1: 'injm (@coset gT 1%g) by rewrite ker_coset. +by rewrite -injm_center; first apply: injm_morphim_inj; rewrite ?norms1. +Qed. + +(* This is Isaacs (2.32)(b). *) +Lemma pgroup_cyclic_faithful (p : nat) : + p.-group G -> cyclic 'Z(G) -> exists i, cfaithful 'chi[G]_i. +Proof. +pose Z := 'Ohm_1('Z(G)) => pG cycZG; have nilG := pgroup_nil pG. +have [-> | ntG] := eqsVneq G [1]; first by exists 0; exact: cfker_sub. +have{pG} [[p_pr _ _] pZ] := (pgroup_pdiv pG ntG, pgroupS (center_sub G) pG). +have ntZ: 'Z(G) != [1] by rewrite center_nil_eq1. +have{pZ} oZ: #|Z| = p by exact: Ohm1_cyclic_pgroup_prime. +apply/existsP; apply: contraR ntZ; rewrite negb_exists => /forallP-not_ffulG. +rewrite -Ohm1_eq1 -subG1 /= -/Z -(TI_cfker_irr G); apply/bigcapsP=> i _. +rewrite prime_meetG ?oZ // setIC meet_Ohm1 // meet_center_nil ?cfker_normal //. +by rewrite -subG1 not_ffulG. +Qed. + +End Center. + +Section Induced. + +Variables (gT : finGroupType) (G H : {group gT}). +Implicit Types (phi : 'CF(G)) (chi : 'CF(H)). + +Lemma cfInd_char chi : chi \is a character -> 'Ind[G] chi \is a character. +Proof. +move=> Nchi; apply/forallP=> i; rewrite coord_cfdot -Frobenius_reciprocity //. +by rewrite Cnat_cfdot_char ?cfRes_char ?irr_char. +Qed. + +Lemma cfInd_eq0 chi : + H \subset G -> chi \is a character -> ('Ind[G] chi == 0) = (chi == 0). +Proof. +move=> sHG Nchi; rewrite -!(char1_eq0) ?cfInd_char // cfInd1 //. +by rewrite (mulrI_eq0 _ (mulfI _)) ?neq0CiG. +Qed. + +Lemma Ind_irr_neq0 i : H \subset G -> 'Ind[G, H] 'chi_i != 0. +Proof. by move/cfInd_eq0->; rewrite ?irr_neq0 ?irr_char. Qed. + +Definition Ind_Iirr (A B : {set gT}) i := cfIirr ('Ind[B, A] 'chi_i). + +Lemma constt_cfRes_irr i : {j | j \in irr_constt ('Res[H, G] 'chi_i)}. +Proof. apply/sigW/neq0_has_constt/Res_irr_neq0. Qed. + +Lemma constt_cfInd_irr i : + H \subset G -> {j | j \in irr_constt ('Ind[G, H] 'chi_i)}. +Proof. by move=> sHG; apply/sigW/neq0_has_constt/Ind_irr_neq0. Qed. + +Lemma cfker_Res phi : + H \subset G -> phi \is a character -> cfker ('Res[H] phi) = H :&: cfker phi. +Proof. +move=> sHG Nphi; apply/setP=> x; rewrite !cfkerEchar ?cfRes_char // !inE. +by apply/andb_id2l=> Hx; rewrite (subsetP sHG) ?cfResE. +Qed. + +(* This is Isaacs Lemma (5.11). *) +Lemma cfker_Ind chi : + H \subset G -> chi \is a character -> chi != 0 -> + cfker ('Ind[G, H] chi) = gcore (cfker chi) G. +Proof. +move=> sHG Nchi nzchi; rewrite !cfker_nzcharE ?cfInd_char ?cfInd_eq0 //. +apply/setP=> x; rewrite inE cfIndE // (can2_eq (mulVKf _) (mulKf _)) ?neq0CG //. +rewrite cfInd1 // mulrA -natrM Lagrange // mulr_natl -sumr_const. +apply/eqP/bigcapP=> [/normC_sum_upper ker_chiG_x y Gy | ker_chiG_x]. + by rewrite mem_conjg inE ker_chiG_x ?groupV // => z _; exact: char1_ge_norm. +by apply: eq_bigr => y /groupVr/ker_chiG_x; rewrite mem_conjgV inE => /eqP. +Qed. + +Lemma cfker_Ind_irr i : + H \subset G -> cfker ('Ind[G, H] 'chi_i) = gcore (cfker 'chi_i) G. +Proof. by move/cfker_Ind->; rewrite ?irr_neq0 ?irr_char. Qed. + +End Induced. + +Arguments Scope Ind_Iirr [_ group_scope group_scope ring_scope].
\ No newline at end of file |
