l3lab/ntp-mathlib huggingface dataset:
theorem iff_card [Fact p.Prime] [Fintype G] : IsPGroup p G ↔ ∃ n : ℕ, card G = p ^ n := by
  have hG : card G ≠ 0 := card_ne_zero
  refine' ⟨fun h => _, fun ⟨n, hn⟩ => of_card hn⟩
  suffices ∀ q ∈ Nat.factors (card G), q = p by
    use (card G).factors.length
    rw [← List.prod_replicate, ← List.eq_replicate_of_mem this, Nat.prod_factors hG]
  intro q hq
  obtain ⟨hq1, hq2⟩ := (Nat.mem_factors hG).mp hq
  haveI : Fact q.Prime := ⟨hq1⟩
  obtain ⟨g, hg⟩ := exists_prime_orderOf_dvd_card q hq2
  obtain ⟨k, hk⟩ := (iff_orderOf.mp h) g
  

Proof state:
case intro.intro.intro
p : ℕ
G : Type u_1
inst✝² : Group G
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fintype G
hG : card G ≠ 0
h : IsPGroup p G
q : ℕ
hq : q ∈ Nat.factors (card G)
hq1 : Nat.Prime q
hq2 : q ∣ card G
this : Fact (Nat.Prime q)
g : G
hg : orderOf g = q
k : ℕ
hk : orderOf g = p ^ k
⊢ q = p

Next tactic:
exact (hq1.pow_eq_iff.mp (hg.symm.trans hk).symm).1.symm
theorem of_injective {H : Type*} [Group H] (ϕ : H →* G) (hϕ : Function.Injective ϕ) :
    IsPGroup p H := by
  

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
H : Type u_2
inst✝ : Group H
ϕ : H →* G
hϕ : Function.Injective ⇑ϕ
⊢ IsPGroup p H

Next tactic:
simp_rw [IsPGroup, ← hϕ.eq_iff, ϕ.map_pow, ϕ.map_one]
theorem of_injective {H : Type*} [Group H] (ϕ : H →* G) (hϕ : Function.Injective ϕ) :
    IsPGroup p H := by
  simp_rw [IsPGroup, ← hϕ.eq_iff, ϕ.map_pow, ϕ.map_one]
  

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
H : Type u_2
inst✝ : Group H
ϕ : H →* G
hϕ : Function.Injective ⇑ϕ
⊢ ∀ (g : H), ∃ k, ϕ g ^ p ^ k = 1

Next tactic:
exact fun h => hG (ϕ h)
theorem of_surjective {H : Type*} [Group H] (ϕ : G →* H) (hϕ : Function.Surjective ϕ) :
    IsPGroup p H := by
  

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
H : Type u_2
inst✝ : Group H
ϕ : G →* H
hϕ : Function.Surjective ⇑ϕ
⊢ IsPGroup p H

Next tactic:
refine' fun h => Exists.elim (hϕ h) fun g hg => Exists.imp (fun k hk => _) (hG g)
theorem of_surjective {H : Type*} [Group H] (ϕ : G →* H) (hϕ : Function.Surjective ϕ) :
    IsPGroup p H := by
  refine' fun h => Exists.elim (hϕ h) fun g hg => Exists.imp (fun k hk => _) (hG g)
  

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
H : Type u_2
inst✝ : Group H
ϕ : G →* H
hϕ : Function.Surjective ⇑ϕ
h : H
g : G
hg : ϕ g = h
k : ℕ
hk : g ^ p ^ k = 1
⊢ h ^ p ^ k = 1

Next tactic:
rw [← hg, ← ϕ.map_pow, hk, ϕ.map_one]
@[simp]
theorem powEquiv_symm_apply {n : ℕ} (hn : p.Coprime n) (g : G) :
    (hG.powEquiv hn).symm g = g ^ (orderOf g).gcdB n := by 

Proof state:
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
n : ℕ
hn : Nat.Coprime p n
g : G
⊢ (powEquiv hG hn).symm g = g ^ Nat.gcdB (orderOf g) n

Next tactic:
rw [← Nat.card_zpowers]
@[simp]
theorem powEquiv_symm_apply {n : ℕ} (hn : p.Coprime n) (g : G) :
    (hG.powEquiv hn).symm g = g ^ (orderOf g).gcdB n := by rw [← Nat.card_zpowers]; 

Proof state:
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
n : ℕ
hn : Nat.Coprime p n
g : G
⊢ (powEquiv hG hn).symm g = g ^ Nat.gcdB (Nat.card ↥(Subgroup.zpowers g)) n

Next tactic:
rfl
theorem index (H : Subgroup G) [H.FiniteIndex] : ∃ n : ℕ, H.index = p ^ n := by
  

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
H : Subgroup G
inst✝ : Subgroup.FiniteIndex H
⊢ ∃ n, Subgroup.index H = p ^ n

Next tactic:
haveI := H.normalCore.fintypeQuotientOfFiniteIndex
theorem index (H : Subgroup G) [H.FiniteIndex] : ∃ n : ℕ, H.index = p ^ n := by
  haveI := H.normalCore.fintypeQuotientOfFiniteIndex
  

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
H : Subgroup G
inst✝ : Subgroup.FiniteIndex H
this : Fintype (G ⧸ Subgroup.normalCore H)
⊢ ∃ n, Subgroup.index H = p ^ n

Next tactic:
obtain ⟨n, hn⟩ := iff_card.mp (hG.to_quotient H.normalCore)
theorem index (H : Subgroup G) [H.FiniteIndex] : ∃ n : ℕ, H.index = p ^ n := by
  haveI := H.normalCore.fintypeQuotientOfFiniteIndex
  obtain ⟨n, hn⟩ := iff_card.mp (hG.to_quotient H.normalCore)
  

Proof state:
case intro
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
H : Subgroup G
inst✝ : Subgroup.FiniteIndex H
this : Fintype (G ⧸ Subgroup.normalCore H)
n : ℕ
hn : card (G ⧸ Subgroup.normalCore H) = p ^ n
⊢ ∃ n, Subgroup.index H = p ^ n

Next tactic:
obtain ⟨k, _, hk2⟩ :=
    (Nat.dvd_prime_pow hp.out).mp
      ((congr_arg _ (H.normalCore.index_eq_card.trans hn)).mp
        (Subgroup.index_dvd_of_le H.normalCore_le))
theorem index (H : Subgroup G) [H.FiniteIndex] : ∃ n : ℕ, H.index = p ^ n := by
  haveI := H.normalCore.fintypeQuotientOfFiniteIndex
  obtain ⟨n, hn⟩ := iff_card.mp (hG.to_quotient H.normalCore)
  obtain ⟨k, _, hk2⟩ :=
    (Nat.dvd_prime_pow hp.out).mp
      ((congr_arg _ (H.normalCore.index_eq_card.trans hn)).mp
        (Subgroup.index_dvd_of_le H.normalCore_le))
  

Proof state:
case intro.intro.intro
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
H : Subgroup G
inst✝ : Subgroup.FiniteIndex H
this : Fintype (G ⧸ Subgroup.normalCore H)
n : ℕ
hn : card (G ⧸ Subgroup.normalCore H) = p ^ n
k : ℕ
left✝ : k ≤ n
hk2 : Subgroup.index H = p ^ k
⊢ ∃ n, Subgroup.index H = p ^ n

Next tactic:
exact ⟨k, hk2⟩
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  

Proof state:
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
⊢ Nat.card G = 1 ∨ p ∣ Nat.card G

Next tactic:
cases fintypeOrInfinite G
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · 

Proof state:
case inl
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Fintype G
⊢ Nat.card G = 1 ∨ p ∣ Nat.card G

Next tactic:
obtain ⟨n, hn⟩ := iff_card.mp hG
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    

Proof state:
case inl.intro
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Fintype G
n : ℕ
hn : card G = p ^ n
⊢ Nat.card G = 1 ∨ p ∣ Nat.card G

Next tactic:
rw [Nat.card_eq_fintype_card, hn]
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    rw [Nat.card_eq_fintype_card, hn]
    

Proof state:
case inl.intro
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Fintype G
n : ℕ
hn : card G = p ^ n
⊢ p ^ n = 1 ∨ p ∣ p ^ n

Next tactic:
cases' n with n n
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    rw [Nat.card_eq_fintype_card, hn]
    cases' n with n n
    · 

Proof state:
case inl.intro.zero
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Fintype G
hn : card G = p ^ Nat.zero
⊢ p ^ Nat.zero = 1 ∨ p ∣ p ^ Nat.zero

Next tactic:
exact Or.inl rfl
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    rw [Nat.card_eq_fintype_card, hn]
    cases' n with n n
    · exact Or.inl rfl
    · 

Proof state:
case inl.intro.succ
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Fintype G
n : ℕ
hn : card G = p ^ Nat.succ n
⊢ p ^ Nat.succ n = 1 ∨ p ∣ p ^ Nat.succ n

Next tactic:
exact Or.inr ⟨p ^ n, by rw [pow_succ]⟩
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    rw [Nat.card_eq_fintype_card, hn]
    cases' n with n n
    · exact Or.inl rfl
    · exact Or.inr ⟨p ^ n, by 

Proof state:
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Fintype G
n : ℕ
hn : card G = p ^ Nat.succ n
⊢ p ^ Nat.succ n = p * p ^ n

Next tactic:
rw [pow_succ]
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    rw [Nat.card_eq_fintype_card, hn]
    cases' n with n n
    · exact Or.inl rfl
    · exact Or.inr ⟨p ^ n, by rw [pow_succ]⟩
  · 

Proof state:
case inr
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Infinite G
⊢ Nat.card G = 1 ∨ p ∣ Nat.card G

Next tactic:
rw [Nat.card_eq_zero_of_infinite]
theorem card_eq_or_dvd : Nat.card G = 1 ∨ p ∣ Nat.card G := by
  cases fintypeOrInfinite G
  · obtain ⟨n, hn⟩ := iff_card.mp hG
    rw [Nat.card_eq_fintype_card, hn]
    cases' n with n n
    · exact Or.inl rfl
    · exact Or.inr ⟨p ^ n, by rw [pow_succ]⟩
  · rw [Nat.card_eq_zero_of_infinite]
    

Proof state:
case inr
p : ℕ
G : Type u_1
inst✝ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
val✝ : Infinite G
⊢ 0 = 1 ∨ p ∣ 0

Next tactic:
exact Or.inr ⟨0, rfl⟩
theorem nontrivial_iff_card [Fintype G] : Nontrivial G ↔ ∃ n > 0, card G = p ^ n :=
  ⟨fun hGnt =>
    let ⟨k, hk⟩ := iff_card.1 hG
    ⟨k,
      Nat.pos_of_ne_zero fun hk0 => by
        

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
inst✝ : Fintype G
hGnt : Nontrivial G
k : ℕ
hk : card G = p ^ k
hk0 : k = 0
⊢ False

Next tactic:
rw [hk0, pow_zero] at hk
theorem nontrivial_iff_card [Fintype G] : Nontrivial G ↔ ∃ n > 0, card G = p ^ n :=
  ⟨fun hGnt =>
    let ⟨k, hk⟩ := iff_card.1 hG
    ⟨k,
      Nat.pos_of_ne_zero fun hk0 => by
        rw [hk0, pow_zero] at hk; 

Proof state:
p : ℕ
G : Type u_1
inst✝¹ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
inst✝ : Fintype G
hGnt : Nontrivial G
k : ℕ
hk : card G = 1
hk0 : k = 0
⊢ False

Next tactic:
exact Fintype.one_lt_card.ne' hk
theorem card_orbit (a : α) [Fintype (orbit G a)] : ∃ n : ℕ, card (orbit G a) = p ^ n := by
  

Proof state:
p : ℕ
G : Type u_1
inst✝² : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝¹ : MulAction G α
a : α
inst✝ : Fintype ↑(orbit G a)
⊢ ∃ n, card ↑(orbit G a) = p ^ n

Next tactic:
let ϕ := orbitEquivQuotientStabilizer G a
theorem card_orbit (a : α) [Fintype (orbit G a)] : ∃ n : ℕ, card (orbit G a) = p ^ n := by
  let ϕ := orbitEquivQuotientStabilizer G a
  

Proof state:
p : ℕ
G : Type u_1
inst✝² : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝¹ : MulAction G α
a : α
inst✝ : Fintype ↑(orbit G a)
ϕ : ↑(orbit G a) ≃ G ⧸ stabilizer G a := orbitEquivQuotientStabilizer G a
⊢ ∃ n, card ↑(orbit G a) = p ^ n

Next tactic:
haveI := Fintype.ofEquiv (orbit G a) ϕ
theorem card_orbit (a : α) [Fintype (orbit G a)] : ∃ n : ℕ, card (orbit G a) = p ^ n := by
  let ϕ := orbitEquivQuotientStabilizer G a
  haveI := Fintype.ofEquiv (orbit G a) ϕ
  

Proof state:
p : ℕ
G : Type u_1
inst✝² : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝¹ : MulAction G α
a : α
inst✝ : Fintype ↑(orbit G a)
ϕ : ↑(orbit G a) ≃ G ⧸ stabilizer G a := orbitEquivQuotientStabilizer G a
this : Fintype (G ⧸ stabilizer G a)
⊢ ∃ n, card ↑(orbit G a) = p ^ n

Next tactic:
haveI := (stabilizer G a).finiteIndex_of_finite_quotient
theorem card_orbit (a : α) [Fintype (orbit G a)] : ∃ n : ℕ, card (orbit G a) = p ^ n := by
  let ϕ := orbitEquivQuotientStabilizer G a
  haveI := Fintype.ofEquiv (orbit G a) ϕ
  haveI := (stabilizer G a).finiteIndex_of_finite_quotient
  

Proof state:
p : ℕ
G : Type u_1
inst✝² : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝¹ : MulAction G α
a : α
inst✝ : Fintype ↑(orbit G a)
ϕ : ↑(orbit G a) ≃ G ⧸ stabilizer G a := orbitEquivQuotientStabilizer G a
this✝ : Fintype (G ⧸ stabilizer G a)
this : Subgroup.FiniteIndex (stabilizer G a)
⊢ ∃ n, card ↑(orbit G a) = p ^ n

Next tactic:
rw [card_congr ϕ, ← Subgroup.index_eq_card]
theorem card_orbit (a : α) [Fintype (orbit G a)] : ∃ n : ℕ, card (orbit G a) = p ^ n := by
  let ϕ := orbitEquivQuotientStabilizer G a
  haveI := Fintype.ofEquiv (orbit G a) ϕ
  haveI := (stabilizer G a).finiteIndex_of_finite_quotient
  rw [card_congr ϕ, ← Subgroup.index_eq_card]
  

Proof state:
p : ℕ
G : Type u_1
inst✝² : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝¹ : MulAction G α
a : α
inst✝ : Fintype ↑(orbit G a)
ϕ : ↑(orbit G a) ≃ G ⧸ stabilizer G a := orbitEquivQuotientStabilizer G a
this✝ : Fintype (G ⧸ stabilizer G a)
this : Subgroup.FiniteIndex (stabilizer G a)
⊢ ∃ n, Subgroup.index (stabilizer G a) = p ^ n

Next tactic:
exact hG.index (stabilizer G a)
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
⊢ card α ≡ card ↑(fixedPoints G α) [MOD p]

Next tactic:
classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
    rw [← ZMod.eq_iff_modEq_nat p, Nat.cast_sum, Nat.cast_sum]
    have key :
      ∀ x,
        card { y // (Quotient.mk'' y : Quotient (orbitRel G α)) = Quotient.mk'' x } =
          card (orbit G x) :=
      fun x => by simp only [Quotient.eq'']; congr
    refine'
      Eq.symm
        (Finset.sum_bij_ne_zero (fun a _ _ => Quotient.mk'' a.1) (fun _ _ _ => Finset.mem_univ _)
          (fun a₁ a₂ _ _ _ _ h =>
            Subtype.eq (mem_fixedPoints'.mp a₂.2 a₁.1 (Quotient.exact' h)))
          (fun b => Quotient.inductionOn' b fun b _ hb => _) fun a ha _ => by
          rw [key, mem_fixedPoints_iff_card_orbit_eq_one.mp a.2])
    obtain ⟨k, hk⟩ := hG.card_orbit b
    have : k = 0 :=
      le_zero_iff.1
        (Nat.le_of_lt_succ
          (lt_of_not_ge
            (mt (pow_dvd_pow p)
              (by
                rwa [pow_one, ← hk, ← Nat.modEq_zero_iff_dvd, ← ZMod.eq_iff_modEq_nat, ← key,
                  Nat.cast_zero]))))
    exact
      ⟨⟨b, mem_fixedPoints_iff_card_orbit_eq_one.2 <| by rw [hk, this, pow_zero]⟩,
        Finset.mem_univ _, ne_of_eq_of_ne Nat.cast_one one_ne_zero, rfl⟩
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
⊢ card α ≡ card ↑(fixedPoints G α) [MOD p]

Next tactic:
calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by 

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
⊢ ∑ _a : ↑(fixedPoints G α), 1 = card ↑(fixedPoints G α)

Next tactic:
simp
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; 

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
⊢ Finset.card Finset.univ = card ↑(fixedPoints G α)

Next tactic:
rfl
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
    

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
⊢ ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } ≡ ∑ _a : ↑(fixedPoints G α), 1 [MOD p]

Next tactic:
rw [← ZMod.eq_iff_modEq_nat p, Nat.cast_sum, Nat.cast_sum]
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
    rw [← ZMod.eq_iff_modEq_nat p, Nat.cast_sum, Nat.cast_sum]
    

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
⊢ ∑ x : Quotient (orbitRel G α), ↑(card { x_1 // Quotient.mk'' x_1 = x }) = ∑ x : ↑(fixedPoints G α), ↑1

Next tactic:
have key :
      ∀ x,
        card { y // (Quotient.mk'' y : Quotient (orbitRel G α)) = Quotient.mk'' x } =
          card (orbit G x) :=
      fun x => by simp only [Quotient.eq'']; congr
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
    rw [← ZMod.eq_iff_modEq_nat p, Nat.cast_sum, Nat.cast_sum]
    have key :
      ∀ x,
        card { y // (Quotient.mk'' y : Quotient (orbitRel G α)) = Quotient.mk'' x } =
          card (orbit G x) :=
      fun x => by 

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
x : α
⊢ card { y // Quotient.mk'' y = Quotient.mk'' x } = card ↑(orbit G x)

Next tactic:
simp only [Quotient.eq'']
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
    rw [← ZMod.eq_iff_modEq_nat p, Nat.cast_sum, Nat.cast_sum]
    have key :
      ∀ x,
        card { y // (Quotient.mk'' y : Quotient (orbitRel G α)) = Quotient.mk'' x } =
          card (orbit G x) :=
      fun x => by simp only [Quotient.eq'']; 

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
x : α
⊢ card { y // Setoid.r y x } = card ↑(orbit G x)

Next tactic:
congr
/-- If `G` is a `p`-group acting on a finite set `α`, then the number of fixed points
  of the action is congruent mod `p` to the cardinality of `α` -/
theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
    card α ≡ card (fixedPoints G α) [MOD p] := by
  classical
    calc
      card α = card (Σy : Quotient (orbitRel G α), { x // Quotient.mk'' x = y }) :=
        card_congr (Equiv.sigmaFiberEquiv (@Quotient.mk'' _ (orbitRel G α))).symm
      _ = ∑ a : Quotient (orbitRel G α), card { x // Quotient.mk'' x = a } := (card_sigma _)
      _ ≡ ∑ _a : fixedPoints G α, 1 [MOD p] := ?_
      _ = _ := by simp; rfl
    rw [← ZMod.eq_iff_modEq_nat p, Nat.cast_sum, Nat.cast_sum]
    have key :
      ∀ x,
        card { y // (Quotient.mk'' y : Quotient (orbitRel G α)) = Quotient.mk'' x } =
          card (orbit G x) :=
      fun x => by simp only [Quotient.eq'']; congr
    

Proof state:
p : ℕ
G : Type u_1
inst✝³ : Group G
hG : IsPGroup p G
hp : Fact (Nat.Prime p)
α : Type u_2
inst✝² : MulAction G α
inst✝¹ : Fintype α
inst✝ : Fintype ↑(fixedPoints G α)
key : ∀ (x : α), card { y // Quotient.mk'' y = Quotient.mk'' x } = card ↑(orbit G x)
⊢ ∑ x : Quotient (orbitRel G α), ↑(card { x_1 // Quotient.mk'' x_1 = x }) = ∑ x : ↑(fixedPoints G α), ↑1

Next tactic:
refine'
      Eq.symm
        (Finset.sum_bij_ne_zero (fun a _ _ => Quotient.mk'' a.1) (fun _ _ _ => Finset.mem_univ _)
          (fun a₁ a₂ _ _ _ _ h =>
            Subtype.eq (mem_fixedPoints'.mp a₂.2 a₁.1 (Quotient.exact' h)))
          (fun b => Quotient.inductionOn' b fun b _ hb => _) fun a ha _ => by
          rw [key, mem_fixedPoints_iff_card_orbit_eq_one.mp a.2])