forked from leanprover-community/mathlib4
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFriendshipGraphs.lean
More file actions
336 lines (291 loc) · 14.1 KB
/
Copy pathFriendshipGraphs.lean
File metadata and controls
336 lines (291 loc) · 14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
/-
Copyright (c) 2020 Aaron Anderson. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Aaron Anderson, Jalex Stark, Kyle Miller
-/
import Mathlib.Combinatorics.SimpleGraph.AdjMatrix
import Mathlib.LinearAlgebra.Matrix.Charpoly.FiniteField
/-!
# The Friendship Theorem
## Definitions and Statement
- A `Friendship` graph is one in which any two distinct vertices have exactly one neighbor in common
- A `Politician`, at least in the context of this problem, is a vertex in a graph which is adjacent
to every other vertex.
- The friendship theorem (Erdős, Rényi, Sós 1966) states that every finite friendship graph has a
politician.
## Proof outline
The proof revolves around the theory of adjacency matrices, although some steps could equivalently
be phrased in terms of counting walks.
- Assume `G` is a finite friendship graph.
- First we show that any two nonadjacent vertices have the same degree
- Assume for contradiction that `G` does not have a politician.
- Conclude from the last two points that `G` is `d`-regular for some `d : ℕ`.
- Show that `G` has `d ^ 2 - d + 1` vertices.
- By casework, show that if `d = 0, 1, 2`, then `G` has a politician.
- If `3 ≤ d`, let `p` be a prime factor of `d - 1`.
- If `A` is the adjacency matrix of `G` with entries in `ℤ/pℤ`, we show that `A ^ p` has trace `1`.
- This gives a contradiction, as `A` has trace `0`, and thus `A ^ p` has trace `0`.
## References
- [P. Erdős, A. Rényi, V. Sós, *On A Problem of Graph Theory*][erdosrenyisos]
- [C. Huneke, *The Friendship Theorem*][huneke2002]
-/
namespace Theorems100
noncomputable section
open Finset SimpleGraph Matrix
universe u v
variable {V : Type u} {R : Type v} [Semiring R]
section FriendshipDef
variable (G : SimpleGraph V)
open scoped Classical in
/-- This property of a graph is the hypothesis of the friendship theorem:
every pair of nonadjacent vertices has exactly one common friend,
a vertex to which both are adjacent.
-/
def Friendship [Fintype V] : Prop :=
∀ ⦃v w : V⦄, v ≠ w → Fintype.card (G.commonNeighbors v w) = 1
/-- A politician is a vertex that is adjacent to all other vertices.
-/
def ExistsPolitician : Prop :=
∃ v : V, ∀ w : V, v ≠ w → G.Adj v w
end FriendshipDef
variable [Fintype V] {G : SimpleGraph V} {d : ℕ} (hG : Friendship G)
namespace Friendship
variable (R)
set_option backward.isDefEq.respectTransparency false in
open scoped Classical in
include hG in
/-- One characterization of a friendship graph is that there is exactly one walk of length 2
between distinct vertices. These walks are counted in off-diagonal entries of the square of
the adjacency matrix, so for a friendship graph, those entries are all 1. -/
theorem adjMatrix_sq_of_ne {v w : V} (hvw : v ≠ w) :
(G.adjMatrix R ^ 2 : Matrix V V R) v w = 1 := by
rw [sq, ← Nat.cast_one, ← hG hvw]
simp only [mul_adjMatrix_apply, neighborFinset_eq_filter, adjMatrix_apply,
sum_boole, filter_filter, and_comm, commonNeighbors,
Fintype.card_ofFinset (s := filter (fun x ↦ x ∈ G.neighborSet v ∩ G.neighborSet w) univ),
Set.mem_inter_iff, mem_neighborSet]
open scoped Classical in
include hG in
/-- This calculation amounts to counting the number of length 3 walks between nonadjacent vertices.
We use it to show that nonadjacent vertices have equal degrees. -/
theorem adjMatrix_pow_three_of_not_adj {v w : V} (non_adj : ¬G.Adj v w) :
(G.adjMatrix R ^ 3 : Matrix V V R) v w = degree G v := by
rw [pow_succ', adjMatrix_mul_apply, degree, card_eq_sum_ones, Nat.cast_sum]
apply sum_congr rfl
intro x hx
rw [adjMatrix_sq_of_ne _ hG, Nat.cast_one]
rintro ⟨rfl⟩
rw [mem_neighborFinset] at hx
exact non_adj hx
variable {R}
open scoped Classical in
include hG in
/-- As `v` and `w` not being adjacent implies
`degree G v = ((G.adjMatrix R) ^ 3) v w` and `degree G w = ((G.adjMatrix R) ^ 3) v w`,
the degrees are equal if `((G.adjMatrix R) ^ 3) v w = ((G.adjMatrix R) ^ 3) w v`
This is true as the adjacency matrix is symmetric. -/
theorem degree_eq_of_not_adj {v w : V} (hvw : ¬G.Adj v w) : degree G v = degree G w := by
rw [← Nat.cast_id (G.degree v), ← Nat.cast_id (G.degree w),
← adjMatrix_pow_three_of_not_adj ℕ hG hvw,
← adjMatrix_pow_three_of_not_adj ℕ hG fun h ↦ hvw h.symm]
conv_lhs => rw [← transpose_adjMatrix]
simp only [pow_succ _ 2, sq, ← transpose_mul, transpose_apply]
simp only [mul_assoc]
open scoped Classical in
include hG in
/-- Let `A` be the adjacency matrix of a graph `G`.
If `G` is a friendship graph, then all of the off-diagonal entries of `A^2` are 1.
If `G` is `d`-regular, then all of the diagonal entries of `A^2` are `d`.
Putting these together determines `A^2` exactly for a `d`-regular friendship graph. -/
theorem adjMatrix_sq_of_regular (hd : G.IsRegularOfDegree d) :
G.adjMatrix R ^ 2 = of fun v w => if v = w then (d : R) else (1 : R) := by
ext (v w); by_cases h : v = w
· rw [h, sq, adjMatrix_mul_self_apply_self, hd]; simp
· rw [adjMatrix_sq_of_ne R hG h, of_apply, if_neg h]
open scoped Classical in
include hG in
theorem adjMatrix_sq_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1)
(hd : G.IsRegularOfDegree d) : G.adjMatrix (ZMod p) ^ 2 = of fun _ _ => 1 := by
simp [adjMatrix_sq_of_regular hG hd, dmod]
section Nonempty
variable [Nonempty V]
open scoped Classical in
include hG in
/-- If `G` is a friendship graph without a politician (a vertex adjacent to all others), then
it is regular. We have shown that nonadjacent vertices of a friendship graph have the same degree,
and if there isn't a politician, we can show this for adjacent vertices by finding a vertex
neither is adjacent to, and then using transitivity. -/
theorem isRegularOf_not_existsPolitician (hG' : ¬ExistsPolitician G) :
∃ d : ℕ, G.IsRegularOfDegree d := by
have v := Classical.arbitrary V
use G.degree v
intro x
by_cases hvx : G.Adj v x; swap; · exact (degree_eq_of_not_adj hG hvx).symm
dsimp only [Theorems100.ExistsPolitician] at hG'
push Not at hG'
rcases hG' v with ⟨w, hvw', hvw⟩
rcases hG' x with ⟨y, hxy', hxy⟩
by_cases hxw : G.Adj x w
swap; · rw [degree_eq_of_not_adj hG hvw]; exact degree_eq_of_not_adj hG hxw
rw [degree_eq_of_not_adj hG hxy]
by_cases hvy : G.Adj v y
swap; · exact (degree_eq_of_not_adj hG hvy).symm
rw [degree_eq_of_not_adj hG hvw]
apply degree_eq_of_not_adj hG
intro hcontra
rcases Finset.card_eq_one.mp (hG hvw') with ⟨⟨a, ha⟩, h⟩
have key : ∀ {x}, x ∈ G.commonNeighbors v w → x = a := by
intro x hx
have h' : ⟨x, hx⟩ ∈ (univ : Finset (G.commonNeighbors v w)) := mem_univ (Subtype.mk x hx)
rw [h, mem_singleton] at h'
injection h'
apply hxy'
rw [key ((mem_commonNeighbors G).mpr ⟨hvx, hxw.symm⟩),
key ((mem_commonNeighbors G).mpr ⟨hvy, hcontra.symm⟩)]
open scoped Classical in
include hG in
set_option backward.isDefEq.respectTransparency.types false in
/-- Let `A` be the adjacency matrix of a `d`-regular friendship graph, and let `v` be a vector
all of whose components are `1`. Then `v` is an eigenvector of `A ^ 2`, and we can compute
the eigenvalue to be `d * d`, or as `d + (Fintype.card V - 1)`, so those quantities must be equal.
This essentially means that the graph has `d ^ 2 - d + 1` vertices. -/
theorem card_of_regular (hd : G.IsRegularOfDegree d) : d + (Fintype.card V - 1) = d * d := by
have v := Classical.arbitrary V
trans ((G.adjMatrix ℕ ^ 2) *ᵥ (fun _ => 1)) v
· rw [adjMatrix_sq_of_regular hG hd, mulVec, dotProduct, ← insert_erase (mem_univ v)]
simp only [sum_insert, mul_one, if_true, Nat.cast_id, mem_erase, not_true,
Ne, not_false_iff, add_right_inj, false_and, of_apply]
rw [Finset.sum_const_nat, card_erase_of_mem (mem_univ v), mul_one]; · rfl
intro x hx; simp [(ne_of_mem_erase hx).symm]
· rw [sq, ← mulVec_mulVec]
simp only [adjMatrix_mulVec_const_apply_of_regular hd, neighborFinset,
card_neighborSet_eq_degree, hd v, Function.const_def, adjMatrix_mulVec_apply _ _ (mulVec _ _),
mul_one, sum_const, Set.toFinset_card, smul_eq_mul, Nat.cast_id]
open scoped Classical in
include hG in
/-- The size of a `d`-regular friendship graph is `1 mod (d-1)`, and thus `1 mod p` for a
factor `p ∣ d-1`. -/
theorem card_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1) (hd : G.IsRegularOfDegree d) :
(Fintype.card V : ZMod p) = 1 := by
have hpos : 0 < Fintype.card V := Fintype.card_pos_iff.mpr inferInstance
rw [← Nat.succ_pred_eq_of_pos hpos, Nat.succ_eq_add_one, Nat.pred_eq_sub_one]
simp only [add_eq_right, Nat.cast_add, Nat.cast_one]
have h := congr_arg (fun n : ℕ => (n : ZMod p)) (card_of_regular hG hd)
revert h; simp [dmod]
end Nonempty
open scoped Classical in
theorem adjMatrix_sq_mul_const_one_of_regular (hd : G.IsRegularOfDegree d) :
G.adjMatrix R * of (fun _ _ => 1) = of (fun _ _ => (d : R)) := by
ext x
simp only [← hd x, degree, adjMatrix_mul_apply, sum_const, Nat.smul_one_eq_cast, of_apply]
open scoped Classical in
theorem adjMatrix_mul_const_one_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1)
(hd : G.IsRegularOfDegree d) :
G.adjMatrix (ZMod p) * of (fun _ _ => 1) = of (fun _ _ => 1) := by
rw [adjMatrix_sq_mul_const_one_of_regular hd, dmod]
open scoped Classical in
include hG in
/-- Modulo a factor of `d-1`, the square and all higher powers of the adjacency matrix
of a `d`-regular friendship graph reduce to the matrix whose entries are all 1. -/
theorem adjMatrix_pow_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1)
(hd : G.IsRegularOfDegree d) {k : ℕ} (hk : 2 ≤ k) :
G.adjMatrix (ZMod p) ^ k = of (fun _ _ => 1) := by
match k with
| 0 | 1 => exfalso; linarith
| k + 2 =>
induction k with
| zero => exact adjMatrix_sq_mod_p_of_regular hG dmod hd
| succ k hind =>
rw [pow_succ', hind (Nat.le_add_left 2 k)]
exact adjMatrix_mul_const_one_mod_p_of_regular dmod hd
variable [Nonempty V]
open scoped Classical in
include hG in
/-- This is the main proof. Assuming that `3 ≤ d`, we take `p` to be a prime factor of `d-1`.
Then the `p`th power of the adjacency matrix of a `d`-regular friendship graph must have trace 1
mod `p`, but we can also show that the trace must be the `p`th power of the trace of the original
adjacency matrix, which is 0, a contradiction.
-/
theorem false_of_three_le_degree (hd : G.IsRegularOfDegree d) (h : 3 ≤ d) : False := by
-- get a prime factor of d - 1
let p : ℕ := (d - 1).minFac
have p_dvd_d_pred := (ZMod.natCast_eq_zero_iff _ _).mpr (d - 1).minFac_dvd
have dpos : 1 ≤ d := by lia
have d_cast : ↑(d - 1) = (d : ℤ) - 1 := by norm_cast
haveI : Fact p.Prime := ⟨Nat.minFac_prime (by lia)⟩
have hp2 : 2 ≤ p := (Fact.out (p := p.Prime)).two_le
have dmod : (d : ZMod p) = 1 := by
rw [← Nat.succ_pred_eq_of_pos dpos, Nat.succ_eq_add_one, Nat.pred_eq_sub_one]
simp only [add_eq_right, Nat.cast_add, Nat.cast_one]
exact p_dvd_d_pred
have Vmod := card_mod_p_of_regular hG dmod hd
-- now we reduce to a trace calculation
have := ZMod.trace_pow_card (G.adjMatrix (ZMod p))
contrapose! this; clear this
-- the trace is 0 mod p when computed one way
rw [trace_adjMatrix, zero_pow this.out.ne_zero]
-- but the trace is 1 mod p when computed the other way
rw [adjMatrix_pow_mod_p_of_regular hG dmod hd hp2]
dsimp only [Fintype.card] at Vmod
simp only [Matrix.trace, Matrix.diag, mul_one, nsmul_eq_mul, sum_const, of_apply, Ne]
rw [Vmod, ← Nat.cast_one (R := ZMod (Nat.minFac (d - 1))), ZMod.natCast_eq_zero_iff,
Nat.dvd_one, Nat.minFac_eq_one_iff]
lia
open scoped Classical in
include hG in
/-- If `d ≤ 1`, a `d`-regular friendship graph has at most one vertex, which is
trivially a politician. -/
theorem existsPolitician_of_degree_le_one (hd : G.IsRegularOfDegree d) (hd1 : d ≤ 1) :
ExistsPolitician G := by
have h := card_of_regular hG hd
have : Fintype.card V ≤ 1 := by interval_cases d <;> lia
exact ⟨Classical.arbitrary V, fun w h ↦ (h <| Fintype.card_le_one_iff.mp this ..).elim⟩
open scoped Classical in
include hG in
/-- If `d = 2`, a `d`-regular friendship graph has 3 vertices, so it must be complete graph,
and all the vertices are politicians. -/
theorem neighborFinset_eq_of_degree_eq_two (hd : G.IsRegularOfDegree 2) (v : V) :
G.neighborFinset v = Finset.univ.erase v := by
apply Finset.eq_of_subset_of_card_le
· rw [Finset.subset_iff]
intro x
rw [mem_neighborFinset, Finset.mem_erase]
exact fun h => ⟨(G.ne_of_adj h).symm, Finset.mem_univ _⟩
convert_to 2 ≤ _
· convert_to _ = Fintype.card V - 1
· have hfr := card_of_regular hG hd
lia
· exact Finset.card_erase_of_mem (Finset.mem_univ _)
· dsimp only [IsRegularOfDegree, degree] at hd
rw [hd]
open scoped Classical in
include hG in
theorem existsPolitician_of_degree_eq_two (hd : G.IsRegularOfDegree 2) : ExistsPolitician G := by
have v := Classical.arbitrary V
use v
intro w hvw
rw [← mem_neighborFinset, neighborFinset_eq_of_degree_eq_two hG hd v, Finset.mem_erase]
exact ⟨hvw.symm, Finset.mem_univ _⟩
open scoped Classical in
include hG in
theorem existsPolitician_of_degree_le_two (hd : G.IsRegularOfDegree d) (h : d ≤ 2) :
ExistsPolitician G := by
interval_cases d
iterate 2 apply existsPolitician_of_degree_le_one hG hd; norm_num
exact existsPolitician_of_degree_eq_two hG hd
end Friendship
include hG in
/-- **Friendship theorem**: We wish to show that a friendship graph has a politician (a vertex
adjacent to all others). We proceed by contradiction, and assume the graph has no politician.
We have already proven that a friendship graph with no politician is `d`-regular for some `d`,
and now we do casework on `d`.
If the degree is at most 2, we observe by casework that it has a politician anyway.
If the degree is at least 3, the graph cannot exist. -/
theorem friendship_theorem [Nonempty V] : ExistsPolitician G := by
by_contra npG
rcases hG.isRegularOf_not_existsPolitician npG with ⟨d, dreg⟩
rcases lt_or_ge d 3 with dle2 | dge3
· exact npG (hG.existsPolitician_of_degree_le_two dreg (Nat.lt_succ_iff.mp dle2))
· exact hG.false_of_three_le_degree dreg dge3
end
end Theorems100