Skip to content

Commit

Permalink
feat: Finset family induction (#7522)
Browse files Browse the repository at this point in the history
Provide an induction principle for finset families: One can increase the support of a finset family one by one.
  • Loading branch information
YaelDillies committed Oct 12, 2023
1 parent d8093fd commit c98e6b7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
80 changes: 79 additions & 1 deletion Mathlib/Combinatorics/SetFamily/Compression/Down.lean
Expand Up @@ -3,7 +3,7 @@ Copyright (c) 2022 YaΓ«l Dillies. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: YaΓ«l Dillies
-/
import Mathlib.Data.Finset.Card
import Mathlib.Data.Finset.Lattice

#align_import combinatorics.set_family.compression.down from "leanprover-community/mathlib"@"9003f28797c0664a49e4179487267c494477d853"

Expand Down Expand Up @@ -136,6 +136,84 @@ theorem nonMemberSubfamily_nonMemberSubfamily :
simp
#align finset.non_member_subfamily_non_member_subfamily Finset.nonMemberSubfamily_nonMemberSubfamily

lemma memberSubfamily_image_insert (hπ’œ : βˆ€ s ∈ π’œ, a βˆ‰ s) :
(π’œ.image <| insert a).memberSubfamily a = π’œ := by
ext s
simp only [mem_memberSubfamily, mem_image]
refine ⟨?_, fun hs ↦ ⟨⟨s, hs, rfl⟩, hπ’œ _ hs⟩⟩
rintro ⟨⟨t, ht, hts⟩, hs⟩
rwa [←insert_erase_invOn.2.injOn (hπ’œ _ ht) hs hts]

@[simp] lemma nonMemberSubfamily_image_insert : (π’œ.image <| insert a).nonMemberSubfamily a = βˆ… := by
simp [eq_empty_iff_forall_not_mem]

@[simp] lemma memberSubfamily_image_erase : (π’œ.image (erase Β· a)).memberSubfamily a = βˆ… := by
simp [eq_empty_iff_forall_not_mem,
(ne_of_mem_of_not_mem' (mem_insert_self _ _) (not_mem_erase _ _)).symm]

lemma image_insert_memberSubfamily (π’œ : Finset (Finset Ξ±)) (a : Ξ±) :
(π’œ.memberSubfamily a).image (insert a) = π’œ.filter (a ∈ Β·) := by
ext s
simp only [mem_memberSubfamily, mem_image, mem_filter]
refine ⟨?_, fun ⟨hs, ha⟩ ↦ ⟨erase s a, ⟨?_, not_mem_erase _ _⟩, insert_erase ha⟩⟩
· rintro ⟨s, ⟨hs, -⟩, rfl⟩
exact ⟨hs, mem_insert_self _ _⟩
Β· rwa [insert_erase ha]

/-- Induction principle for finset families. To prove a statement for every finset family,
it suffices to prove it for
* the empty finset family.
* the finset family which only contains the empty finset.
* `ℬ βˆͺ {s βˆͺ {a} | s ∈ π’ž}` assuming the property for `ℬ` and `π’ž`, where `a` is an element of the
ground type and `π’œ` and `ℬ` are families of finsets not containing `a`.
Note that instead of giving `ℬ` and `π’ž`, the `subfamily` case gives you
`π’œ = ℬ βˆͺ {s βˆͺ {a} | s ∈ π’ž}`, so that `ℬ = π’œ.nonMemberSubfamily` and `π’ž = π’œ.memberSubfamily`.
This is a way of formalising induction on `n` where `π’œ` is a finset family on `n` elements.
See also `Finset.family_induction_on.`-/
@[elab_as_elim]
lemma memberFamily_induction_on {p : Finset (Finset Ξ±) β†’ Prop}
(π’œ : Finset (Finset Ξ±)) (empty : p βˆ…) (singleton_empty : p {βˆ…})
(subfamily : βˆ€ (a : Ξ±) β¦ƒπ’œ : Finset (Finset Ξ±)⦄,
p (π’œ.nonMemberSubfamily a) β†’ p (π’œ.memberSubfamily a) β†’ p π’œ) : p π’œ := by
set u := π’œ.sup id
have hu : βˆ€ s ∈ π’œ, s βŠ† u := fun s ↦ le_sup (f := id)
clear_value u
induction' u using Finset.induction with a u _ ih generalizing π’œ
Β· simp_rw [subset_empty] at hu
rw [←subset_singleton_iff', subset_singleton_iff] at hu
obtain rfl | rfl := hu <;> assumption
refine subfamily a (ih _ ?_) (ih _ ?_)
Β· simp only [mem_nonMemberSubfamily, and_imp]
exact fun s hs has ↦ (subset_insert_iff_of_not_mem has).1 <| hu _ hs
Β· simp only [mem_memberSubfamily, and_imp]
exact fun s hs ha ↦ (insert_subset_insert_iff ha).1 <| hu _ hs

/-- Induction principle for finset families. To prove a statement for every finset family,
it suffices to prove it for
* the empty finset family.
* the finset family which only contains the empty finset.
* `{s βˆͺ {a} | s ∈ π’œ}` assuming the property for `π’œ` a family of finsets not containing `a`.
* `ℬ βˆͺ π’ž` assuming the property for `ℬ` and `π’ž`, where `a` is an element of the ground type and
`ℬ`is a family of finsets not containing `a` and `π’ž` a family of finsets containing `a`.
Note that instead of giving `ℬ` and `π’ž`, the `subfamily` case gives you `π’œ = ℬ βˆͺ π’ž`, so that
`ℬ = π’œ.filter (a βˆ‰ Β·)` and `π’ž = π’œ.filter (a ∈ Β·)`.
This is a way of formalising induction on `n` where `π’œ` is a finset family on `n` elements.
See also `Finset.memberFamily_induction_on.`-/
@[elab_as_elim]
protected lemma family_induction_on {p : Finset (Finset Ξ±) β†’ Prop}
(π’œ : Finset (Finset Ξ±)) (empty : p βˆ…) (singleton_empty : p {βˆ…})
(image_insert : βˆ€ (a : Ξ±) β¦ƒπ’œ : Finset (Finset Ξ±)⦄,
(βˆ€ s ∈ π’œ, a βˆ‰ s) β†’ p π’œ β†’ p (π’œ.image <| insert a))
(subfamily : βˆ€ (a : Ξ±) β¦ƒπ’œ : Finset (Finset Ξ±)⦄,
p (π’œ.filter (a βˆ‰ Β·)) β†’ p (π’œ.filter (a ∈ Β·)) β†’ p π’œ) : p π’œ := by
refine memberFamily_induction_on π’œ empty singleton_empty fun a π’œ hπ’œβ‚€ hπ’œβ‚ ↦ subfamily a hπ’œβ‚€ ?_
rw [←image_insert_memberSubfamily]
exact image_insert _ (by simp) hπ’œβ‚

end Finset

open Finset
Expand Down
3 changes: 3 additions & 0 deletions Mathlib/Data/Finset/Basic.lean
Expand Up @@ -1198,6 +1198,9 @@ theorem insert_subset_insert (a : Ξ±) {s t : Finset Ξ±} (h : s βŠ† t) : insert a
insert_subset_iff.2 ⟨mem_insert_self _ _, Subset.trans h (subset_insert _ _)⟩
#align finset.insert_subset_insert Finset.insert_subset_insert

@[simp] lemma insert_subset_insert_iff (ha : a βˆ‰ s) : insert a s βŠ† insert a t ↔ s βŠ† t := by
simp_rw [←coe_subset]; simp [-coe_subset, ha]

theorem insert_inj (ha : a βˆ‰ s) : insert a s = insert b s ↔ a = b :=
⟨fun h => eq_of_not_mem_of_mem_insert (h.subst <| mem_insert_self _ _) ha, congr_arg (insert · s)⟩
#align finset.insert_inj Finset.insert_inj
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/Data/Set/Basic.lean
Expand Up @@ -1172,7 +1172,7 @@ theorem insert_subset (ha : a ∈ t) (hs : s βŠ† t) : insert a s βŠ† t :=
theorem insert_subset_insert (h : s βŠ† t) : insert a s βŠ† insert a t := fun _ => Or.imp_right (@h _)
#align set.insert_subset_insert Set.insert_subset_insert

theorem insert_subset_insert_iff (ha : a βˆ‰ s) : insert a s βŠ† insert a t ↔ s βŠ† t := by
@[simp] theorem insert_subset_insert_iff (ha : a βˆ‰ s) : insert a s βŠ† insert a t ↔ s βŠ† t := by
refine' ⟨fun h x hx => _, insert_subset_insert⟩
rcases h (subset_insert _ _ hx) with (rfl | hxt)
exacts [(ha hx).elim, hxt]
Expand Down

0 comments on commit c98e6b7

Please sign in to comment.