Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: More big operator lemmas #10551

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
203e465
feat: More big operator lemmas
YaelDillies Feb 14, 2024
2ac4370
Update Mathlib/Algebra/BigOperators/Basic.lean
YaelDillies Feb 14, 2024
af812f7
Update Mathlib/Algebra/BigOperators/Pi.lean
YaelDillies Feb 14, 2024
479cec9
Update Mathlib/Algebra/BigOperators/Pi.lean
YaelDillies Feb 14, 2024
2c75941
`Pi.mulSingle` lemmas
YaelDillies Feb 14, 2024
3eaeafb
nolint
YaelDillies Feb 14, 2024
d5ef523
explain simpNF false positive
YaelDillies Feb 14, 2024
88bbd97
extra lemma
YaelDillies Feb 16, 2024
56cde85
fix Algebra.Module.BigOperators
YaelDillies Feb 16, 2024
73ff1da
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Feb 26, 2024
13c38c8
see also
YaelDillies Feb 26, 2024
e066895
rewrap
YaelDillies Feb 26, 2024
90b3a7b
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Mar 7, 2024
85551a4
extract a lemma
YaelDillies Mar 7, 2024
347a01a
fix
YaelDillies Mar 7, 2024
447f9e0
fix GroupTheory.PGroup
YaelDillies Mar 8, 2024
69f27dd
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Mar 21, 2024
dc3bc75
prod_subset
YaelDillies Mar 21, 2024
d5994a1
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Mar 30, 2024
4cea4a7
Eric's rw
YaelDillies Mar 30, 2024
ded7555
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Apr 5, 2024
5c55001
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Apr 15, 2024
3c2fe13
fix GroupTheory.PGroup
YaelDillies Apr 17, 2024
f650b66
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Apr 29, 2024
748d331
missing newline
YaelDillies Apr 29, 2024
dff0434
Merge remote-tracking branch 'origin/master' into prod_fiberwise_eq_p…
YaelDillies Apr 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 84 additions & 1 deletion Mathlib/Algebra/BigOperators/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,19 @@ lemma prod_of_injOn (e : ι → κ) (he : Set.InjOn e s) (hest : Set.MapsTo e s

variable [DecidableEq κ]

@[to_additive]
lemma prod_fiberwise_eq_prod_filter (s : Finset ι) (t : Finset κ) (g : ι → κ) (f : ι → α) :
∏ j in t, ∏ i in s.filter fun i ↦ g i = j, f i = ∏ i in s.filter fun i ↦ g i ∈ t, f i := by
rw [← prod_disjiUnion, disjiUnion_filter_eq]

@[to_additive]
lemma prod_fiberwise_eq_prod_filter' (s : Finset ι) (t : Finset κ) (g : ι → κ) (f : κ → α) :
∏ j in t, ∏ _i in s.filter fun i ↦ g i = j, f j = ∏ i in s.filter fun i ↦ g i ∈ t, f (g i) := by
calc
_ = ∏ j in t, ∏ i in s.filter fun i ↦ g i = j, f (g i) :=
prod_congr rfl fun j _ ↦ prod_congr rfl fun i hi ↦ by rw [(mem_filter.1 hi).2]
_ = _ := prod_fiberwise_eq_prod_filter _ _ _ _

@[to_additive]
lemma prod_fiberwise_of_maps_to {g : ι → κ} (h : ∀ i ∈ s, g i ∈ t) (f : ι → α) :
∏ j in t, ∏ i in s.filter fun i ↦ g i = j, f i = ∏ i in s, f i := by
Expand Down Expand Up @@ -1945,6 +1958,23 @@ theorem prod_dvd_prod_of_subset {ι M : Type*} [CommMonoid M] (s t : Finset ι)

end CommMonoid

section CancelCommMonoid
variable [DecidableEq ι] [CancelCommMonoid α] {s t : Finset ι} {f : ι → α}

@[to_additive]
lemma prod_sdiff_eq_prod_sdiff_iff :
∏ i in s \ t, f i = ∏ i in t \ s, f i ↔ ∏ i in s, f i = ∏ i in t, f i :=
eq_comm.trans $ eq_iff_eq_of_mul_eq_mul $ by
rw [← prod_union disjoint_sdiff_self_left, ← prod_union disjoint_sdiff_self_left,
sdiff_union_self_eq_union, sdiff_union_self_eq_union, union_comm]

@[to_additive]
lemma prod_sdiff_ne_prod_sdiff_iff :
∏ i in s \ t, f i ≠ ∏ i in t \ s, f i ↔ ∏ i in s, f i ≠ ∏ i in t, f i :=
prod_sdiff_eq_prod_sdiff_iff.not

end CancelCommMonoid

theorem card_eq_sum_ones (s : Finset α) : s.card = ∑ x in s, 1 := by
rw [sum_const, smul_eq_mul, mul_one]
#align finset.card_eq_sum_ones Finset.card_eq_sum_ones
Expand All @@ -1955,6 +1985,10 @@ theorem sum_const_nat {m : ℕ} {f : α → ℕ} (h₁ : ∀ x ∈ s, f x = m) :
apply sum_congr rfl h₁
#align finset.sum_const_nat Finset.sum_const_nat

lemma sum_card_fiberwise_eq_card_filter {κ : Type*} [DecidableEq κ] (s : Finset ι) (t : Finset κ)
(g : ι → κ) : ∑ j in t, (s.filter fun i ↦ g i = j).card = (s.filter fun i ↦ g i ∈ t).card := by
simpa only [card_eq_sum_ones] using sum_fiberwise_eq_sum_filter _ _ _ _

lemma card_filter (p) [DecidablePred p] (s : Finset α) :
(filter p s).card = ∑ a in s, ite (p a) 1 0 := by
rw [sum_ite, sum_const_zero, add_zero, sum_const, smul_eq_mul, mul_one]
Expand Down Expand Up @@ -2156,10 +2190,13 @@ theorem prod_int_mod (s : Finset α) (n : ℤ) (f : α → ℤ) :
end Finset

namespace Fintype
variable {ι κ α : Type*} [Fintype ι] [Fintype κ] [CommMonoid α]
variable {ι κ α : Type*} [Fintype ι] [Fintype κ]

open Finset

section CommMonoid
variable [CommMonoid α]

/-- `Fintype.prod_bijective` is a variant of `Finset.prod_bij` that accepts `Function.Bijective`.

See `Function.Bijective.prod_comp` for a version without `h`. -/
Expand Down Expand Up @@ -2256,6 +2293,52 @@ theorem prod_subtype_mul_prod_subtype {α β : Type*} [Fintype α] [CommMonoid
#align fintype.prod_subtype_mul_prod_subtype Fintype.prod_subtype_mul_prod_subtype
#align fintype.sum_subtype_add_sum_subtype Fintype.sum_subtype_add_sum_subtype

@[to_additive] lemma prod_subset {s : Finset ι} {f : ι → α} (h : ∀ i, f i ≠ 1 → i ∈ s) :
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to match x ∉ s₁ → f x = 1 from Finset.prod_subset?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's much more useful this way, I find, as it can be interpreted as saying that the support of f is a subset of s. Finset.prod_subset can't really afford to be stated like that as it instead wants to emphasize s₁ \ s₂.

∏ i in s, f i = ∏ i, f i :=
Finset.prod_subset s.subset_univ $ by simpa [not_imp_comm (a := _ ∈ s)]

@[to_additive]
lemma prod_ite_eq_ite_exists (p : ι → Prop) [DecidablePred p] (h : ∀ i j, p i → p j → i = j)
(a : α) : ∏ i, ite (p i) a 1 = ite (∃ i, p i) a 1 := by
simp [prod_ite_one univ p (by simpa using h)]

variable [DecidableEq ι]

/-- See also `Finset.prod_dite_eq`. -/
@[to_additive "See also `Finset.sum_dite_eq`."] lemma prod_dite_eq (i : ι) (f : ∀ j, i = j → α) :
∏ j, (if h : i = j then f j h else 1) = f i rfl := by
rw [Finset.prod_dite_eq, if_pos (mem_univ _)]

/-- See also `Finset.prod_dite_eq'`. -/
@[to_additive "See also `Finset.sum_dite_eq'`."] lemma prod_dite_eq' (i : ι) (f : ∀ j, j = i → α) :
∏ j, (if h : j = i then f j h else 1) = f i rfl := by
rw [Finset.prod_dite_eq', if_pos (mem_univ _)]

/-- See also `Finset.prod_ite_eq`. -/
@[to_additive "See also `Finset.sum_ite_eq`."]
lemma prod_ite_eq (i : ι) (f : ι → α) : ∏ j, (if i = j then f j else 1) = f i := by
rw [Finset.prod_ite_eq, if_pos (mem_univ _)]

/-- See also `Finset.prod_ite_eq'`. -/
@[to_additive "See also `Finset.sum_ite_eq'`."]
lemma prod_ite_eq' (i : ι) (f : ι → α) : ∏ j, (if j = i then f j else 1) = f i := by
rw [Finset.prod_ite_eq', if_pos (mem_univ _)]

/-- See also `Finset.prod_pi_mulSingle`. -/
@[to_additive "See also `Finset.sum_pi_single`."]
lemma prod_pi_mulSingle {α : ι → Type*} [∀ i, CommMonoid (α i)] (i : ι) (f : ∀ i, α i) :
∏ j, Pi.mulSingle j (f j) i = f i := prod_dite_eq _ _

/-- See also `Finset.prod_pi_mulSingle'`. -/
@[to_additive "See also `Finset.sum_pi_single'`."]
lemma prod_pi_mulSingle' (i : ι) (a : α) : ∏ j, Pi.mulSingle i a j = a := prod_dite_eq' _ _

end CommMonoid

variable [CommMonoidWithZero α] {p : ι → Prop} [DecidablePred p]

lemma prod_boole : ∏ i, ite (p i) (1 : α) 0 = ite (∀ i, p i) 1 0 := by simp [Finset.prod_boole]

end Fintype

namespace Finset
Expand Down
28 changes: 26 additions & 2 deletions Mathlib/Algebra/BigOperators/Ring.lean
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,11 @@ lemma prod_univ_sum [Fintype ι] (t : ∀ i, Finset (κ i)) (f : ∀ i, κ i →

lemma sum_prod_piFinset {κ : Type*} [Fintype ι] (s : Finset κ) (g : ι → κ → α) :
∑ f in piFinset fun _ : ι ↦ s, ∏ i, g i (f i) = ∏ i, ∑ j in s, g i j := by
classical rw [← prod_univ_sum]
rw [← prod_univ_sum]

lemma sum_pow' (s : Finset ι) (f : ι → α) (n : ℕ) :
(∑ a in s, f a) ^ n = ∑ p in piFinset fun _i : Fin n ↦ s, ∏ i, f (p i) := by
classical convert @prod_univ_sum (Fin n) _ _ _ _ _ (fun _i ↦ s) fun _i d ↦ f d; simp
convert @prod_univ_sum (Fin n) _ _ _ _ _ (fun _i ↦ s) fun _i d ↦ f d; simp

/-- The product of `f a + g a` over all of `s` is the sum over the powerset of `s` of the product of
`f` over a subset `t` times the product of `g` over the complement of `t` -/
Expand Down Expand Up @@ -297,7 +297,31 @@ lemma sum_div (s : Finset ι) (f : ι → α) (a : α) :
end DivisionSemiring
end Finset

open Finset

namespace Fintype
variable {ι κ α : Type*} [DecidableEq ι] [Fintype ι] [Fintype κ] [CommSemiring α]

lemma sum_pow (f : ι → α) (n : ℕ) : (∑ a, f a) ^ n = ∑ p : Fin n → ι, ∏ i, f (p i) := by
simp [sum_pow']

lemma sum_mul_sum (f : ι → α) (g : κ → α) : (∑ i, f i) * ∑ j, g j = ∑ i, ∑ j, f i * g j :=
Finset.sum_mul_sum _ _ _ _

lemma prod_add (f g : ι → α) : ∏ a, (f a + g a) = ∑ t, (∏ a in t, f a) * ∏ a in tᶜ, g a := by
simpa [compl_eq_univ_sdiff] using Finset.prod_add f g univ

end Fintype

namespace Nat
variable {ι : Type*} {s : Finset ι} {f : ι → ℕ} {n : ℕ}

protected lemma sum_div (hf : ∀ i ∈ s, n ∣ f i) : (∑ i in s, f i) / n = ∑ i in s, f i / n := by
obtain rfl | hn := n.eq_zero_or_pos
· simp
rw [Nat.div_eq_iff_eq_mul_left hn (dvd_sum hf), sum_mul]
refine' sum_congr rfl fun s hs ↦ _
rw [Nat.div_mul_cancel (hf _ hs)]

@[simp, norm_cast]
lemma cast_list_sum [AddMonoidWithOne β] (s : List ℕ) : (↑s.sum : β) = (s.map (↑)).sum :=
Expand Down
17 changes: 16 additions & 1 deletion Mathlib/Algebra/Module/BigOperators.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes, Yury Kudryashov, Yaël Dillies
-/
import Mathlib.Algebra.Module.Basic
import Mathlib.Data.Fintype.BigOperators
import Mathlib.GroupTheory.GroupAction.BigOperators

#align_import algebra.module.big_operators from "leanprover-community/mathlib"@"509de852e1de55e1efa8eacfa11df0823f26f226"
Expand All @@ -14,7 +15,7 @@ import Mathlib.GroupTheory.GroupAction.BigOperators

open BigOperators

variable {α β R M ι : Type*}
variable {ι κ α β R M : Type*}

section AddCommMonoid

Expand Down Expand Up @@ -51,3 +52,17 @@ end AddCommMonoid
theorem Finset.cast_card [CommSemiring R] (s : Finset α) : (s.card : R) = ∑ a in s, 1 := by
rw [Finset.sum_const, Nat.smul_one_eq_coe]
#align finset.cast_card Finset.cast_card

open Finset

namespace Fintype
variable [DecidableEq ι] [Fintype ι] [AddCommMonoid α]

lemma sum_piFinset_apply (f : κ → α) (s : Finset κ) (i : ι) :
∑ g in piFinset fun _ : ι ↦ s, f (g i) = s.card ^ (card ι - 1) • ∑ b in s, f b := by
classical
rw [Finset.sum_comp]
simp only [eval_image_piFinset_const, card_filter_piFinset_const s, ite_smul, zero_smul, smul_sum,
sum_ite_mem, inter_self]

end Fintype
2 changes: 1 addition & 1 deletion Mathlib/Data/Finset/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2631,7 +2631,7 @@ theorem filter_False {h} (s : Finset α) : @filter _ (fun _ => False) h s = ∅

variable {p q}

theorem filter_eq_self : s.filter p = s ↔ ∀ x ∈ s, p x := by simp [Finset.ext_iff]
@[simp] lemma filter_eq_self : s.filter p = s ↔ ∀ x ∈ s, p x := by simp [Finset.ext_iff]
#align finset.filter_eq_self Finset.filter_eq_self

theorem filter_eq_empty_iff : s.filter p = ∅ ↔ ∀ ⦃x⦄, x ∈ s → ¬p x := by simp [Finset.ext_iff]
Expand Down
21 changes: 13 additions & 8 deletions Mathlib/Data/Finset/Union.lean
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,20 @@ lemma disjiUnion_disjiUnion (s : Finset α) (f : α → Finset β) (g : β → F
exact disjoint_left.mp (h1 a.prop b.prop <| Subtype.coe_injective.ne hab) hfa hfb :=
eq_of_veq <| Multiset.bind_assoc.trans (Multiset.attach_bind_coe _ _).symm
#align finset.disj_Union_disj_Union Finset.disjiUnion_disjiUnion
variable [DecidableEq β] {s : Finset α} {t : Finset β} {f : α → β}
YaelDillies marked this conversation as resolved.
Show resolved Hide resolved

lemma disjiUnion_filter_eq_of_maps_to [DecidableEq β] {s : Finset α} {t : Finset β} {f : α → β}
(h : ∀ x ∈ s, f x ∈ t) :
t.disjiUnion (fun a ↦ s.filter (fun c ↦ f c = a))
(fun x' hx y' hy hne ↦ by
simp_rw [disjoint_left, mem_filter]
rintro i ⟨_, rfl⟩ ⟨_, rfl⟩
exact hne rfl) = s :=
ext fun b ↦ by simpa using h b
private lemma pairwiseDisjoint_fibers : Set.PairwiseDisjoint ↑t fun a ↦ s.filter (f · = a) :=
fun x' hx y' hy hne ↦ by
simp_rw [disjoint_left, mem_filter]; rintro i ⟨_, rfl⟩ ⟨_, rfl⟩; exact hne rfl

-- `simpNF` claims that the statement can't simplify itself, but it can (as of 2024-02-14)
@[simp, nolint simpNF] lemma disjiUnion_filter_eq (s : Finset α) (t : Finset β) (f : α → β) :
t.disjiUnion (fun a ↦ s.filter (f · = a)) pairwiseDisjoint_fibers =
s.filter fun c ↦ f c ∈ t :=
ext fun b => by simpa using and_comm

lemma disjiUnion_filter_eq_of_maps_to (h : ∀ x ∈ s, f x ∈ t) :
t.disjiUnion (fun a ↦ s.filter (f · = a)) pairwiseDisjoint_fibers = s := by simpa
#align finset.disj_Union_filter_eq_of_maps_to Finset.disjiUnion_filter_eq_of_maps_to

end DisjiUnion
Expand Down
66 changes: 50 additions & 16 deletions Mathlib/Data/Fintype/BigOperators.lean
Original file line number Diff line number Diff line change
Expand Up @@ -118,29 +118,63 @@ end

open Finset

@[simp]
nonrec theorem Fintype.card_sigma {α : Type*} (β : α → Type*) [Fintype α] [∀ a, Fintype (β a)] :
Fintype.card (Sigma β) = ∑ a, Fintype.card (β a) :=
card_sigma _ _
#align fintype.card_sigma Fintype.card_sigma
section Pi
variable {ι κ : Type*} {α : ι → Type*} [DecidableEq ι] [DecidableEq κ] [Fintype ι]
[∀ i, DecidableEq (α i)]

@[simp]
theorem Finset.card_pi [DecidableEq α] {δ : α → Type*} (s : Finset α) (t : ∀ a, Finset (δ a)) :
(s.pi t).card = ∏ a in s, card (t a) :=
Multiset.card_pi _ _
@[simp] lemma Finset.card_pi (s : Finset ι) (t : ∀ i, Finset (α i)) :
(s.pi t).card = ∏ i in s, card (t i) := Multiset.card_pi _ _
#align finset.card_pi Finset.card_pi

@[simp]
theorem Fintype.card_piFinset [DecidableEq α] [Fintype α] {δ : α → Type*} (t : ∀ a, Finset (δ a)) :
(Fintype.piFinset t).card = ∏ a, Finset.card (t a) := by simp [Fintype.piFinset, card_map]
namespace Fintype

@[simp] lemma card_piFinset (s : ∀ i, Finset (α i)) :
(piFinset s).card = ∏ i, (s i).card := by simp [piFinset, card_map]
#align fintype.card_pi_finset Fintype.card_piFinset

@[simp]
theorem Fintype.card_pi {β : α → Type*} [DecidableEq α] [Fintype α] [∀ a, Fintype (β a)] :
Fintype.card (∀ a, β a) = ∏ a, Fintype.card (β a) :=
Fintype.card_piFinset _
@[simp] lemma card_pi [DecidableEq ι] [∀ i, Fintype (α i)] : card (∀ i, α i) = ∏ i, card (α i) :=
card_piFinset _
#align fintype.card_pi Fintype.card_pi

@[simp] nonrec lemma card_sigma [Fintype ι] [∀ i, Fintype (α i)] :
card (Sigma α) = ∑ i, card (α i) := card_sigma _ _
#align fintype.card_sigma Fintype.card_sigma

/-- The number of dependent maps `f : Π j, s j` for which the `i` component is `a` is the product
over all `j ≠ i` of `(s j).card`.

Note that this is just a composition of easier lemmas, but there's some glue missing to make that
smooth enough not to need this lemma. -/
lemma card_filter_piFinset_eq_of_mem (s : ∀ i, Finset (α i)) (i : ι) {a : α i} (ha : a ∈ s i) :
((piFinset s).filter fun f ↦ f i = a).card = ∏ j in univ.erase i, (s j).card := by
calc
_ = ∏ j, (Function.update s i {a} j).card := by
rw [← piFinset_update_singleton_eq_filter_piFinset_eq _ _ ha, Fintype.card_piFinset]
_ = ∏ j, Function.update (fun j ↦ (s j).card) i 1 j :=
Fintype.prod_congr _ _ fun j ↦ by obtain rfl | hji := eq_or_ne j i <;> simp [*]
_ = _ := by simp [prod_update_of_mem, erase_eq]

lemma card_filter_piFinset_const_eq_of_mem (s : Finset κ) (i : ι) {x : κ} (hx : x ∈ s) :
((piFinset fun _ ↦ s).filter fun f ↦ f i = x).card = s.card ^ (card ι - 1) :=
(card_filter_piFinset_eq_of_mem _ _ hx).trans $ by
rw [prod_const s.card, card_erase_of_mem (mem_univ _), card_univ]

lemma card_filter_piFinset_eq (s : ∀ i, Finset (α i)) (i : ι) (a : α i) :
((piFinset s).filter fun f ↦ f i = a).card =
if a ∈ s i then ∏ b in univ.erase i, (s b).card else 0 := by
split_ifs with h
· rw [card_filter_piFinset_eq_of_mem _ _ h]
· rw [filter_piFinset_of_not_mem _ _ _ h, Finset.card_empty]

lemma card_filter_piFinset_const (s : Finset κ) (i : ι) (j : κ) :
((piFinset fun _ ↦ s).filter fun f ↦ f i = j).card =
if j ∈ s then s.card ^ (card ι - 1) else 0 :=
(card_filter_piFinset_eq _ _ _).trans $ by
rw [prod_const s.card, card_erase_of_mem (mem_univ _), card_univ]

end Fintype
end Pi

-- FIXME ouch, this should be in the main file.
@[simp]
theorem Fintype.card_fun [DecidableEq α] [Fintype α] [Fintype β] :
Expand Down
33 changes: 31 additions & 2 deletions Mathlib/Data/Fintype/Pi.lean
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,39 @@ lemma eval_image_piFinset (t : ∀ a, Finset (δ a)) (a : α) [DecidableEq (δ a
choose f hf using ht
exact ⟨fun b ↦ if h : a = b then h ▸ x else f _ h, by aesop, by simp⟩

lemma filter_piFinset_of_not_mem [∀ a, DecidableEq (δ a)] (t : ∀ a, Finset (δ a)) (a : α)
(x : δ a) (hx : x ∉ t a) : (piFinset t).filter (· a = x) = ∅ := by
lemma eval_image_piFinset_const {β} [DecidableEq β] (t : Finset β) (a : α) :
((piFinset fun _i : α ↦ t).image fun f ↦ f a) = t := by
obtain rfl | ht := t.eq_empty_or_nonempty
· haveI : Nonempty α := ⟨a⟩
simp
· exact eval_image_piFinset (fun _ ↦ t) a fun _ _ ↦ ht

variable [∀ a, DecidableEq (δ a)]

lemma filter_piFinset_of_not_mem (t : ∀ a, Finset (δ a)) (a : α) (x : δ a) (hx : x ∉ t a) :
(piFinset t).filter (· a = x) = ∅ := by
simp only [filter_eq_empty_iff, mem_piFinset]; rintro f hf rfl; exact hx (hf _)

-- TODO: This proof looks like a good example of something that `aesop` can't do but should
lemma piFinset_update_eq_filter_piFinset_mem (s : ∀ i, Finset (δ i)) (i : α) {t : Finset (δ i)}
(hts : t ⊆ s i) : piFinset (Function.update s i t) = (piFinset s).filter (fun f ↦ f i ∈ t) := by
ext f
simp only [mem_piFinset, mem_filter]
refine ⟨fun h ↦ ?_, fun h j ↦ ?_⟩
· have := by simpa using h i
refine ⟨fun j ↦ ?_, this⟩
obtain rfl | hji := eq_or_ne j i
· exact hts this
· simpa [hji] using h j
· obtain rfl | hji := eq_or_ne j i
· simpa using h.2
· simpa [hji] using h.1 j

lemma piFinset_update_singleton_eq_filter_piFinset_eq (s : ∀ i, Finset (δ i)) (i : α) {a : δ i}
(ha : a ∈ s i) :
piFinset (Function.update s i {a}) = (piFinset s).filter (fun f ↦ f i = a) := by
simp [piFinset_update_eq_filter_piFinset_mem, ha]

end Fintype

/-! ### pi -/
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/GroupTheory/PGroup.lean
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ theorem card_modEq_card_fixedPoints [Fintype (fixedPoints G α)] :
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 : 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]
Expand Down
Loading