Skip to content

Commit 734b51c

Browse files
feat(Combinatorics/SimpleGraph): define extremalNumber (#19865)
Define the extremal number `extremalNumber n H` of a natural number `n` and a simple graph `H`: `extremalNumber n H` is the maximum number of edges in a `H`-free simple graph on `n` vertices, if `H` is contained in all simple graphs on `n` vertices, then this is `0`. Also define the predicate that a simple graph is an extremal graph `IsExtremal` satisfying some predicate.
1 parent 12e7ef9 commit 734b51c

File tree

3 files changed

+203
-5
lines changed

3 files changed

+203
-5
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,6 +2633,7 @@ import Mathlib.Combinatorics.SimpleGraph.Density
26332633
import Mathlib.Combinatorics.SimpleGraph.Diam
26342634
import Mathlib.Combinatorics.SimpleGraph.Ends.Defs
26352635
import Mathlib.Combinatorics.SimpleGraph.Ends.Properties
2636+
import Mathlib.Combinatorics.SimpleGraph.Extremal.Basic
26362637
import Mathlib.Combinatorics.SimpleGraph.Finite
26372638
import Mathlib.Combinatorics.SimpleGraph.Finsubgraph
26382639
import Mathlib.Combinatorics.SimpleGraph.Girth

Mathlib/Combinatorics/SimpleGraph/Copy.lean

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,18 @@ lemma IsContained.mono_left {A' : SimpleGraph α} (h_sub : A ≤ A') (h_isub : A
256256

257257
alias IsContained.trans_le' := IsContained.mono_left
258258

259-
/-- If `A ≃g B`, then `A` is contained in `C` if and only if `B` is contained in `C`. -/
260-
theorem isContained_congr (e : A ≃g B) : A ⊑ C ↔ B ⊑ C :=
261-
⟨.trans ⟨e.symm.toCopy⟩, .trans ⟨e.toCopy⟩⟩
259+
/-- If `A ≃g H` and `B ≃g G` then `A` is contained in `B` if and only if `H` is contained
260+
in `G`. -/
261+
theorem isContained_congr (e₁ : A ≃g H) (e₂ : B ≃g G) : A ⊑ B ↔ H ⊑ G :=
262+
⟨.trans' ⟨e₂.toCopy⟩ ∘ .trans ⟨e₁.symm.toCopy⟩, .trans' ⟨e₂.symm.toCopy⟩ ∘ .trans ⟨e₁.toCopy⟩⟩
263+
264+
lemma isContained_congr_left (e₁ : A ≃g B) : A ⊑ C ↔ B ⊑ C := isContained_congr e₁ .refl
265+
266+
alias ⟨_, IsContained.congr_left⟩ := isContained_congr_left
267+
268+
lemma isContained_congr_right (e₂ : B ≃g C) : A ⊑ B ↔ A ⊑ C := isContained_congr .refl e₂
269+
270+
alias ⟨_, IsContained.congr_right⟩ := isContained_congr_right
262271

263272
/-- A simple graph having no vertices is contained in any simple graph. -/
264273
lemma IsContained.of_isEmpty [IsEmpty α] : A ⊑ B :=
@@ -295,8 +304,17 @@ abbrev Free (A : SimpleGraph α) (B : SimpleGraph β) := ¬A ⊑ B
295304

296305
lemma not_free : ¬A.Free B ↔ A ⊑ B := not_not
297306

298-
/-- If `A ≃g B`, then `C` is `A`-free if and only if `C` is `B`-free. -/
299-
theorem free_congr (e : A ≃g B) : A.Free C ↔ B.Free C := (isContained_congr e).not
307+
/-- If `A ≃g H` and `B ≃g G` then `B` is `A`-free if and only if `G` is `H`-free. -/
308+
theorem free_congr (e₁ : A ≃g H) (e₂ : B ≃g G) : A.Free B ↔ H.Free G :=
309+
(isContained_congr e₁ e₂).not
310+
311+
lemma free_congr_left (e₁ : A ≃g B) : A.Free C ↔ B.Free C := free_congr e₁ .refl
312+
313+
alias ⟨_, Free.congr_left⟩ := free_congr_left
314+
315+
lemma free_congr_right (e₂ : B ≃g C) : A.Free B ↔ A.Free C := free_congr .refl e₂
316+
317+
alias ⟨_, Free.congr_right⟩ := free_congr_right
300318

301319
lemma free_bot (h : A ≠ ⊥) : A.Free (⊥ : SimpleGraph β) := by
302320
rw [← edgeSet_nonempty] at h
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/-
2+
Copyright (c) 2025 Mitchell Horner. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Mitchell Horner
5+
-/
6+
import Mathlib.Algebra.Order.Floor.Defs
7+
import Mathlib.Algebra.Order.Floor.Semiring
8+
import Mathlib.Combinatorics.SimpleGraph.Operations
9+
import Mathlib.Combinatorics.SimpleGraph.Copy
10+
11+
/-!
12+
# Extremal graph theory
13+
14+
This file introduces basic definitions for extremal graph theory, including extremal numbers.
15+
16+
## Main definitions
17+
18+
* `SimpleGraph.IsExtremal` is the predicate that `G` satisfies `p` and any `H` satisfying `p` has
19+
at most as many edges as `G`.
20+
21+
* `SimpleGraph.extremalNumber` is the maximum number of edges in a `H`-free simple graph on `n`
22+
vertices.
23+
24+
If `H` is contained in all simple graphs on `n` vertices, then this is `0`.
25+
-/
26+
27+
28+
open Finset Fintype
29+
30+
namespace SimpleGraph
31+
32+
section IsExtremal
33+
34+
variable {V : Type*} [Fintype V] {G : SimpleGraph V} [DecidableRel G.Adj]
35+
36+
/-- `G` is an extremal graph satisfying `p` if `G` has the maximum number of edges of any simple
37+
graph satisfying `p`. -/
38+
def IsExtremal (G : SimpleGraph V) [DecidableRel G.Adj] (p : SimpleGraph V → Prop) :=
39+
p G ∧ ∀ ⦃G' : SimpleGraph V⦄ [DecidableRel G'.Adj], p G' → #G'.edgeFinset ≤ #G.edgeFinset
40+
41+
lemma IsExtremal.prop {p : SimpleGraph V → Prop} (h : G.IsExtremal p) : p G := h.1
42+
43+
open Classical in
44+
/-- If one simple graph satisfies `p`, then there exists an extremal graph satisfying `p`. -/
45+
theorem exists_isExtremal_iff_exists (p : SimpleGraph V → Prop) :
46+
(∃ G : SimpleGraph V, ∃ _ : DecidableRel G.Adj, G.IsExtremal p) ↔ ∃ G, p G := by
47+
refine ⟨fun ⟨_, _, h⟩ ↦ ⟨_, h.1⟩, fun ⟨G, hp⟩ ↦ ?_⟩
48+
obtain ⟨G', hp', h⟩ := by
49+
apply exists_max_image { G | p G } (#·.edgeFinset)
50+
use G, by simpa using hp
51+
use G', inferInstanceAs (DecidableRel G'.Adj)
52+
exact ⟨by simpa using hp', fun _ _ hp ↦ by convert h _ (by simpa using hp)⟩
53+
54+
/-- If `H` has at least one edge, then there exists an extremal `H.Free` graph. -/
55+
theorem exists_isExtremal_free {W : Type*} {H : SimpleGraph W} (h : H ≠ ⊥) :
56+
∃ G : SimpleGraph V, ∃ _ : DecidableRel G.Adj, G.IsExtremal H.Free :=
57+
(exists_isExtremal_iff_exists H.Free).mpr ⟨⊥, free_bot h⟩
58+
59+
end IsExtremal
60+
61+
section ExtremalNumber
62+
63+
open Classical in
64+
/-- The extremal number of a natural number `n` and a simple graph `H` is the the maximum number of
65+
edges in a `H`-free simple graph on `n` vertices.
66+
67+
If `H` is contained in all simple graphs on `n` vertices, then this is `0`. -/
68+
noncomputable def extremalNumber (n : ℕ) {W : Type*} (H : SimpleGraph W) : ℕ :=
69+
sup { G : SimpleGraph (Fin n) | H.Free G } (#·.edgeFinset)
70+
71+
variable {n : ℕ} {V W : Type*} {G : SimpleGraph V} {H : SimpleGraph W}
72+
73+
open Classical in
74+
theorem extremalNumber_of_fintypeCard_eq [Fintype V] (hc : card V = n) :
75+
extremalNumber n H = sup { G : SimpleGraph V | H.Free G } (#·.edgeFinset) := by
76+
let e := Fintype.equivFinOfCardEq hc
77+
rw [extremalNumber, le_antisymm_iff]
78+
and_intros
79+
on_goal 1 =>
80+
replace e := e.symm
81+
all_goals
82+
rw [Finset.sup_le_iff]
83+
intro G h
84+
let G' := G.map e.toEmbedding
85+
replace h' : G' ∈ univ.filter (H.Free ·) := by
86+
rw [mem_filter, ← free_congr .refl (.map e G)]
87+
simpa using h
88+
rw [Iso.card_edgeFinset_eq (.map e G)]
89+
convert @le_sup _ _ _ _ { G | H.Free G } (#·.edgeFinset) G' h'
90+
91+
variable [Fintype V] [DecidableRel G.Adj]
92+
93+
/-- If `G` is `H`-free, then `G` has at most `extremalNumber (card V) H` edges. -/
94+
theorem card_edgeFinset_le_extremalNumber (h : H.Free G) :
95+
#G.edgeFinset ≤ extremalNumber (card V) H := by
96+
rw [extremalNumber_of_fintypeCard_eq rfl]
97+
convert @le_sup _ _ _ _ { G | H.Free G } (#·.edgeFinset) G (by simpa using h)
98+
99+
/-- If `G` has more than `extremalNumber (card V) H` edges, then `G` contains a copy of `H`. -/
100+
theorem IsContained.of_extremalNumber_lt_card_edgeFinset
101+
(h : extremalNumber (card V) H < #G.edgeFinset) : H ⊑ G := by
102+
contrapose! h
103+
exact card_edgeFinset_le_extremalNumber h
104+
105+
/-- `extremalNumber (card V) H` is at most `x` if and only if every `H`-free simple graph `G` has
106+
at most `x` edges. -/
107+
theorem extremalNumber_le_iff (H : SimpleGraph W) (m : ℕ) :
108+
extremalNumber (card V) H ≤ m ↔
109+
∀ ⦃G : SimpleGraph V⦄ [DecidableRel G.Adj], H.Free G → #G.edgeFinset ≤ m := by
110+
simp_rw [extremalNumber_of_fintypeCard_eq rfl, Finset.sup_le_iff, mem_filter, mem_univ, true_and]
111+
exact ⟨fun h _ _ h' ↦ by convert h _ h', fun h _ h' ↦ by convert h h'⟩
112+
113+
/-- `extremalNumber (card V) H` is greater than `x` if and only if there exists a `H`-free simple
114+
graph `G` with more than `x` edges. -/
115+
theorem lt_extremalNumber_iff (H : SimpleGraph W) (m : ℕ) :
116+
m < extremalNumber (card V) H ↔
117+
∃ G : SimpleGraph V, ∃ _ : DecidableRel G.Adj, H.Free G ∧ m < #G.edgeFinset := by
118+
simp_rw [extremalNumber_of_fintypeCard_eq rfl, Finset.lt_sup_iff, mem_filter, mem_univ, true_and]
119+
exact ⟨fun ⟨_, h, h'⟩ ↦ ⟨_, _, h, h'⟩, fun ⟨_, _, h, h'⟩ ↦ ⟨_, h, by convert h'⟩⟩
120+
121+
variable {R : Type*} [Semiring R] [LinearOrder R] [FloorSemiring R]
122+
123+
@[inherit_doc extremalNumber_le_iff]
124+
theorem extremalNumber_le_iff_of_nonneg (H : SimpleGraph W) {m : R} (h : 0 ≤ m) :
125+
extremalNumber (card V) H ≤ m ↔
126+
∀ ⦃G : SimpleGraph V⦄ [DecidableRel G.Adj], H.Free G → #G.edgeFinset ≤ m := by
127+
simp_rw [← Nat.le_floor_iff h]
128+
exact extremalNumber_le_iff H ⌊m⌋₊
129+
130+
@[inherit_doc lt_extremalNumber_iff]
131+
theorem lt_extremalNumber_iff_of_nonneg (H : SimpleGraph W) {m : R} (h : 0 ≤ m) :
132+
m < extremalNumber (card V) H ↔
133+
∃ G : SimpleGraph V, ∃ _ : DecidableRel G.Adj, H.Free G ∧ m < #G.edgeFinset := by
134+
simp_rw [← Nat.floor_lt h]
135+
exact lt_extremalNumber_iff H ⌊m⌋₊
136+
137+
/-- If `H` contains a copy of `H'`, then `extremalNumber n H` is at most `extremalNumber n H`. -/
138+
theorem IsContained.extremalNumber_le {W' : Type*} {H' : SimpleGraph W'} (h : H' ⊑ H) :
139+
extremalNumber n H' ≤ extremalNumber n H := by
140+
rw [← Fintype.card_fin n, extremalNumber_le_iff]
141+
intro _ _ h'
142+
contrapose! h'
143+
rw [not_not]
144+
exact h.trans (IsContained.of_extremalNumber_lt_card_edgeFinset h')
145+
146+
/-- If `H₁ ≃g H₂`, then `extremalNumber n H₁` equals `extremalNumber n H₂`. -/
147+
@[congr]
148+
theorem extremalNumber_congr {n₁ n₂ : ℕ} {W₁ W₂ : Type*} {H₁ : SimpleGraph W₁}
149+
{H₂ : SimpleGraph W₂} (h : n₁ = n₂) (e : H₁ ≃g H₂) :
150+
extremalNumber n₁ H₁ = extremalNumber n₂ H₂ := by
151+
rw [h, le_antisymm_iff]
152+
and_intros
153+
on_goal 2 =>
154+
replace e := e.symm
155+
all_goals
156+
rw [← Fintype.card_fin n₂, extremalNumber_le_iff]
157+
intro G _ h
158+
apply card_edgeFinset_le_extremalNumber
159+
contrapose! h
160+
rw [not_free] at h ⊢
161+
exact h.trans' ⟨e.toCopy⟩
162+
163+
/-- If `H₁ ≃g H₂`, then `extremalNumber n H₁` equals `extremalNumber n H₂`. -/
164+
theorem extremalNumber_congr_right {W₁ W₂ : Type*} {H₁ : SimpleGraph W₁} {H₂ : SimpleGraph W₂}
165+
(e : H₁ ≃g H₂) : extremalNumber n H₁ = extremalNumber n H₂ := extremalNumber_congr rfl e
166+
167+
/-- `H`-free extremal graphs are `H`-free simple graphs having `extremalNumber (card V) H` many
168+
edges. -/
169+
theorem isExtremal_free_iff :
170+
G.IsExtremal H.Free ↔ H.Free G ∧ #G.edgeFinset = extremalNumber (card V) H := by
171+
rw [IsExtremal, and_congr_right_iff, ← extremalNumber_le_iff]
172+
exact fun h ↦ ⟨eq_of_le_of_le (card_edgeFinset_le_extremalNumber h), ge_of_eq⟩
173+
174+
lemma card_edgeFinset_of_isExtremal_free (h : G.IsExtremal H.Free) :
175+
#G.edgeFinset = extremalNumber (card V) H := (isExtremal_free_iff.mp h).2
176+
177+
end ExtremalNumber
178+
179+
end SimpleGraph

0 commit comments

Comments
 (0)