Zulip Chat Archive
Stream: Is there code for X?
Topic: Lindstrom's theorem for set systems
Strahinja Gvozdić (Sep 26 2025 at 12:55):
Hello! I would like to check if there is already a proof of Lindström's theorem for set systems: given a system of , , subsets of , there are disjoint subsets of indices such that .
Yaël Dillies (Sep 26 2025 at 13:22):
Not that I know of! @Bhavik Mehta ?
Bhavik Mehta (Sep 26 2025 at 23:07):
This statement looks too weak to be what you want, since you can pick I,J both empty. For the version where I,J are enforced to me nonempty, you also need to assume the A_i are nonempty (or some similar condition). And this version I think I have code for lying around somewhere, which I can find if it'd be useful?
Strahinja Gvozdić (Sep 27 2025 at 20:34):
You are right, I forgot to add here the nonemptiness conditions (for I,J and A_i). I thought to contribute it, along with the similar result that for , there are such as before and such that the intersections coincide as well. Do you also have the code for the latter?
Bhavik Mehta (Sep 27 2025 at 20:47):
I don't, but it should be an easy modification to get that one too. I think these would be welcome in mathlib, I just never had time to contribute them myself
Strahinja Gvozdić (Sep 27 2025 at 21:03):
Great, could you send me the code? I will add the latter theorem and make the PR.
Bhavik Mehta (Sep 27 2025 at 21:55):
Here you go:
import Mathlib
open Finset Fintype
-- exists in mathlib, but this one is more general, so should replace it
theorem Finset.exists_pos_of_sum_zero_of_exists_nonzero'
{ι M : Type*} [AddCommMonoid M] [LinearOrder M] [IsOrderedAddMonoid M] {s : Finset ι}
(f : ι → M) (h₁ : ∑ i ∈ s, f i = 0) (h₂ : ∃ i ∈ s, f i ≠ 0) :
∃ i ∈ s, 0 < f i := by
obtain ⟨i, hi, hfi⟩ := h₂
by_contra! h
have : ¬ ∃ x ∈ s, f x < 0 := by simp [← sum_neg_iff_of_nonpos h, h₁]
exact this ⟨i, hi, lt_of_le_of_ne (h i hi) hfi⟩
theorem Finset.exists_neg_of_sum_zero_of_exists_nonzero
{ι M : Type*} [AddCommMonoid M] [LinearOrder M] [IsOrderedAddMonoid M] {s : Finset ι}
(f : ι → M) (h₁ : ∑ i ∈ s, f i = 0) (h₂ : ∃ i ∈ s, f i ≠ 0) :
∃ i ∈ s, f i < 0 := by
obtain ⟨i, hi, hfi⟩ := h₂
by_contra! h
have : ¬ ∃ x ∈ s, 0 < f x := by simp [← sum_pos_iff_of_nonneg h, h₁]
exact this ⟨i, hi, lt_of_le_of_ne' (h i hi) hfi⟩
lemma biUnion_eq_empty {α β : Type*} [DecidableEq β] (s : Finset α) (f : α → Finset β) :
s.biUnion f = ∅ ↔ ∀ a ∈ s, f a = ∅ := by
grind
lemma biUnion_nonempty {α β : Type*} [DecidableEq β] (s : Finset α) (f : α → Finset β) :
(s.biUnion f).Nonempty ↔ ∃ a ∈ s, (f a).Nonempty := by
grind [not_nonempty_iff_eq_empty]
theorem lindstrom {α β : Type*} [Fintype α] [Fintype β] [DecidableEq β] (f : α → Finset β)
(h : card β + 1 ≤ card α) (hf : ∀ i, (f i).Nonempty) :
∃ I J : Finset α, Disjoint I J ∧ I.Nonempty ∧ J.Nonempty ∧ I.biUnion f = J.biUnion f := by
let v (x : α) (y : β) : ℚ := if y ∈ f x then 1 else 0
have hv : ¬ LinearIndependent ℚ v := by
intro h
have : Fintype.card α ≤ Fintype.card β := by simpa using h.fintype_card_le_finrank
omega
obtain ⟨c, hc, hci⟩ : ∃ c : α → ℚ, ∑ i, c i • v i = 0 ∧ ∃ i, c i ≠ 0 := by
simpa [Fintype.linearIndependent_iff] using hv
let I : Finset α := { i | 0 < c i }
let J : Finset α := { i | c i < 0 }
have hij : I.Nonempty ∨ J.Nonempty := by grind [filter_nonempty_iff]
have h₁ : ∀ a ∈ I, ∀ x ∈ f a, ∃ b ∈ J, x ∈ f b := by
intro a ha x hx
have hzero : ∑ i, c i * v i x = 0 := by simpa using congr($hc x)
have hpos : 0 < c a * v a x := by simpa [v, hx, I] using ha
obtain ⟨b, -, hb⟩ := exists_neg_of_sum_zero_of_exists_nonzero _ hzero (by grind)
simp only [mul_ite, v] at hb
exact ⟨b, by grind⟩
have h₂ : ∀ b ∈ J, ∀ x ∈ f b, ∃ a ∈ I, x ∈ f a := by
intro b hb x hx
have hzero : ∑ i, c i * v i x = 0 := by simpa using congr($hc x)
have hpos : c b * v b x < 0 := by simpa [v, hx, J] using hb
obtain ⟨a, -, ha⟩ := exists_pos_of_sum_zero_of_exists_nonzero' _ hzero (by grind)
simp only [mul_ite, v] at ha
exact ⟨a, by grind⟩
have hIJ : I.biUnion f = J.biUnion f := by grind
have hi : I.Nonempty := by grind [biUnion_empty, biUnion_eq_empty, not_nonempty_iff_eq_empty]
have hj : J.Nonempty := by grind [biUnion_empty, biUnion_eq_empty, not_nonempty_iff_eq_empty]
exact ⟨I, J, by grind [disjoint_left]⟩
I took the liberty of updating it to use grind in a few places :)
Strahinja Gvozdić (Oct 18 2025 at 21:32):
Here's the PR. https://github.com/leanprover-community/mathlib4/pull/30637
Last updated: Dec 20 2025 at 21:32 UTC