Skip to content

Commit 17e458e

Browse files
arienmalecjcommelin
andcommitted
feat: Port/Combinatorics.Hindman (#2280)
port of combinatorics.hindman Co-authored-by: Johan Commelin <johan@commelin.net>
1 parent f249e00 commit 17e458e

File tree

2 files changed

+311
-0
lines changed

2 files changed

+311
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ import Mathlib.Combinatorics.Composition
387387
import Mathlib.Combinatorics.DoubleCounting
388388
import Mathlib.Combinatorics.HalesJewett
389389
import Mathlib.Combinatorics.Hall.Finite
390+
import Mathlib.Combinatorics.Hindman
390391
import Mathlib.Combinatorics.Partition
391392
import Mathlib.Combinatorics.Pigeonhole
392393
import Mathlib.Combinatorics.Quiver.Arborescence

Mathlib/Combinatorics/Hindman.lean

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
/-
2+
Copyright (c) 2021 David Wärn. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: David Wärn
5+
6+
! This file was ported from Lean 3 source module combinatorics.hindman
7+
! leanprover-community/mathlib commit dc6c365e751e34d100e80fe6e314c3c3e0fd2988
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Topology.StoneCech
12+
import Mathlib.Topology.Algebra.Semigroup
13+
import Mathlib.Data.Stream.Init
14+
15+
/-!
16+
# Hindman's theorem on finite sums
17+
18+
We prove Hindman's theorem on finite sums, using idempotent ultrafilters.
19+
20+
Given an infinite sequence `a₀, a₁, a₂, …` of positive integers, the set `FS(a₀, …)` is the set
21+
of positive integers that can be expressed as a finite sum of `aᵢ`'s, without repetition. Hindman's
22+
theorem asserts that whenever the positive integers are finitely colored, there exists a sequence
23+
`a₀, a₁, a₂, …` such that `FS(a₀, …)` is monochromatic. There is also a stronger version, saying
24+
that whenever a set of the form `FS(a₀, …)` is finitely colored, there exists a sequence
25+
`b₀, b₁, b₂, …` such that `FS(b₀, …)` is monochromatic and contained in `FS(a₀, …)`. We prove both
26+
these versions for a general semigroup `M` instead of `ℕ+` since it is no harder, although this
27+
special case implies the general case.
28+
29+
The idea of the proof is to extend the addition `(+) : M → M → M` to addition `(+) : βM → βM → βM`
30+
on the space `βM` of ultrafilters on `M`. One can prove that if `U` is an _idempotent_ ultrafilter,
31+
i.e. `U + U = U`, then any `U`-large subset of `M` contains some set `FS(a₀, …)` (see
32+
`exists_FS_of_large`). And with the help of a general topological argument one can show that any set
33+
of the form `FS(a₀, …)` is `U`-large according to some idempotent ultrafilter `U` (see
34+
`exists_idempotent_ultrafilter_le_FS`). This is enough to prove the theorem since in any finite
35+
partition of a `U`-large set, one of the parts is `U`-large.
36+
37+
## Main results
38+
39+
- `FS_partition_regular`: the strong form of Hindman's theorem
40+
- `exists_FS_of_finite_cover`: the weak form of Hindman's theorem
41+
42+
## Tags
43+
44+
Ramsey theory, ultrafilter
45+
46+
-/
47+
48+
49+
open Filter
50+
51+
/-- Multiplication of ultrafilters given by `∀ᶠ m in U*V, p m ↔ ∀ᶠ m in U, ∀ᶠ m' in V, p (m*m')`. -/
52+
@[to_additive
53+
"Addition of ultrafilters given by\n`∀ᶠ m in U+V, p m ↔ ∀ᶠ m in U, ∀ᶠ m' in V, p (m+m')`."]
54+
def Ultrafilter.hasMul {M} [Mul M] : Mul (Ultrafilter M) where mul U V := (· * ·) <$> U <*> V
55+
#align ultrafilter.has_mul Ultrafilter.hasMul
56+
#align ultrafilter.has_add Ultrafilter.hasAdd
57+
58+
attribute [local instance] Ultrafilter.hasMul Ultrafilter.hasAdd
59+
60+
/- We could have taken this as the definition of `U * V`, but then we would have to prove that it
61+
defines an ultrafilter. -/
62+
@[to_additive]
63+
theorem Ultrafilter.eventually_mul {M} [Mul M] (U V : Ultrafilter M) (p : M → Prop) :
64+
(∀ᶠ m in ↑(U * V), p m) ↔ ∀ᶠ m in U, ∀ᶠ m' in V, p (m * m') :=
65+
Iff.rfl
66+
#align ultrafilter.eventually_mul Ultrafilter.eventually_mul
67+
#align ultrafilter.eventually_add Ultrafilter.eventually_add
68+
69+
-- porting note: slow to typecheck
70+
/-- Semigroup structure on `Ultrafilter M` induced by a semigroup structure on `M`. -/
71+
@[to_additive
72+
"Additive semigroup structure on `Ultrafilter M` induced by an additive semigroup
73+
structure on `M`."]
74+
def Ultrafilter.semigroup {M} [Semigroup M] : Semigroup (Ultrafilter M) :=
75+
{ Ultrafilter.hasMul with
76+
mul_assoc := fun U V W =>
77+
Ultrafilter.coe_inj.mp <|
78+
Filter.ext' fun p => by simp only [Ultrafilter.eventually_mul, mul_assoc] }
79+
#align ultrafilter.semigroup Ultrafilter.semigroup
80+
#align ultrafilter.add_semigroup Ultrafilter.addSemigroup
81+
82+
attribute [local instance] Ultrafilter.semigroup Ultrafilter.addSemigroup
83+
84+
-- We don't prove `continuous_mul_right`, because in general it is false!
85+
@[to_additive]
86+
theorem Ultrafilter.continuous_mul_left {M} [Semigroup M] (V : Ultrafilter M) :
87+
Continuous (· * V) :=
88+
TopologicalSpace.IsTopologicalBasis.continuous ultrafilterBasis_is_basis _ <|
89+
Set.forall_range_iff.mpr fun s => ultrafilter_isOpen_basic { m : M | ∀ᶠ m' in V, m * m' ∈ s }
90+
#align ultrafilter.continuous_mul_left Ultrafilter.continuous_mul_left
91+
#align ultrafilter.continuous_add_left Ultrafilter.continuous_add_left
92+
93+
namespace Hindman
94+
95+
-- porting note: mathport wants these names to be `fS`, `fP`, etc, but this does violence to
96+
-- mathematical naming conventions, as does `fs`, `fp`, so we just followed `mathlib` 3 here
97+
98+
/-- `FS a` is the set of finite sums in `a`, i.e. `m ∈ FS a` if `m` is the sum of a nonempty
99+
subsequence of `a`. We give a direct inductive definition instead of talking about subsequences. -/
100+
inductive FS {M} [AddSemigroup M] : Stream' M → Set M
101+
| head (a : Stream' M) : FS a a.head
102+
| tail (a : Stream' M) (m : M) (h : FS a.tail m) : FS a m
103+
| cons (a : Stream' M) (m : M) (h : FS a.tail m) : FS a (a.head + m)
104+
set_option linter.uppercaseLean3 false in
105+
#align hindman.FS Hindman.FS
106+
107+
/-- `FP a` is the set of finite products in `a`, i.e. `m ∈ FP a` if `m` is the product of a nonempty
108+
subsequence of `a`. We give a direct inductive definition instead of talking about subsequences. -/
109+
@[to_additive FS]
110+
inductive FP {M} [Semigroup M] : Stream' M → Set M
111+
| head (a : Stream' M) : FP a a.head
112+
| tail (a : Stream' M) (m : M) (h : FP a.tail m) : FP a m
113+
| cons (a : Stream' M) (m : M) (h : FP a.tail m) : FP a (a.head * m)
114+
set_option linter.uppercaseLean3 false in
115+
#align hindman.FP Hindman.FP
116+
117+
/-- If `m` and `m'` are finite products in `M`, then so is `m * m'`, provided that `m'` is obtained
118+
from a subsequence of `M` starting sufficiently late. -/
119+
@[to_additive
120+
"If `m` and `m'` are finite sums in `M`, then so is `m + m'`, provided that `m'`
121+
is obtained from a subsequence of `M` starting sufficiently late."]
122+
theorem FP.mul {M} [Semigroup M] {a : Stream' M} {m : M} (hm : m ∈ FP a) :
123+
∃ n, ∀ m' ∈ FP (a.drop n), m * m' ∈ FP a := by
124+
induction' hm with a a m hm ih a m hm ih
125+
· exact ⟨1, fun m hm => FP.cons a m hm⟩
126+
· cases' ih with n hn
127+
use n + 1
128+
intro m' hm'
129+
exact FP.tail _ _ (hn _ hm')
130+
· cases' ih with n hn
131+
use n + 1
132+
intro m' hm'
133+
rw [mul_assoc]
134+
exact FP.cons _ _ (hn _ hm')
135+
set_option linter.uppercaseLean3 false in
136+
#align hindman.FP.mul Hindman.FP.mul
137+
set_option linter.uppercaseLean3 false in
138+
#align hindman.FS.add Hindman.FS.add
139+
140+
@[to_additive exists_idempotent_ultrafilter_le_FS]
141+
theorem exists_idempotent_ultrafilter_le_FP {M} [Semigroup M] (a : Stream' M) :
142+
∃ U : Ultrafilter M, U * U = U ∧ ∀ᶠ m in U, m ∈ FP a := by
143+
let S : Set (Ultrafilter M) := ⋂ n, { U | ∀ᶠ m in U, m ∈ FP (a.drop n) }
144+
have h := exists_idempotent_in_compact_subsemigroup ?_ S ?_ ?_ ?_
145+
rcases h with ⟨U, hU, U_idem⟩
146+
· refine' ⟨U, U_idem, _⟩
147+
convert Set.mem_interᵢ.mp hU 0
148+
· exact Ultrafilter.continuous_mul_left
149+
· apply IsCompact.nonempty_interᵢ_of_sequence_nonempty_compact_closed
150+
· intro n U hU
151+
apply Eventually.mono hU
152+
rw [add_comm, ← Stream'.drop_drop, ← Stream'.tail_eq_drop]
153+
exact FP.tail _
154+
· intro n
155+
exact ⟨pure _, mem_pure.mpr <| FP.head _⟩
156+
· exact (ultrafilter_isClosed_basic _).isCompact
157+
· intro n
158+
apply ultrafilter_isClosed_basic
159+
· exact IsClosed.isCompact (isClosed_interᵢ fun i => ultrafilter_isClosed_basic _)
160+
· intro U hU V hV
161+
rw [Set.mem_interᵢ] at *
162+
intro n
163+
rw [Set.mem_setOf_eq, Ultrafilter.eventually_mul]
164+
apply Eventually.mono (hU n)
165+
intro m hm
166+
obtain ⟨n', hn⟩ := FP.mul hm
167+
apply Eventually.mono (hV (n' + n))
168+
intro m' hm'
169+
apply hn
170+
simpa only [Stream'.drop_drop] using hm'
171+
set_option linter.uppercaseLean3 false in
172+
#align hindman.exists_idempotent_ultrafilter_le_FP Hindman.exists_idempotent_ultrafilter_le_FP
173+
set_option linter.uppercaseLean3 false in
174+
#align hindman.exists_idempotent_ultrafilter_le_FS Hindman.exists_idempotent_ultrafilter_le_FS
175+
176+
@[to_additive exists_FS_of_large]
177+
theorem exists_FP_of_large {M} [Semigroup M] (U : Ultrafilter M) (U_idem : U * U = U) (s₀ : Set M)
178+
(sU : s₀ ∈ U) : ∃ a, FP a ⊆ s₀ := by
179+
/- Informally: given a `U`-large set `s₀`, the set `s₀ ∩ { m | ∀ᶠ m' in U, m * m' ∈ s₀ }` is also
180+
`U`-large (since `U` is idempotent). Thus in particular there is an `a₀` in this intersection. Now
181+
let `s₁` be the intersection `s₀ ∩ { m | a₀ * m ∈ s₀ }`. By choice of `a₀`, this is again
182+
`U`-large, so we can repeat the argument starting from `s₁`, obtaining `a₁`, `s₂`, etc.
183+
This gives the desired infinite sequence. -/
184+
have exists_elem : ∀ {s : Set M} (_hs : s ∈ U), (s ∩ { m | ∀ᶠ m' in U, m * m' ∈ s }).Nonempty :=
185+
fun {s} hs =>
186+
Ultrafilter.nonempty_of_mem
187+
(inter_mem hs <| by
188+
rw [← U_idem] at hs
189+
exact hs)
190+
let elem : { s // s ∈ U } → M := fun p => (exists_elem p.property).some
191+
let succ : {s // s ∈ U} → {s // s ∈ U} := fun (p : {s // s ∈ U}) =>
192+
⟨p.val ∩ {m : M | elem p * m ∈ p.val},
193+
inter_mem p.property
194+
(show (exists_elem p.property).some ∈ {m : M | ∀ᶠ (m' : M) in ↑U, m * m' ∈ p.val} from
195+
p.val.inter_subset_right {m : M | ∀ᶠ (m' : M) in ↑U, m * m' ∈ p.val}
196+
(exists_elem p.property).some_mem)⟩
197+
use Stream'.corec elem succ (Subtype.mk s₀ sU)
198+
suffices ∀ (a : Stream' M), ∀ m ∈ FP a, ∀ p, a = Stream'.corec elem succ p → m ∈ p.val
199+
by
200+
intro m hm
201+
exact this _ m hm ⟨s₀, sU⟩ rfl
202+
clear sU s₀
203+
intro a m h
204+
induction' h with b b n h ih b n h ih
205+
· rintro p rfl
206+
rw [Stream'.corec_eq, Stream'.head_cons]
207+
exact Set.inter_subset_left _ _ (Set.Nonempty.some_mem _)
208+
· rintro p rfl
209+
refine' Set.inter_subset_left _ _ (ih (succ p) _)
210+
rw [Stream'.corec_eq, Stream'.tail_cons]
211+
· rintro p rfl
212+
have := Set.inter_subset_right _ _ (ih (succ p) ?_)
213+
· simpa only using this
214+
rw [Stream'.corec_eq, Stream'.tail_cons]
215+
set_option linter.uppercaseLean3 false in
216+
#align hindman.exists_FP_of_large Hindman.exists_FP_of_large
217+
set_option linter.uppercaseLean3 false in
218+
#align hindman.exists_FS_of_large Hindman.exists_FS_of_large
219+
220+
/-- The strong form of **Hindman's theorem**: in any finite cover of an FP-set, one the parts
221+
contains an FP-set. -/
222+
@[to_additive FS_partition_regular
223+
"The strong form of **Hindman's theorem**: in any finite cover of
224+
an FS-set, one the parts contains an FS-set."]
225+
theorem FP_partition_regular {M} [Semigroup M] (a : Stream' M) (s : Set (Set M)) (sfin : s.Finite)
226+
(scov : FP a ⊆ ⋃₀ s) : ∃ c ∈ s, ∃ b : Stream' M, FP b ⊆ c :=
227+
let ⟨U, idem, aU⟩ := exists_idempotent_ultrafilter_le_FP a
228+
let ⟨c, cs, hc⟩ := (Ultrafilter.finite_unionₛ_mem_iff sfin).mp (mem_of_superset aU scov)
229+
⟨c, cs, exists_FP_of_large U idem c hc⟩
230+
set_option linter.uppercaseLean3 false in
231+
#align hindman.FP_partition_regular Hindman.FP_partition_regular
232+
set_option linter.uppercaseLean3 false in
233+
#align hindman.FS_partition_regular Hindman.FS_partition_regular
234+
235+
/-- The weak form of **Hindman's theorem**: in any finite cover of a nonempty semigroup, one of the
236+
parts contains an FP-set. -/
237+
@[to_additive exists_FS_of_finite_cover
238+
"The weak form of **Hindman's theorem**: in any finite cover
239+
of a nonempty additive semigroup, one of the parts contains an FS-set."]
240+
theorem exists_FP_of_finite_cover {M} [Semigroup M] [Nonempty M] (s : Set (Set M)) (sfin : s.Finite)
241+
(scov : ⊤ ⊆ ⋃₀ s) : ∃ c ∈ s, ∃ a : Stream' M, FP a ⊆ c :=
242+
let ⟨U, hU⟩ :=
243+
exists_idempotent_of_compact_t2_of_continuous_mul_left (@Ultrafilter.continuous_mul_left M _)
244+
let ⟨c, c_s, hc⟩ := (Ultrafilter.finite_unionₛ_mem_iff sfin).mp (mem_of_superset univ_mem scov)
245+
⟨c, c_s, exists_FP_of_large U hU c hc⟩
246+
set_option linter.uppercaseLean3 false in
247+
#align hindman.exists_FP_of_finite_cover Hindman.exists_FP_of_finite_cover
248+
set_option linter.uppercaseLean3 false in
249+
#align hindman.exists_FS_of_finite_cover Hindman.exists_FS_of_finite_cover
250+
251+
@[to_additive FS_iter_tail_sub_FS]
252+
theorem FP_drop_subset_FP {M} [Semigroup M] (a : Stream' M) (n : ℕ) : FP (a.drop n) ⊆ FP a := by
253+
induction' n with n ih; · rfl
254+
rw [Nat.succ_eq_one_add, ← Stream'.drop_drop]
255+
exact _root_.trans (FP.tail _) ih
256+
set_option linter.uppercaseLean3 false in
257+
#align hindman.FP_drop_subset_FP Hindman.FP_drop_subset_FP
258+
set_option linter.uppercaseLean3 false in
259+
#align hindman.FS_iter_tail_sub_FS Hindman.FS_iter_tail_sub_FS
260+
261+
@[to_additive]
262+
theorem FP.singleton {M} [Semigroup M] (a : Stream' M) (i : ℕ) : a.nth i ∈ FP a := by
263+
induction' i with i ih generalizing a
264+
· apply FP.head
265+
· apply FP.tail
266+
apply ih
267+
set_option linter.uppercaseLean3 false in
268+
#align hindman.FP.singleton Hindman.FP.singleton
269+
set_option linter.uppercaseLean3 false in
270+
#align hindman.FS.singleton Hindman.FS.singleton
271+
272+
@[to_additive]
273+
theorem FP.mul_two {M} [Semigroup M] (a : Stream' M) (i j : ℕ) (ij : i < j) :
274+
a.nth i * a.nth j ∈ FP a := by
275+
refine' FP_drop_subset_FP _ i _
276+
rw [← Stream'.head_drop]
277+
apply FP.cons
278+
rcases le_iff_exists_add.mp (Nat.succ_le_of_lt ij) with ⟨d, hd⟩
279+
have := FP.singleton (a.drop i).tail d
280+
rw [Stream'.tail_eq_drop, Stream'.nth_drop, Stream'.nth_drop] at this
281+
convert this
282+
rw [hd, add_comm, Nat.succ_add, Nat.add_succ]
283+
set_option linter.uppercaseLean3 false in
284+
#align hindman.FP.mul_two Hindman.FP.mul_two
285+
set_option linter.uppercaseLean3 false in
286+
#align hindman.FS.add_two Hindman.FS.add_two
287+
288+
@[to_additive]
289+
theorem FP.finset_prod {M} [CommMonoid M] (a : Stream' M) (s : Finset ℕ) (hs : s.Nonempty) :
290+
(s.prod fun i => a.nth i) ∈ FP a := by
291+
refine' FP_drop_subset_FP _ (s.min' hs) _
292+
induction' s using Finset.strongInduction with s ih
293+
rw [← Finset.mul_prod_erase _ _ (s.min'_mem hs), ← Stream'.head_drop]
294+
cases' (s.erase (s.min' hs)).eq_empty_or_nonempty with h h
295+
· rw [h, Finset.prod_empty, mul_one]
296+
exact FP.head _
297+
· apply FP.cons
298+
rw [Stream'.tail_eq_drop, Stream'.drop_drop, add_comm]
299+
refine' Set.mem_of_subset_of_mem _ (ih _ (Finset.erase_ssubset <| s.min'_mem hs) h)
300+
have : s.min' hs + 1 ≤ (s.erase (s.min' hs)).min' h :=
301+
Nat.succ_le_of_lt (Finset.min'_lt_of_mem_erase_min' _ _ <| Finset.min'_mem _ _)
302+
cases' le_iff_exists_add.mp this with d hd
303+
rw [hd, add_comm, ← Stream'.drop_drop]
304+
apply FP_drop_subset_FP
305+
set_option linter.uppercaseLean3 false in
306+
#align hindman.FP.finset_prod Hindman.FP.finset_prod
307+
set_option linter.uppercaseLean3 false in
308+
#align hindman.FS.finset_sum Hindman.FS.finset_sum
309+
310+
end Hindman

0 commit comments

Comments
 (0)