Zulip Chat Archive
Stream: Is there code for X?
Topic: Proof by descent on finite sets
Xavier Xarles (Dec 27 2023 at 18:12):
In the middle of a proof I would need something similar to a descent argument for finsets, that say if a property of Finsets is true for the empty one, false for the singletons and if it is true for a Finset with more than one element (called non-trivial), then it is true for the subset removing one element, then the property is only true for the empty set. I tried to prove it using induction on Finsets but I am completely stuck.
import Mathlib.Data.Finset.Basic
theorem descent {α : Type*}[DecidableEq α]{p : ∀ s : Finset α, Prop}{s : Finset α}
(hempty: p ∅) (hsingle: ∀ (a : α), ¬ p {a} )
(hind : ∀ (s) (hn :s.Nontrivial), p s → (∃ (a : α), a∈ s ∧ p (Finset.erase s a)) ):
(p s) ↔ s= ∅ := by sorry
Any suggestion will be very much appreciated. Also suggestions proposing more natural but essentially equivalent results.
Andrew Yang (Dec 27 2023 at 18:19):
I suspect it will be easier to do induction on fun s ↦ p s → s = ∅
in your application.
EDIT: maybe not
Yaël Dillies (Dec 27 2023 at 18:37):
Here's a more natural statement:
import Mathlib.Data.Finset.Basic
open Finset
variable {α : Type*} {p : Finset α → Prop} {s : Finset α}
theorem descent (hempty : p ∅) (hsingle : ∀ a, ¬ p {a})
(hind : ∀ s, s.Nonempty → ∀ a ha, p (cons a s ha) → p s) :
p s ↔ s = ∅ := by
refine ⟨fun hs ↦ ?_, by rintro rfl; exact hempty⟩
contrapose! hs
refine (nonempty_iff_ne_empty.2 hs).cons_induction hsingle fun a s ha hs ih h ↦ ?_
exact ih $ hind _ hs _ ha h
Yaël Dillies (Dec 27 2023 at 18:37):
It's not quite what you want, though
Andrew Yang (Dec 27 2023 at 18:46):
import Mathlib.Data.Finset.Card
theorem descent' {α : Type*}[DecidableEq α]{p : Finset α → Prop}{s : Finset α}
(hempty: p ∅) (hsingle: ∀ (a : α), ¬ p {a})
(hind : ∀ s, s.Nonempty → p s → (∃ (a : α), a ∈ s ∧ p (Finset.erase s a))) :
(p s) ↔ s= ∅ := by
refine ⟨?_, fun e ↦ e ▸ hempty⟩
rw [← Finset.card_eq_zero]
generalize hn : s.card = n
induction n generalizing s with
| zero => exact fun _ ↦ rfl
| succ n ih =>
intro H
have : s.Nonempty
· rw [Finset.nonempty_iff_ne_empty, ne_eq, ← Finset.card_eq_zero, hn]
exact Nat.succ_ne_zero n
obtain ⟨x, hxs, hs⟩ := hind s this H
obtain rfl := ih (by rw [Finset.card_erase_of_mem hxs, hn]; rfl) hs
obtain ⟨y, rfl⟩ := Finset.card_eq_one.mp hn
exact (hsingle _ H).elim
theorem descent {α : Type*}[DecidableEq α]{p : ∀ s : Finset α, Prop}{s : Finset α}
(hempty: p ∅) (hsingle: ∀ (a : α), ¬ p {a} )
(hind : ∀ (s) (hn :s.Nontrivial), p s → (∃ (a : α), a∈ s ∧ p (Finset.erase s a)) ):
(p s) ↔ s= ∅ := by
apply descent' hempty hsingle
intros s hn hs
obtain (⟨a, rfl⟩|hs') := hn.exists_eq_singleton_or_nontrivial
· exact (hsingle _ hs).elim
· exact hind s hs' hs
Yaël Dillies (Dec 27 2023 at 18:51):
I have a better solution coming
Yaël Dillies (Dec 27 2023 at 19:03):
import Mathlib.Data.Finset.Card
namespace Finset
variable {α : Type*} [DecidableEq α] {p : Finset α → Prop} {s : Finset α} {a : α}
lemma Nontrivial.exists_ne (hs : s.Nontrivial) (a : α) : ∃ b ∈ s, b ≠ a := by
by_contra!; exact not_nontrivial_singleton $ hs.mono fun b hb ↦ mem_singleton.2 $ this b hb
lemma Nontrivial.erase_nonempty (hs : s.Nontrivial) : (s.erase a).Nonempty :=
(hs.exists_ne a).imp $ by aesop
/-- Suppose that, given objects defined on all nonempty strict subsets of any nontrivial finset `s`,
one knows how to define an object on `s`. Then one can inductively define an object on all finsets,
starting from singletons and iterating. This can be used either to define data, or to prove
properties.
TODO: Actually let `p` be `Sort`-valued. -/
@[elab_as_elim]
protected lemma Nonempty.strong_induction {p : ∀ s, s.Nonempty → Prop}
(h₀ : ∀ a, p {a} (singleton_nonempty _))
(h₁ : ∀ ⦃s⦄ (hs : s.Nontrivial), (∀ t ht, t ⊂ s → p t ht) → p s hs.nonempty) :
∀ ⦃s : Finset α⦄ (hs), p s hs
| s, hs => by
obtain ⟨a, rfl⟩ | hs := hs.exists_eq_singleton_or_nontrivial
· exact h₀ _
· refine h₁ hs fun t ht hts ↦ ?_
have := card_lt_card hts
exact ht.strong_induction h₀ h₁
termination_by Nonempty.strong_induction _ => Finset.card ‹_›
theorem descent (hempty : p ∅) (hsingle : ∀ a, ¬ p {a})
(hind : ∀ s, s.Nontrivial → p s → ∃ a ∈ s, p (s.erase a)) :
p s ↔ s = ∅ := by
refine ⟨?_, by rintro rfl; exact hempty⟩
rw [← not_nonempty_iff_eq_empty]
rintro hps hs
induction' hs using Nonempty.strong_induction with _ s hs ih
· exact hsingle _ hps
obtain ⟨a, ha, hpa⟩ := hind s hs hps
exact ih _ hs.erase_nonempty (erase_ssubset ha) hpa
end Finset
Yaël Dillies (Dec 27 2023 at 19:03):
Everything but descent
should be in mathlib. Feel free to PR it (or to tell me to do it).
Xavier Xarles (Dec 27 2023 at 19:08):
I would very pleased if you PR all these...
Xavier Xarles (Dec 27 2023 at 19:08):
(excluding "descent")
Ruben Van de Velde (Dec 27 2023 at 19:16):
Yeah, it turns out that "descent" just means "strong induction" if you squint at it right
Junyan Xu (Dec 27 2023 at 19:20):
It's annoying that all Finset induction principles uses Forall rather than Exists (of an element to insert), so we must relegate to induction on the cardinality. #9123 is a move in the right direction (uses Exists), but it's for Set, not Finset.
Yaël Dillies (Dec 27 2023 at 19:23):
But that's because the version with Exists
is usually false? It's only true over finite types.
Junyan Xu (Dec 27 2023 at 19:24):
I don't think you assumed finiteness of α when proving theorem descent
?
Yaël Dillies (Dec 27 2023 at 19:25):
How is that related to #9123 ?
Junyan Xu (Dec 27 2023 at 19:26):
Oh I see what you're saying. You're right the versions with Exists are not always true.
I see that descent
is not exactly "contrapositive" of the induction principle . #9123 does assume finiteness.
Yaël Dillies (Dec 27 2023 at 19:29):
However #9123 seems to be a special case of what we have here (once translated to Set
).
Yaël Dillies (Dec 27 2023 at 20:01):
(you need to apply ᶜ
everywhere)
Yaël Dillies (Dec 27 2023 at 20:08):
Xavier Xarles said:
I would very pleased if you PR all these...
Wish granted: #9308
Eric Rodriguez (Dec 27 2023 at 20:46):
open Finset
theorem descent {α : Type*}[DecidableEq α]{p : ∀ s : Finset α, Prop}{s : Finset α}
(hempty: p ∅) (hsingle: ∀ (a : α), ¬ p {a} )
(hind : ∀ (s) (hn :s.Nontrivial), p s → (∃ (a : α), a∈ s ∧ p (Finset.erase s a)) ):
(p s) ↔ s= ∅ := by
refine ⟨fun hp ↦ ?_, by rintro rfl; exact hempty⟩
contrapose! hsingle
induction' s using strongInduction with k ih
obtain (⟨a, rfl⟩ | h) := (nonempty_of_ne_empty hsingle).exists_eq_singleton_or_nontrivial
· exact ⟨a, hp⟩
· obtain ⟨a, hak, hap⟩ := hind _ h hp
apply ih (k.erase a) (erase_ssubset hak) hap
sorry
this is an easier approach that is at worst missing the sorry
lemma (I have to run, but it's easy i promise!)
Xavier Xarles (Dec 27 2023 at 23:55):
The proof by @Eric Rodriguez finished:
import Mathlib.Data.Finset.Card
open Finset
theorem descent {α : Type*}[DecidableEq α]{p : ∀ s : Finset α, Prop}{s : Finset α}
(hempty: p ∅) (hsingle: ∀ (a : α), ¬ p {a} )
(hind : ∀ (s) (hn :s.Nontrivial), p s → (∃ (a : α), a∈ s ∧ p (Finset.erase s a)) ):
(p s) ↔ s= ∅ := by
refine ⟨fun hp ↦ ?_, by rintro rfl; exact hempty⟩
contrapose! hsingle
induction' s using strongInduction with k ih
obtain (⟨a, rfl⟩ | h) := (nonempty_of_ne_empty hsingle).exists_eq_singleton_or_nontrivial
· exact ⟨a, hp⟩
· obtain ⟨a, hak, hap⟩ := hind _ h hp
apply ih (k.erase a) (erase_ssubset hak) hap
rw [← nonempty_iff_ne_empty]
exact (Finset.erase_nonempty hak).2 h
Yaël Dillies (Dec 28 2023 at 07:01):
Is eric's sorry not my Finset.Nontrivial.erase_nonempty
above?
Xavier Xarles (Jan 03 2024 at 12:17):
(deleted)
Last updated: May 02 2025 at 03:31 UTC