Zulip Chat Archive

Stream: new members

Topic: Van der Waerden


Luc Champignon (Jul 07 2025 at 10:47):

Hello, m’I new on lean. For training, I have formalised the theorem
of van der Waerden. Do you think it's worth integrating it with
mathlib?

/-
Copyright (c) 2025 Luc Champignon. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Luc Champignon
-/
import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Algebra.BigOperators.Finprod

/-!
# Theorem of Van der Waerden on arithmetic progressions

In this file we prove the theorem of Van der Waerden on arithmetic progressions. The demonstration
is adapted from the following article.

## References

R. L. Graham and B. L. Rothschild, Proc. Amer. Math. Soc. 42 (1974), 385-386,
DOI: 10.1090/S0002-9939-1974-0329917-8
https://www.ams.org/journals/proc/1974-042-02/S0002-9939-1974-0329917-8/S0002-9939-1974-0329917-8.pdf
-/

open BigOperators
open Finset

private def S (l m : Nat) : Prop :=  r : Nat,  N : Nat,  C : Nat  Fin r,
   a : Nat,  d : Nat  Nat,  q : Nat  Fin r, ( i : Nat, d i  0) 
  (a + (l + 1) *  x in range (m + 1), d x < N) 
  ( I : Nat  Nat,  n : Nat, n  m + 1 
  ( i : Nat, (i < n  I i = l + 1)  (n  i  i  m  I i  l)) 
  C (a +  x in range (m + 1), d x * I x) = q n)  1  N

private lemma aux {r : Nat} (F : Nat  Fin r) :  u v : Nat,
    u < v  u < r + 1  v < r + 1  F u = F v := by
  obtain u, v, h1 := Fintype.exists_ne_map_eq_of_card_lt
    (fun u : Fin (r + 1)  F u) (by simp [Fintype.card_fin])
  rcases lt_or_gt_of_ne (Fin.val_ne_iff.2 h1.1) with h2 | h3
  · use u.1, v.1, h2, u.2, v.2, h1.2
  use v.1, u.1, h3, v.2, u.2, Eq.symm h1.2

private lemma sum_if {f g : Nat  Nat} {m : Nat} : ( x in range (m + 1),
    if x < m then f x else g x) = ( x in range m, f x) + g m := by
  simp [sum_range_succ]
  apply sum_congr rfl
  intro _ h1
  simp at h1
  simp [h1]

private lemma sum_if_2 {u v : Nat} {f g : Nat  Nat} (h1 : u < v) :
    ( x in range u, f x +  x in range v, if x < u then 0 else g x) =
     x in range v, if x < u then f x else g x := by
  have h1 {h : Nat  Nat} :  x in range v, h x =
     x in range u, h x +  x in ((range v) \ (range u)), h x := by
    rw [  sum_disjUnion Finset.disjoint_sdiff]
    exact sum_congr (by simp [disjUnion_eq_union, le_of_lt h1]) (by simp)
  rw [h1, h1,  add_assoc,  sum_add_distrib]
  congr 1
  repeat
    apply sum_congr rfl
    intro _ h2
    simp at h2
    split <;> omega

private lemma n1 (l m : Nat) : S l 0  S l m  S l (m + 1) := by
  intro h h0 r
  obtain M, h1 := h0 r
  obtain M', h2 := h (r ^ M)
  use M' * M + M
  intro C
  let C' := fun k  finFunctionFinEquiv (fun j : Fin M  C (k * M + j))
  obtain a', d', q', h3 := h2 C'
  simp at h3
  obtain a, d, q, h4 := h1 (fun k  C (a' * M + k))
  let d'' := fun i  if i < m + 1 then d i else d' 0 * M
  let q'' := fun k  if k < m + 2 then q k else C (a' * M + a +
     x in range (m + 2), if x < m + 1 then d x * (l + 1) else d' 0 * M * (l + 1))
  use a' * M + a, d'', q''
  simp
  constructor
  · exact fun i  by simp [mt ite_eq_iff'.1, h4.1 i, Nat.one_le_iff_ne_zero.1 h4.2.2.2, h3.1 0]
  constructor
  · calc
    (a' * M + a + (l + 1) *  x in range (m + 2), if x < m + 1 then d x else d' 0 * M)
    _ = (a' * M + a + (l + 1) * ( x in range (m + 1), d x + d' 0 * M)) := by simp [sum_if]
    _ = (a' + (l + 1) * d' 0) * M + (a + (l + 1) * ( x in range (m + 1), d x)) := by
      simp_arith [add_mul _ _ M, mul_add (l + 1), mul_assoc]
    _ < (a' + (l + 1) * d' 0) * M + M := by simp [h4.2.1]
    _   M' * M + M := by simp [Nat.mul_le_mul_right M (le_of_lt h3.2.1)]
  constructor
  · intro I n _ h5
    split
    case inl h6 =>
      have h7 :  i : , (i < n  I i = l + 1)  (n  i  i  m  I i  l) :=
        fun i  And.left (h5 i), fun h h'  And.right (h5 i) h (Nat.le_step h')
      have h8 :  y : Nat, y  l   C' (a' + d' 0 * y) = q' 0 := by
        intro y h9
        apply h3.2.2.1 (fun _  y) 0 zero_le_one
        simp [h9]
      have h10 : C' (a' + d' 0 * I (m + 1)) = C' (a' + d' 0 * 0) := by
        rw [h8 (I (m + 1)) (And.right (h5 (m + 1))
          (Nat.lt_add_one_iff.1 h6) (le_refl (m + 1))), h8 0 (zero_le l)]
      simp at h10
      have h11 :  x  range (m + 1), d x * I x  d x * (l + 1) := by
        intro x h12
        apply Nat.mul_le_mul_left
        rcases le_or_lt n x with h13 | h14
        · exact Nat.le_step (And.right (h5 x) h13 (le_of_lt (mem_range.1 h12)))
        · exact le_of_eq (And.left (h5 x) h14)
      have h15 : a +  x in range (m + 1), d x * I x < M := by calc
        a +  x in range (m + 1), d x * I x
        _  a +  x in range (m + 1), d x * (l  + 1) := by simp [sum_le_sum h11]
        _ = a + (l + 1) *  x in range (m + 1), d x := by
          simp [mul_comm, mul_sum (range (m + 1)) d (l + 1)]
        _ < M := h4.2.1
      rw [ h4.2.2.1 I n (Nat.lt_add_one_iff.1 h6) h7,  congr_fun h10 ( _ , h15 : Fin M)]
      congr 1
      simp [sum_if, add_mul _ _ M]
      simp_arith [mul_assoc, mul_comm M]
    case inr h16 =>
      congr 2
      apply sum_congr rfl
      intro x h17
      rw [And.left (h5 x) (lt_of_lt_of_le (mem_range.1 h17) (le_of_not_lt h16))]
  calc
    1  M := h4.2.2.2
    _  M' * M + M := by simp

private lemma n2 (l : Nat) : ( m, S l m)  S (l + 1) 0 := by
  intro h1 r
  obtain N, h2 := h1 r r
  use 2 * N
  intro C
  obtain a, d, q, h3 := h2 C
  obtain u, v, h4 := aux q
  use a +  x in range u, d x * (l + 1),
    fun n  if n = 0 then  x in range v, if x < u then 0 else d x else 1,
    fun k  if k = 0 then q u else C (a +  x in range u, d x * (l + 1) +
      ( x in range v, if x < u then 0 else d x) * (l + 2))
  constructor
  · rintro _
    split
    · simp [mt sum_eq_zero_iff.1]
      use u, le_refl u, h4.1, h3.1 u
    exact one_ne_zero
  simp
  constructor
  · calc
    a +  x in range u, (d x * (l + 1)) +
      (l + 1 + 1) * ( x in range v, if x < u then 0 else d x)
    _ = a + (l + 1) *  x in range u, d x +
      (l + 1 + 1) *  x in range v, if x < u then 0 else d x := by
        simp [mul_sum (range u) d (l + 1)]
        simp [mul_comm]
    _ = a + (l + 1) *  x in range u, d x +
      (l + 1) * ( x in range v, if x < u then 0 else d x)
      + ( x in range v, if x < u then 0 else d x) := by
        rw [add_mul (l + 1) 1 ( x in range v, if x < u then 0 else d x), one_mul]
        omega
    _ = a + (l + 1) * ( x in range u, d x +  x in range v, if x < u then 0 else d x)
      + ( x in range v, if x < u then 0 else d x) := by simp [mul_add, add_assoc]
    _ = a + (l + 1) * ( x in range v, d x) +
      ( x in range v, if x < u then 0 else d x) := by simp [sum_if_2 h4.1]
    _  a + (l + 1) * ( x in range (r + 1), d x) +
      ( x in range v, if x < u then 0 else d x) := by
        simp [sum_le_sum_of_subset (range_subset.2 (le_of_lt h4.2.2.1))]
    _ < N + ( x in range v, if x < u then 0 else d x) := by simp [h3.2.1]
    _  N + ( x in range v, d x) := by
        simp [add_assoc]
        apply sum_le_sum
        intro _ _
        split <;> simp
    _  N + ( x in range (r + 1), d x) := by
        simp [sum_le_sum_of_subset (range_subset.2 (le_of_lt h4.2.2.1))]
    _  N + a + ( x in range (r + 1), d x) := by simp
    _  N + a + (l + 1) * ( x in range (r + 1), d x) := by simp [add_mul]
    _ < N + N := by simp [add_assoc, h3.2.1]
    _ = 2 * N := by omega
  constructor
  · intro I x _ h5
    split
    case inl h6 =>
      rw [h6] at h5
      rcases eq_or_lt_of_le (And.right (h5 0) le_rfl rfl) with h7 | _
      · let I' := fun x  if x < v then l + 1 else 0
        have h8 :  i : , (i < v  I' i = l + 1)  (v  i  i  r  I' i  l) := by
          simp
          intro
          constructor
          all_goals (try split) <;> omega
        rw [h4.2.2.2, h7,  h3.2.2.1 I' v (le_of_lt h4.2.2.1) h8]
        simp [add_assoc, sum_mul,  sum_if_2 h4.2.2.1, sum_if_2 h4.1]
      let I'' := fun x  if x < v then if x < u then l + 1 else I 0 else 0
      have h9 :  (i : ), (i < u  I'' i = l + 1)  (u  i  i  r  I'' i  l) := by
        simp
        intro
        constructor
        all_goals (try repeat split) <;> omega
      rw [  h3.2.2.1 I'' u (le_of_lt h4.2.1) h9]
      simp [add_assoc, sum_mul,  sum_if_2 h4.2.2.1, sum_if_2 h4.1]
    case inr h10 =>
      simp [h5 0, Nat.zero_lt_of_ne_zero h10]
  omega

Luc Champignon (Jul 07 2025 at 10:47):

private lemma n3 : S 0 0 := by
  intro
  use 2
  intro C
  use 0, fun _  1, C
  simp
  intro _ _ h1 h2
  rcases Nat.le_one_iff_eq_zero_or_eq_one.1 h1 with h3 | h3
  all_goals simp [h2, h3]

private lemma n4 :  l m : Nat, S l m := by
  have h1 :  l : Nat, S l 0   m : Nat, S l m := by
    rintro l h1 m
    induction m with
    | zero => exact h1
    | succ n h2 => exact n1 l n h1 h2
  intro l
  induction l with
  | zero => exact h1 0 n3
  | succ n ih => exact h1 (n + 1) (n2 n ih)

/-- **The theorem of Van der Waerden on arithmetic progressions** which asserts that for any
partition of the naturel into a finite number of classes, some class contains arbitrarily long
arithmetic progressions.-/
theorem VanDerWaerden (r l : Nat) :  N : Nat,  C : Nat  Fin r,  a b : Nat,  c : Fin r,
    b  0  a + (l + 1) * b < N   n : Nat, n  l  C (a + b * n) = c := by
  obtain N, h1 := n4 l 0 r
  use N
  intro C
  obtain a, d, q, h2 := h1 C
  simp at h2
  use a, d 0, q 0, h2.1 0, h2.2.1, fun n h  by simp [h2.2.2.1 (fun _  n) 0, h]

Kenny Lau (Jul 07 2025 at 10:50):

https://leanprover-community.github.io/mathlib4_docs/Mathlib/Combinatorics/HalesJewett.html#Combinatorics.exists_mono_homothetic_copy

Kenny Lau (Jul 07 2025 at 10:50):

/-- A generalization of Van der Waerden's theorem: if `M` is a finitely colored commutative
monoid, and `S` is a finite subset, then there exists a monochromatic homothetic copy of `S`. -/
theorem exists_mono_homothetic_copy {M κ : Type*} [AddCommMonoid M] (S : Finset M) [Finite κ]
    (C : M  κ) :  a > 0,  (b : M) (c : κ),  s  S, C (a  s + b) = c

Kenny Lau (Jul 07 2025 at 10:53):

@Luc Champignon Congratulations on formalising the theorem! :tada: , and welcome to Lean! I hope you enjoyed your formalisation process and that it taught you something new; but unfortunately Mathlib seems to already contain a generalisation of that theorem, so maybe you can try to specialise that instead if you really want arithmetic progressions :slight_smile:

Kenny Lau (Jul 07 2025 at 10:55):

I hope you won't be deterred by this; there are definitely more theorems out there that have not been formalised, if your goal is to get something into mathlib; and I would be very happy to review your future first PR (but warning, I don't know a lot about combinatorics, but I know someone who does)!


Last updated: Dec 20 2025 at 21:32 UTC