Skip to content

Commit 62a82d6

Browse files
committed
feat(Combinatorics): a clique has size at most the chromatic number (leanprover-community#32654)
There already exists a version of this lemma for cliques given by a set, but it's impractical to provide an explicit clique on an explicit graph as a set, rather than an indexed family, especially because computing the size of the set would then involve proving that it is the range of an injective function, even though being a clique already implies being injective! Application: google-deepmind/formal-conjectures#1369 Also rename `coloringOfIsEmpty` and `colorable_of_isEmpty` to leverage anonymous dot notation, and make more arguments implicit. From FormalConjectures
1 parent 4df4ffd commit 62a82d6

2 files changed

Lines changed: 51 additions & 40 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Basic.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ theorem adj_congr_of_sym2 {u v w x : V} (h : s(u, v) = s(w, x)) : G.Adj u v ↔
199199
· rw [hl.1, hl.2]
200200
· rw [hr.1, hr.2, adj_comm]
201201

202+
instance symm_adj (f : ι → V) : Std.Symm fun i j ↦ G.Adj (f i) (f j) where symm _ _ := .symm
203+
202204
section Order
203205

204206
/-- The relation that one `SimpleGraph` is a subgraph of another.

Mathlib/Combinatorics/SimpleGraph/Coloring.lean

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,15 @@ This is also known as a proper coloring.
7474
abbrev Coloring (α : Type v) := G →g completeGraph α
7575

7676
variable {G}
77-
variable {α β : Type*} (C : G.Coloring α)
77+
variable {ι α β : Type*} (C : G.Coloring α)
7878

7979
theorem Coloring.valid {v w : V} (h : G.Adj v w) : C v ≠ C w :=
8080
C.map_rel h
8181

82+
lemma Coloring.injective_comp_of_pairwise_adj (C : G.Coloring α) (f : ι → V)
83+
(hf : Pairwise fun i j ↦ G.Adj (f i) (f j)) : (C ∘ f).Injective :=
84+
Function.injective_iff_pairwise_ne.2 <| hf.mono fun _ _ ↦ C.valid
85+
8286
/-- Construct a term of `SimpleGraph.Coloring` using a function that
8387
assigns vertices to colors and a proof that it is as proper coloring.
8488
@@ -129,17 +133,17 @@ instance [DecidableEq α] {c : α} :
129133
DecidablePred (· ∈ C.colorClass c) :=
130134
inferInstanceAs <| DecidablePred (· ∈ { v | C v = c })
131135

132-
variable (G)
133-
136+
variable (G) in
134137
/-- Whether a graph can be colored by at most `n` colors. -/
135138
def Colorable (n : ℕ) : Prop := Nonempty (G.Coloring (Fin n))
136139

137140
/-- The coloring of an empty graph. -/
138-
def coloringOfIsEmpty [IsEmpty V] : G.Coloring α :=
139-
Coloring.mk isEmptyElim fun {v} => isEmptyElim v
141+
def Coloring.ofIsEmpty [IsEmpty V] : G.Coloring α := .mk isEmptyElim fun {v} => isEmptyElim v
142+
143+
theorem Colorable.of_isEmpty [IsEmpty V] (n : ℕ) : G.Colorable n := ⟨.ofIsEmpty⟩
140144

141-
theorem colorable_of_isEmpty [IsEmpty V] (n : ℕ) : G.Colorable n :=
142-
⟨G.coloringOfIsEmpty⟩
145+
@[deprecated (since := "2026-01-03")] alias coloringOfIsEmpty := Coloring.ofIsEmpty
146+
@[deprecated (since := "2026-01-03")] alias colorableOfIsEmpty := Colorable.of_isEmpty
143147

144148
theorem isEmpty_of_colorable_zero (h : G.Colorable 0) : IsEmpty V := by
145149
constructor
@@ -149,39 +153,57 @@ theorem isEmpty_of_colorable_zero (h : G.Colorable 0) : IsEmpty V := by
149153

150154
@[simp]
151155
lemma colorable_zero_iff : G.Colorable 0 ↔ IsEmpty V :=
152-
G.isEmpty_of_colorable_zero, fun _ ↦ G.colorable_of_isEmpty 0
156+
⟨isEmpty_of_colorable_zero, fun _ ↦ .of_isEmpty 0
153157

154158
/-- If `G` is `n`-colorable, then mapping the vertices of `G` produces an `n`-colorable simple
155159
graph. -/
156-
theorem Colorable.map {β : Type*} (f : V ↪ β) [NeZero n] {G : SimpleGraph V} (hc : G.Colorable n) :
157-
(G.map f).Colorable n := by
160+
theorem Colorable.map (f : V ↪ β) [NeZero n] (hc : G.Colorable n) : (G.map f).Colorable n := by
158161
obtain ⟨C⟩ := hc
159162
use extend f C (const β default)
160163
intro a b ⟨_, _, hadj, ha, hb⟩
161164
rw [← ha, f.injective.extend_apply, ← hb, f.injective.extend_apply]
162165
exact C.valid hadj
163166

167+
lemma Colorable.card_le_of_pairwise_adj (hG : G.Colorable n) (f : ι → V)
168+
(hf : Pairwise fun i j ↦ G.Adj (f i) (f j)) : Nat.card ι ≤ n := by
169+
obtain ⟨C⟩ := hG
170+
simpa using Nat.card_le_card_of_injective _ (C.injective_comp_of_pairwise_adj f hf)
171+
172+
variable (G) in
164173
/-- The "tautological" coloring of a graph, using the vertices of the graph as colors. -/
165174
def selfColoring : G.Coloring V := Coloring.mk id fun {_ _} => G.ne_of_adj
166175

176+
variable (G) in
167177
/-- The chromatic number of a graph is the minimal number of colors needed to color it.
168178
This is `⊤` (infinity) iff `G` isn't colorable with finitely many colors.
169179
170180
If `G` is colorable, then `ENat.toNat G.chromaticNumber` is the `ℕ`-valued chromatic number. -/
171181
noncomputable def chromaticNumber : ℕ∞ := ⨅ n ∈ setOf G.Colorable, (n : ℕ∞)
172182

173-
lemma chromaticNumber_eq_biInf {G : SimpleGraph V} :
174-
G.chromaticNumber = ⨅ n ∈ setOf G.Colorable, (n : ℕ∞) := rfl
183+
lemma le_chromaticNumber_iff_colorable : n ≤ G.chromaticNumber ↔ ∀ m, G.Colorable m → n ≤ m := by
184+
simp [chromaticNumber]
185+
186+
lemma le_chromaticNumber_iff_coloring :
187+
n ≤ G.chromaticNumber ↔ ∀ m, G.Coloring (Fin m) → n ≤ m := by
188+
simp [le_chromaticNumber_iff_colorable, Colorable]
189+
190+
lemma le_chromaticNumber_of_pairwise_adj (hn : n ≤ Nat.card ι) (f : ι → V)
191+
(hf : Pairwise fun i j ↦ G.Adj (f i) (f j)) : n ≤ G.chromaticNumber :=
192+
le_chromaticNumber_iff_colorable.2 fun _m hm ↦ hn.trans <| hm.card_le_of_pairwise_adj f hf
175193

176-
lemma chromaticNumber_eq_iInf {G : SimpleGraph V} :
177-
G.chromaticNumber = ⨅ n : {m | G.Colorable m}, (n : ℕ∞) := by
194+
variable (G) in
195+
lemma chromaticNumber_eq_biInf : G.chromaticNumber = ⨅ n ∈ setOf G.Colorable, (n : ℕ∞) := rfl
196+
197+
variable (G) in
198+
lemma chromaticNumber_eq_iInf : G.chromaticNumber = ⨅ n : {m | G.Colorable m}, (n : ℕ∞) := by
178199
rw [chromaticNumber, iInf_subtype]
179200

180-
lemma Colorable.chromaticNumber_eq_sInf {G : SimpleGraph V} {n} (h : G.Colorable n) :
201+
lemma Colorable.chromaticNumber_eq_sInf (h : G.Colorable n) :
181202
G.chromaticNumber = sInf {n' : ℕ | G.Colorable n'} := by
182203
rw [ENat.coe_sInf, chromaticNumber]
183204
exact ⟨_, h⟩
184205

206+
variable (G) in
185207
/-- Given an embedding, there is an induced embedding of colorings. -/
186208
def recolorOfEmbedding {α β : Type*} (f : α ↪ β) : G.Coloring α ↪ G.Coloring β where
187209
toFun C := (Embedding.completeGraph f).toHom.comp C
@@ -194,9 +216,11 @@ def recolorOfEmbedding {α β : Type*} (f : α ↪ β) : G.Coloring α ↪ G.Col
194216
rw [h]
195217
rfl
196218

219+
variable (G) in
197220
@[simp] lemma coe_recolorOfEmbedding (f : α ↪ β) :
198221
⇑(G.recolorOfEmbedding f) = (Embedding.completeGraph f).toHom.comp := rfl
199222

223+
variable (G) in
200224
/-- Given an equivalence, there is an induced equivalence between colorings. -/
201225
def recolorOfEquiv {α β : Type*} (f : α ≃ β) : G.Coloring α ≃ G.Coloring β where
202226
toFun := G.recolorOfEmbedding f.toEmbedding
@@ -208,21 +232,22 @@ def recolorOfEquiv {α β : Type*} (f : α ≃ β) : G.Coloring α ≃ G.Colorin
208232
ext v
209233
apply Equiv.apply_symm_apply
210234

235+
variable (G) in
211236
@[simp] lemma coe_recolorOfEquiv (f : α ≃ β) :
212237
⇑(G.recolorOfEquiv f) = (Embedding.completeGraph f).toHom.comp := rfl
213238

239+
variable (G) in
214240
/-- There is a noncomputable embedding of `α`-colorings to `β`-colorings if
215241
`β` has at least as large a cardinality as `α`. -/
216242
noncomputable def recolorOfCardLE {α β : Type*} [Fintype α] [Fintype β]
217243
(hn : Fintype.card α ≤ Fintype.card β) : G.Coloring α ↪ G.Coloring β :=
218244
G.recolorOfEmbedding <| (Function.Embedding.nonempty_of_card_le hn).some
219245

246+
variable (G) in
220247
@[simp] lemma coe_recolorOfCardLE [Fintype α] [Fintype β] (hαβ : card α ≤ card β) :
221248
⇑(G.recolorOfCardLE hαβ) =
222249
(Embedding.completeGraph (Embedding.nonempty_of_card_le hαβ).some).toHom.comp := rfl
223250

224-
variable {G}
225-
226251
theorem Colorable.mono {n m : ℕ} (h : n ≤ m) (hc : G.Colorable n) : G.Colorable m :=
227252
⟨G.recolorOfCardLE (by simp [h]) hc.some⟩
228253

@@ -342,8 +367,7 @@ theorem colorable_of_chromaticNumber_ne_top (h : G.chromaticNumber ≠ ⊤) :
342367
exact colorable_chromaticNumber hn
343368

344369
theorem chromaticNumber_eq_zero_of_isEmpty [IsEmpty V] : G.chromaticNumber = 0 := by
345-
rw [← nonpos_iff_eq_zero, ← Nat.cast_zero, chromaticNumber_le_iff_colorable]
346-
apply colorable_of_isEmpty
370+
rw [← nonpos_iff_eq_zero, ← Nat.cast_zero, chromaticNumber_le_iff_colorable]; exact .of_isEmpty _
347371

348372
@[deprecated (since := "2025-09-15")]
349373
alias chromaticNumber_eq_zero_of_isempty := chromaticNumber_eq_zero_of_isEmpty
@@ -502,31 +526,16 @@ theorem CompleteBipartiteGraph.chromaticNumber {V W : Type*} [Nonempty V] [Nonem
502526

503527
/-! ### Cliques -/
504528

529+
theorem IsClique.card_le_of_colorable {s : Finset V} (h : G.IsClique s) (hc : G.Colorable n) :
530+
s.card ≤ n := by
531+
simpa using hc.card_le_of_pairwise_adj (Subtype.val : s → V) <| by simpa [Pairwise] using h
505532

506533
theorem IsClique.card_le_of_coloring {s : Finset V} (h : G.IsClique s) [Fintype α]
507-
(C : G.Coloring α) : s.card ≤ Fintype.card α := by
508-
rw [isClique_iff_induce_eq] at h
509-
have f : G.induce ↑s ↪g G := Embedding.comap (Function.Embedding.subtype fun x => x ∈ ↑s) G
510-
rw [h] at f
511-
convert Fintype.card_le_of_injective _ (C.comp f.toHom).injective_of_top_hom using 1
512-
simp
513-
514-
theorem IsClique.card_le_of_colorable {s : Finset V} (h : G.IsClique s) {n : ℕ}
515-
(hc : G.Colorable n) : s.card ≤ n := by
516-
convert h.card_le_of_coloring hc.some
517-
simp
534+
(C : G.Coloring α) : s.card ≤ Fintype.card α := h.card_le_of_colorable C.colorable
518535

519536
theorem IsClique.card_le_chromaticNumber {s : Finset V} (h : G.IsClique s) :
520-
s.card ≤ G.chromaticNumber := by
521-
obtain (hc | hc) := eq_or_ne G.chromaticNumber ⊤
522-
· rw [hc]
523-
exact le_top
524-
· have hc' := hc
525-
rw [chromaticNumber_ne_top_iff_exists] at hc'
526-
obtain ⟨n, c⟩ := hc'
527-
rw [← ENat.coe_toNat_eq_self] at hc
528-
rw [← hc, Nat.cast_le]
529-
exact h.card_le_of_colorable (colorable_chromaticNumber c)
537+
s.card ≤ G.chromaticNumber :=
538+
le_chromaticNumber_of_pairwise_adj (by simp) (Subtype.val : s → V) <| by simpa [Pairwise] using h
530539

531540
protected theorem Colorable.cliqueFree {n m : ℕ} (hc : G.Colorable n) (hm : n < m) :
532541
G.CliqueFree m := by

0 commit comments

Comments
 (0)