Skip to content

Commit 35c93d9

Browse files
committed
feat: Construct a tripartite graph from its triangles (#12570)
Both the lower bound of the Ruzsa-Szemerédi problem and the proof of the corners theorem define an auxiliary tripartite graph by specifying its triangles and showing that there are no more. This PR provides the boilerplate for this construction. It greatly simplifies both proofs. Co-authored-by: Bhavik Mehta <bhavik.mehta8@gmail.com>
1 parent 5e84313 commit 35c93d9

File tree

2 files changed

+246
-0
lines changed

2 files changed

+246
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,6 +1678,7 @@ import Mathlib.Combinatorics.SimpleGraph.Trails
16781678
import Mathlib.Combinatorics.SimpleGraph.Triangle.Basic
16791679
import Mathlib.Combinatorics.SimpleGraph.Triangle.Counting
16801680
import Mathlib.Combinatorics.SimpleGraph.Triangle.Removal
1681+
import Mathlib.Combinatorics.SimpleGraph.Triangle.Tripartite
16811682
import Mathlib.Combinatorics.SimpleGraph.Turan
16821683
import Mathlib.Combinatorics.Young.SemistandardTableau
16831684
import Mathlib.Combinatorics.Young.YoungDiagram
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/-
2+
Copyright (c) 2023 Yaël Dillies, Bhavik Mehta. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yaël Dillies, Bhavik Mehta
5+
-/
6+
import Mathlib.Combinatorics.SimpleGraph.Triangle.Basic
7+
8+
/-!
9+
# Construct a tripartite graph from its triangles
10+
11+
This file contains the construction of a simple graph on `α ⊕ β ⊕ γ` from a list of triangles
12+
`(a, b, c)` (with `a` in the first component, `b` in the second, `c` in the third).
13+
14+
We call
15+
* `t : Finset (α × β × γ)` the set of *triangle indices* (its elements are not triangles within the
16+
graph but instead index them).
17+
* *explicit* a triangle of the constructed graph coming from a triangle index.
18+
* *accidental* a triangle of the constructed graph not coming from a triangle index.
19+
20+
The two important properties of this construction are:
21+
* `SimpleGraph.TripartiteFromTriangles.ExplicitDisjoint`: Whether the explicit triangles are
22+
edge-disjoint.
23+
* `SimpleGraph.TripartiteFromTriangles.NoAccidental`: Whether all triangles are explicit.
24+
25+
This construction shows up unrelatedly twice in the theory of Roth numbers:
26+
* The lower bound of the Ruzsa-Szemerédi problem: From a set `s` in a finite abelian group `G` of
27+
odd order, we construct a tripartite graph on `G ⊕ G ⊕ G`. The triangle indices are
28+
`(x, x + a, x + 2 * a)` for `x` any element and `a ∈ s`. The explicit triangles are always
29+
edge-disjoint and there is no accidental triangle if `s` is 3AP-free.
30+
* The proof of the corners theorem from the triangle removal lemma: For a set `s` in a finite
31+
abelian group `G`, we construct a tripartite graph on `G ⊕ G ⊕ G`, whose vertices correspond to
32+
the horizontal, vertical and diagonal lines in `G × G`. The explicit triangles are `(h, v, d)`
33+
where `h`, `v`, `d` are horizontal, vertical, diagonal lines that intersect in an element of `s`.
34+
The explicit triangles are always edge-disjoint and there is no accidental triangle if `s` is
35+
corner-free.
36+
-/
37+
38+
open Finset Function Sum3
39+
40+
variable {α β γ 𝕜 : Type*} [LinearOrderedField 𝕜] {t : Finset (α × β × γ)} {a a' : α} {b b' : β}
41+
{c c' : γ} {x : α × β × γ} {ε : 𝕜}
42+
43+
namespace SimpleGraph
44+
namespace TripartiteFromTriangles
45+
46+
/-- The underlying relation of the tripartite-from-triangles graph.
47+
48+
Two vertices are related iff there exists a triangle index containing them both. -/
49+
@[mk_iff] inductive Rel (t : Finset (α × β × γ)) : α ⊕ β ⊕ γ → α ⊕ β ⊕ γ → Prop
50+
| in₀₁ ⦃a b c⦄ : (a, b, c) ∈ t → Rel t (in₀ a) (in₁ b)
51+
| in₁₀ ⦃a b c⦄ : (a, b, c) ∈ t → Rel t (in₁ b) (in₀ a)
52+
| in₀₂ ⦃a b c⦄ : (a, b, c) ∈ t → Rel t (in₀ a) (in₂ c)
53+
| in₂₀ ⦃a b c⦄ : (a, b, c) ∈ t → Rel t (in₂ c) (in₀ a)
54+
| in₁₂ ⦃a b c⦄ : (a, b, c) ∈ t → Rel t (in₁ b) (in₂ c)
55+
| in₂₁ ⦃a b c⦄ : (a, b, c) ∈ t → Rel t (in₂ c) (in₁ b)
56+
57+
open Rel
58+
59+
lemma rel_irrefl : ∀ x, ¬ Rel t x x := fun _x hx ↦ nomatch hx
60+
lemma rel_symm : Symmetric (Rel t) := fun x y h ↦ by cases h <;> constructor <;> assumption
61+
62+
/-- The tripartite-from-triangles graph. Two vertices are related iff there exists a triangle index
63+
containing them both. -/
64+
def graph (t : Finset (α × β × γ)) : SimpleGraph (α ⊕ β ⊕ γ) := ⟨Rel t, rel_symm, rel_irrefl⟩
65+
66+
namespace Graph
67+
68+
@[simp] lemma not_in₀₀ : ¬ (graph t).Adj (in₀ a) (in₀ a') := fun h ↦ nomatch h
69+
@[simp] lemma not_in₁₁ : ¬ (graph t).Adj (in₁ b) (in₁ b') := fun h ↦ nomatch h
70+
@[simp] lemma not_in₂₂ : ¬ (graph t).Adj (in₂ c) (in₂ c') := fun h ↦ nomatch h
71+
72+
@[simp] lemma in₀₁_iff : (graph t).Adj (in₀ a) (in₁ b) ↔ ∃ c, (a, b, c) ∈ t :=
73+
by rintro ⟨⟩; exact ⟨_, ‹_›⟩, fun ⟨_, h⟩ ↦ in₀₁ h⟩
74+
@[simp] lemma in₁₀_iff : (graph t).Adj (in₁ b) (in₀ a) ↔ ∃ c, (a, b, c) ∈ t :=
75+
by rintro ⟨⟩; exact ⟨_, ‹_›⟩, fun ⟨_, h⟩ ↦ in₁₀ h⟩
76+
@[simp] lemma in₀₂_iff : (graph t).Adj (in₀ a) (in₂ c) ↔ ∃ b, (a, b, c) ∈ t :=
77+
by rintro ⟨⟩; exact ⟨_, ‹_›⟩, fun ⟨_, h⟩ ↦ in₀₂ h⟩
78+
@[simp] lemma in₂₀_iff : (graph t).Adj (in₂ c) (in₀ a) ↔ ∃ b, (a, b, c) ∈ t :=
79+
by rintro ⟨⟩; exact ⟨_, ‹_›⟩, fun ⟨_, h⟩ ↦ in₂₀ h⟩
80+
@[simp] lemma in₁₂_iff : (graph t).Adj (in₁ b) (in₂ c) ↔ ∃ a, (a, b, c) ∈ t :=
81+
by rintro ⟨⟩; exact ⟨_, ‹_›⟩, fun ⟨_, h⟩ ↦ in₁₂ h⟩
82+
@[simp] lemma in₂₁_iff : (graph t).Adj (in₂ c) (in₁ b) ↔ ∃ a, (a, b, c) ∈ t :=
83+
by rintro ⟨⟩; exact ⟨_, ‹_›⟩, fun ⟨_, h⟩ ↦ in₂₁ h⟩
84+
85+
lemma in₀₁_iff' :
86+
(graph t).Adj (in₀ a) (in₁ b) ↔ ∃ x : α × β × γ, x ∈ t ∧ x.1 = a ∧ x.2.1 = b where
87+
mp := by rintro ⟨⟩; exact ⟨_, ‹_›, by simp⟩
88+
mpr := by rintro ⟨⟨a, b, c⟩, h, rfl, rfl⟩; constructor; assumption
89+
lemma in₁₀_iff' :
90+
(graph t).Adj (in₁ b) (in₀ a) ↔ ∃ x : α × β × γ, x ∈ t ∧ x.2.1 = b ∧ x.1 = a where
91+
mp := by rintro ⟨⟩; exact ⟨_, ‹_›, by simp⟩
92+
mpr := by rintro ⟨⟨a, b, c⟩, h, rfl, rfl⟩; constructor; assumption
93+
lemma in₀₂_iff' :
94+
(graph t).Adj (in₀ a) (in₂ c) ↔ ∃ x : α × β × γ, x ∈ t ∧ x.1 = a ∧ x.2.2 = c where
95+
mp := by rintro ⟨⟩; exact ⟨_, ‹_›, by simp⟩
96+
mpr := by rintro ⟨⟨a, b, c⟩, h, rfl, rfl⟩; constructor; assumption
97+
lemma in₂₀_iff' :
98+
(graph t).Adj (in₂ c) (in₀ a) ↔ ∃ x : α × β × γ, x ∈ t ∧ x.2.2 = c ∧ x.1 = a where
99+
mp := by rintro ⟨⟩; exact ⟨_, ‹_›, by simp⟩
100+
mpr := by rintro ⟨⟨a, b, c⟩, h, rfl, rfl⟩; constructor; assumption
101+
lemma in₁₂_iff' :
102+
(graph t).Adj (in₁ b) (in₂ c) ↔ ∃ x : α × β × γ, x ∈ t ∧ x.2.1 = b ∧ x.2.2 = c where
103+
mp := by rintro ⟨⟩; exact ⟨_, ‹_›, by simp⟩
104+
mpr := by rintro ⟨⟨a, b, c⟩, h, rfl, rfl⟩; constructor; assumption
105+
lemma in₂₁_iff' :
106+
(graph t).Adj (in₂ c) (in₁ b) ↔ ∃ x : α × β × γ, x ∈ t ∧ x.2.2 = c ∧ x.2.1 = b where
107+
mp := by rintro ⟨⟩; exact ⟨_, ‹_›, by simp⟩
108+
mpr := by rintro ⟨⟨a, b, c⟩, h, rfl, rfl⟩; constructor; assumption
109+
110+
end Graph
111+
112+
open Graph
113+
114+
/-- Predicate on the triangle indices for the explicit triangles to be edge-disjoint. -/
115+
class ExplicitDisjoint (t : Finset (α × β × γ)) : Prop where
116+
inj₀ : ∀ ⦃a b c a'⦄, (a, b, c) ∈ t → (a', b, c) ∈ t → a = a'
117+
inj₁ : ∀ ⦃a b c b'⦄, (a, b, c) ∈ t → (a, b', c) ∈ t → b = b'
118+
inj₂ : ∀ ⦃a b c c'⦄, (a, b, c) ∈ t → (a, b, c') ∈ t → c = c'
119+
120+
/-- Predicate on the triangle indices for there to be no accidental triangle.
121+
122+
Note that we cheat a bit, since the exact translation of this informal description would have
123+
`(a', b', c') ∈ t` as a conclusion rather than `a = a' ∨ b = b' ∨ c = c'`. Those conditions are
124+
equivalent when the explicit triangles are edge-disjoint (which is the case we care about). -/
125+
class NoAccidental (t : Finset (α × β × γ)) : Prop where
126+
eq_or_eq_or_eq : ∀ ⦃a a' b b' c c'⦄, (a', b, c) ∈ t → (a, b', c) ∈ t → (a, b, c') ∈ t →
127+
a = a' ∨ b = b' ∨ c = c'
128+
129+
section DecidableEq
130+
variable [DecidableEq α] [DecidableEq β] [DecidableEq γ]
131+
132+
instance graph.instDecidableRelAdj : DecidableRel (graph t).Adj
133+
| in₀ _a, in₀ _a' => Decidable.isFalse not_in₀₀
134+
| in₀ _a, in₁ _b' => decidable_of_iff' _ in₀₁_iff'
135+
| in₀ _a, in₂ _c' => decidable_of_iff' _ in₀₂_iff'
136+
| in₁ _b, in₀ _a' => decidable_of_iff' _ in₁₀_iff'
137+
| in₁ _b, in₁ _b' => Decidable.isFalse not_in₁₁
138+
| in₁ _b, in₂ _b' => decidable_of_iff' _ in₁₂_iff'
139+
| in₂ _c, in₀ _a' => decidable_of_iff' _ in₂₀_iff'
140+
| in₂ _c, in₁ _b' => decidable_of_iff' _ in₂₁_iff'
141+
| in₂ _c, in₂ _b' => Decidable.isFalse not_in₂₂
142+
143+
/-- This lemma reorders the elements of a triangle in the tripartite graph. It turns a triangle
144+
`{x, y, z}` into a triangle `{a, b, c}` where `a : α `, `b : β`, `c : γ`. -/
145+
lemma graph_triple ⦃x y z⦄ :
146+
(graph t).Adj x y → (graph t).Adj x z → (graph t).Adj y z → ∃ a b c,
147+
({in₀ a, in₁ b, in₂ c} : Finset (α ⊕ β ⊕ γ)) = {x, y, z} ∧ (graph t).Adj (in₀ a) (in₁ b) ∧
148+
(graph t).Adj (in₀ a) (in₂ c) ∧ (graph t).Adj (in₁ b) (in₂ c) := by
149+
rintro (_ | _ | _) (_ | _ | _) (_ | _ | _) <;>
150+
refine ⟨_, _, _, by ext; simp only [Finset.mem_insert, Finset.mem_singleton]; try tauto,
151+
?_, ?_, ?_⟩ <;> constructor <;> assumption
152+
153+
/-- The map that turns a triangle index into an explicit triangle. -/
154+
@[simps] def toTriangle : α × β × γ ↪ Finset (α ⊕ β ⊕ γ) where
155+
toFun x := {in₀ x.1, in₁ x.2.1, in₂ x.2.2}
156+
inj' := fun ⟨a, b, c⟩ ⟨a', b', c'⟩ ↦ by simpa only [Finset.Subset.antisymm_iff, Finset.subset_iff,
157+
mem_insert, mem_singleton, forall_eq_or_imp, forall_eq, Prod.mk.inj_iff, or_false, false_or,
158+
in₀, in₁, in₂, Sum.inl.inj_iff, Sum.inr.inj_iff] using And.left
159+
160+
lemma toTriangle_is3Clique (hx : x ∈ t) : (graph t).IsNClique 3 (toTriangle x) := by
161+
simp only [toTriangle_apply, is3Clique_triple_iff, in₀₁_iff, in₀₂_iff, in₁₂_iff]
162+
exact ⟨⟨_, hx⟩, ⟨_, hx⟩, _, hx⟩
163+
164+
lemma exists_mem_toTriangle {x y : α ⊕ β ⊕ γ} (hxy : (graph t).Adj x y) :
165+
∃ z ∈ t, x ∈ toTriangle z ∧ y ∈ toTriangle z := by cases hxy <;> exact ⟨_, ‹_›, by simp⟩
166+
167+
nonrec lemma is3Clique_iff [NoAccidental t] {s : Finset (α ⊕ β ⊕ γ)} :
168+
(graph t).IsNClique 3 s ↔ ∃ x, x ∈ t ∧ toTriangle x = s := by
169+
refine ⟨fun h ↦ ?_, ?_⟩
170+
· rw [is3Clique_iff] at h
171+
obtain ⟨x, y, z, hxy, hxz, hyz, rfl⟩ := h
172+
obtain ⟨a, b, c, habc, hab, hac, hbc⟩ := graph_triple hxy hxz hyz
173+
refine ⟨(a, b, c), ?_, habc⟩
174+
obtain ⟨c', hc'⟩ := in₀₁_iff.1 hab
175+
obtain ⟨b', hb'⟩ := in₀₂_iff.1 hac
176+
obtain ⟨a', ha'⟩ := in₁₂_iff.1 hbc
177+
obtain rfl | rfl | rfl := NoAccidental.eq_or_eq_or_eq ha' hb' hc' <;> assumption
178+
· rintro ⟨x, hx, rfl⟩
179+
exact toTriangle_is3Clique hx
180+
181+
lemma toTriangle_surjOn [NoAccidental t] :
182+
(t : Set (α × β × γ)).SurjOn toTriangle ((graph t).cliqueSet 3) := fun _ ↦ is3Clique_iff.1
183+
184+
variable (t)
185+
186+
lemma map_toTriangle_disjoint [ExplicitDisjoint t] :
187+
(t.map toTriangle : Set (Finset (α ⊕ β ⊕ γ))).Pairwise
188+
fun x y ↦ (x ∩ y : Set (α ⊕ β ⊕ γ)).Subsingleton := by
189+
clear x
190+
intro
191+
simp only [Finset.coe_map, Set.mem_image, Finset.mem_coe, Prod.exists, Ne,
192+
forall_exists_index, and_imp]
193+
rintro a b c habc rfl e x y z hxyz rfl h'
194+
have := ne_of_apply_ne _ h'
195+
simp only [Ne, Prod.mk.inj_iff, not_and] at this
196+
simp only [toTriangle_apply, in₀, in₁, in₂, Set.mem_inter_iff, mem_insert, mem_singleton,
197+
mem_coe, and_imp, Sum.forall, or_false, forall_eq, false_or, eq_self_iff_true, imp_true_iff,
198+
true_and, and_true, Set.Subsingleton]
199+
suffices ¬ (a = x ∧ b = y) ∧ ¬ (a = x ∧ c = z) ∧ ¬ (b = y ∧ c = z) by aesop
200+
refine ⟨?_, ?_, ?_⟩
201+
· rintro ⟨rfl, rfl⟩
202+
exact this rfl rfl (ExplicitDisjoint.inj₂ habc hxyz)
203+
· rintro ⟨rfl, rfl⟩
204+
exact this rfl (ExplicitDisjoint.inj₁ habc hxyz) rfl
205+
· rintro ⟨rfl, rfl⟩
206+
exact this (ExplicitDisjoint.inj₀ habc hxyz) rfl rfl
207+
208+
lemma cliqueSet_eq_image [NoAccidental t] : (graph t).cliqueSet 3 = toTriangle '' t := by
209+
ext; exact is3Clique_iff
210+
211+
section Fintype
212+
variable [Fintype α] [Fintype β] [Fintype γ]
213+
214+
lemma cliqueFinset_eq_image [NoAccidental t] : (graph t).cliqueFinset 3 = t.image toTriangle :=
215+
coe_injective $ by push_cast; exact cliqueSet_eq_image _
216+
217+
lemma cliqueFinset_eq_map [NoAccidental t] : (graph t).cliqueFinset 3 = t.map toTriangle := by
218+
simp [cliqueFinset_eq_image, map_eq_image]
219+
220+
@[simp] lemma card_triangles [NoAccidental t] : ((graph t).cliqueFinset 3).card = t.card := by
221+
rw [cliqueFinset_eq_map, card_map]
222+
223+
lemma farFromTriangleFree [ExplicitDisjoint t] {ε : 𝕜}
224+
(ht : ε * ((Fintype.card α + Fintype.card β + Fintype.card γ) ^ 2 : ℕ) ≤ t.card) :
225+
(graph t).FarFromTriangleFree ε :=
226+
farFromTriangleFree_of_disjoint_triangles (t.map toTriangle)
227+
(map_subset_iff_subset_preimage.2 fun x hx ↦ by simpa using toTriangle_is3Clique hx)
228+
(map_toTriangle_disjoint t) $ by simpa [add_assoc] using ht
229+
230+
end Fintype
231+
end DecidableEq
232+
233+
variable (t)
234+
235+
lemma locallyLinear [ExplicitDisjoint t] [NoAccidental t] : (graph t).LocallyLinear := by
236+
classical
237+
refine ⟨?_, fun x y hxy ↦ ?_⟩
238+
· unfold EdgeDisjointTriangles
239+
convert map_toTriangle_disjoint t
240+
rw [cliqueSet_eq_image, coe_map]
241+
· obtain ⟨z, hz, hxy⟩ := exists_mem_toTriangle hxy
242+
exact ⟨_, toTriangle_is3Clique hz, hxy⟩
243+
244+
end TripartiteFromTriangles
245+
end SimpleGraph

0 commit comments

Comments
 (0)