-
Notifications
You must be signed in to change notification settings - Fork 384
/
Copy pathFinite.lean
494 lines (392 loc) · 20.7 KB
/
Finite.lean
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
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
/-
Copyright (c) 2020 Aaron Anderson, Jalex Stark, Kyle Miller. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Aaron Anderson, Jalex Stark, Kyle Miller, Alena Gusakov
-/
import Mathlib.Algebra.Order.Ring.Defs
import Mathlib.Combinatorics.SimpleGraph.Basic
import Mathlib.Data.Sym.Card
/-!
# Definitions for finite and locally finite graphs
This file defines finite versions of `edgeSet`, `neighborSet` and `incidenceSet` and proves some
of their basic properties. It also defines the notion of a locally finite graph, which is one
whose vertices have finite degree.
The design for finiteness is that each definition takes the smallest finiteness assumption
necessary. For example, `SimpleGraph.neighborFinset v` only requires that `v` have
finitely many neighbors.
## Main definitions
* `SimpleGraph.edgeFinset` is the `Finset` of edges in a graph, if `edgeSet` is finite
* `SimpleGraph.neighborFinset` is the `Finset` of vertices adjacent to a given vertex,
if `neighborSet` is finite
* `SimpleGraph.incidenceFinset` is the `Finset` of edges containing a given vertex,
if `incidenceSet` is finite
## Naming conventions
If the vertex type of a graph is finite, we refer to its cardinality as `CardVerts`
or `card_verts`.
## Implementation notes
* A locally finite graph is one with instances `Π v, Fintype (G.neighborSet v)`.
* Given instances `DecidableRel G.Adj` and `Fintype V`, then the graph
is locally finite, too.
-/
open Finset Function
namespace SimpleGraph
variable {V : Type*} (G : SimpleGraph V) {e : Sym2 V}
section EdgeFinset
variable {G₁ G₂ : SimpleGraph V} [Fintype G.edgeSet] [Fintype G₁.edgeSet] [Fintype G₂.edgeSet]
/-- The `edgeSet` of the graph as a `Finset`. -/
abbrev edgeFinset : Finset (Sym2 V) :=
Set.toFinset G.edgeSet
#align simple_graph.edge_finset SimpleGraph.edgeFinset
@[norm_cast]
theorem coe_edgeFinset : (G.edgeFinset : Set (Sym2 V)) = G.edgeSet :=
Set.coe_toFinset _
#align simple_graph.coe_edge_finset SimpleGraph.coe_edgeFinset
variable {G}
theorem mem_edgeFinset : e ∈ G.edgeFinset ↔ e ∈ G.edgeSet :=
Set.mem_toFinset
#align simple_graph.mem_edge_finset SimpleGraph.mem_edgeFinset
theorem not_isDiag_of_mem_edgeFinset : e ∈ G.edgeFinset → ¬e.IsDiag :=
not_isDiag_of_mem_edgeSet _ ∘ mem_edgeFinset.1
#align simple_graph.not_is_diag_of_mem_edge_finset SimpleGraph.not_isDiag_of_mem_edgeFinset
theorem edgeFinset_inj : G₁.edgeFinset = G₂.edgeFinset ↔ G₁ = G₂ := by simp
#align simple_graph.edge_finset_inj SimpleGraph.edgeFinset_inj
theorem edgeFinset_subset_edgeFinset : G₁.edgeFinset ⊆ G₂.edgeFinset ↔ G₁ ≤ G₂ := by simp
#align simple_graph.edge_finset_subset_edge_finset SimpleGraph.edgeFinset_subset_edgeFinset
theorem edgeFinset_ssubset_edgeFinset : G₁.edgeFinset ⊂ G₂.edgeFinset ↔ G₁ < G₂ := by simp
#align simple_graph.edge_finset_ssubset_edge_finset SimpleGraph.edgeFinset_ssubset_edgeFinset
@[gcongr] alias ⟨_, edgeFinset_mono⟩ := edgeFinset_subset_edgeFinset
#align simple_graph.edge_finset_mono SimpleGraph.edgeFinset_mono
alias ⟨_, edgeFinset_strict_mono⟩ := edgeFinset_ssubset_edgeFinset
#align simple_graph.edge_finset_strict_mono SimpleGraph.edgeFinset_strict_mono
attribute [mono] edgeFinset_mono edgeFinset_strict_mono
@[simp]
theorem edgeFinset_bot : (⊥ : SimpleGraph V).edgeFinset = ∅ := by simp [edgeFinset]
#align simple_graph.edge_finset_bot SimpleGraph.edgeFinset_bot
@[simp]
theorem edgeFinset_sup [Fintype (edgeSet (G₁ ⊔ G₂))] [DecidableEq V] :
(G₁ ⊔ G₂).edgeFinset = G₁.edgeFinset ∪ G₂.edgeFinset := by simp [edgeFinset]
#align simple_graph.edge_finset_sup SimpleGraph.edgeFinset_sup
@[simp]
theorem edgeFinset_inf [DecidableEq V] : (G₁ ⊓ G₂).edgeFinset = G₁.edgeFinset ∩ G₂.edgeFinset := by
simp [edgeFinset]
#align simple_graph.edge_finset_inf SimpleGraph.edgeFinset_inf
@[simp]
theorem edgeFinset_sdiff [DecidableEq V] :
(G₁ \ G₂).edgeFinset = G₁.edgeFinset \ G₂.edgeFinset := by simp [edgeFinset]
#align simple_graph.edge_finset_sdiff SimpleGraph.edgeFinset_sdiff
theorem edgeFinset_card : G.edgeFinset.card = Fintype.card G.edgeSet :=
Set.toFinset_card _
#align simple_graph.edge_finset_card SimpleGraph.edgeFinset_card
@[simp]
theorem edgeSet_univ_card : (univ : Finset G.edgeSet).card = G.edgeFinset.card :=
Fintype.card_of_subtype G.edgeFinset fun _ => mem_edgeFinset
#align simple_graph.edge_set_univ_card SimpleGraph.edgeSet_univ_card
variable [Fintype V]
@[simp]
theorem edgeFinset_top [DecidableEq V] :
(⊤ : SimpleGraph V).edgeFinset = univ.filter fun e => ¬e.IsDiag := by
rw [← coe_inj]; simp
/-- The complete graph on `n` vertices has `n.choose 2` edges. -/
theorem card_edgeFinset_top_eq_card_choose_two [DecidableEq V] :
(⊤ : SimpleGraph V).edgeFinset.card = (Fintype.card V).choose 2 := by
simp_rw [Set.toFinset_card, edgeSet_top, Set.coe_setOf, ← Sym2.card_subtype_not_diag]
/-- Any graph on `n` vertices has at most `n.choose 2` edges. -/
theorem card_edgeFinset_le_card_choose_two : G.edgeFinset.card ≤ (Fintype.card V).choose 2 := by
classical
rw [← card_edgeFinset_top_eq_card_choose_two]
exact card_le_card (edgeFinset_mono le_top)
end EdgeFinset
theorem edgeFinset_deleteEdges [DecidableEq V] [Fintype G.edgeSet] (s : Finset (Sym2 V))
[Fintype (G.deleteEdges s).edgeSet] :
(G.deleteEdges s).edgeFinset = G.edgeFinset \ s := by
ext e
simp [edgeSet_deleteEdges]
#align simple_graph.edge_finset_delete_edges SimpleGraph.edgeFinset_deleteEdges
section DeleteFar
-- Porting note: added `Fintype (Sym2 V)` argument.
variable {𝕜 : Type*} [OrderedRing 𝕜] [Fintype V] [Fintype (Sym2 V)]
[Fintype G.edgeSet] {p : SimpleGraph V → Prop} {r r₁ r₂ : 𝕜}
/-- A graph is `r`-*delete-far* from a property `p` if we must delete at least `r` edges from it to
get a graph with the property `p`. -/
def DeleteFar (p : SimpleGraph V → Prop) (r : 𝕜) : Prop :=
∀ ⦃s⦄, s ⊆ G.edgeFinset → p (G.deleteEdges s) → r ≤ s.card
#align simple_graph.delete_far SimpleGraph.DeleteFar
variable {G}
theorem deleteFar_iff :
G.DeleteFar p r ↔ ∀ ⦃H : SimpleGraph _⦄ [DecidableRel H.Adj],
H ≤ G → p H → r ≤ G.edgeFinset.card - H.edgeFinset.card := by
classical
refine ⟨fun h H _ hHG hH ↦ ?_, fun h s hs hG ↦ ?_⟩
· have := h (sdiff_subset (t := H.edgeFinset))
simp only [deleteEdges_sdiff_eq_of_le hHG, edgeFinset_mono hHG, card_sdiff,
card_le_card, coe_sdiff, coe_edgeFinset, Nat.cast_sub] at this
exact this hH
· classical
simpa [card_sdiff hs, edgeFinset_deleteEdges, -Set.toFinset_card, Nat.cast_sub,
card_le_card hs] using h (G.deleteEdges_le s) hG
#align simple_graph.delete_far_iff SimpleGraph.deleteFar_iff
alias ⟨DeleteFar.le_card_sub_card, _⟩ := deleteFar_iff
#align simple_graph.delete_far.le_card_sub_card SimpleGraph.DeleteFar.le_card_sub_card
theorem DeleteFar.mono (h : G.DeleteFar p r₂) (hr : r₁ ≤ r₂) : G.DeleteFar p r₁ := fun _ hs hG =>
hr.trans <| h hs hG
#align simple_graph.delete_far.mono SimpleGraph.DeleteFar.mono
end DeleteFar
section FiniteAt
/-!
## Finiteness at a vertex
This section contains definitions and lemmas concerning vertices that
have finitely many adjacent vertices. We denote this condition by
`Fintype (G.neighborSet v)`.
We define `G.neighborFinset v` to be the `Finset` version of `G.neighborSet v`.
Use `neighborFinset_eq_filter` to rewrite this definition as a `Finset.filter` expression.
-/
variable (v) [Fintype (G.neighborSet v)]
/-- `G.neighbors v` is the `Finset` version of `G.Adj v` in case `G` is
locally finite at `v`. -/
def neighborFinset : Finset V :=
(G.neighborSet v).toFinset
#align simple_graph.neighbor_finset SimpleGraph.neighborFinset
theorem neighborFinset_def : G.neighborFinset v = (G.neighborSet v).toFinset :=
rfl
#align simple_graph.neighbor_finset_def SimpleGraph.neighborFinset_def
@[simp]
theorem mem_neighborFinset (w : V) : w ∈ G.neighborFinset v ↔ G.Adj v w :=
Set.mem_toFinset
#align simple_graph.mem_neighbor_finset SimpleGraph.mem_neighborFinset
theorem not_mem_neighborFinset_self : v ∉ G.neighborFinset v := by simp
#align simple_graph.not_mem_neighbor_finset_self SimpleGraph.not_mem_neighborFinset_self
theorem neighborFinset_disjoint_singleton : Disjoint (G.neighborFinset v) {v} :=
Finset.disjoint_singleton_right.mpr <| not_mem_neighborFinset_self _ _
#align simple_graph.neighbor_finset_disjoint_singleton SimpleGraph.neighborFinset_disjoint_singleton
theorem singleton_disjoint_neighborFinset : Disjoint {v} (G.neighborFinset v) :=
Finset.disjoint_singleton_left.mpr <| not_mem_neighborFinset_self _ _
#align simple_graph.singleton_disjoint_neighbor_finset SimpleGraph.singleton_disjoint_neighborFinset
/-- `G.degree v` is the number of vertices adjacent to `v`. -/
def degree : ℕ :=
(G.neighborFinset v).card
#align simple_graph.degree SimpleGraph.degree
-- Porting note: in Lean 3 we could do `simp [← degree]`, but that gives
-- "invalid '←' modifier, 'SimpleGraph.degree' is a declaration name to be unfolded".
-- In any case, having this lemma is good since there's no guarantee we won't still change
-- the definition of `degree`.
@[simp]
theorem card_neighborFinset_eq_degree : (G.neighborFinset v).card = G.degree v := rfl
@[simp]
theorem card_neighborSet_eq_degree : Fintype.card (G.neighborSet v) = G.degree v :=
(Set.toFinset_card _).symm
#align simple_graph.card_neighbor_set_eq_degree SimpleGraph.card_neighborSet_eq_degree
theorem degree_pos_iff_exists_adj : 0 < G.degree v ↔ ∃ w, G.Adj v w := by
simp only [degree, card_pos, Finset.Nonempty, mem_neighborFinset]
#align simple_graph.degree_pos_iff_exists_adj SimpleGraph.degree_pos_iff_exists_adj
theorem degree_compl [Fintype (Gᶜ.neighborSet v)] [Fintype V] :
Gᶜ.degree v = Fintype.card V - 1 - G.degree v := by
classical
rw [← card_neighborSet_union_compl_neighborSet G v, Set.toFinset_union]
simp [card_union_of_disjoint (Set.disjoint_toFinset.mpr (compl_neighborSet_disjoint G v))]
#align simple_graph.degree_compl SimpleGraph.degree_compl
instance incidenceSetFintype [DecidableEq V] : Fintype (G.incidenceSet v) :=
Fintype.ofEquiv (G.neighborSet v) (G.incidenceSetEquivNeighborSet v).symm
#align simple_graph.incidence_set_fintype SimpleGraph.incidenceSetFintype
/-- This is the `Finset` version of `incidenceSet`. -/
def incidenceFinset [DecidableEq V] : Finset (Sym2 V) :=
(G.incidenceSet v).toFinset
#align simple_graph.incidence_finset SimpleGraph.incidenceFinset
@[simp]
theorem card_incidenceSet_eq_degree [DecidableEq V] :
Fintype.card (G.incidenceSet v) = G.degree v := by
rw [Fintype.card_congr (G.incidenceSetEquivNeighborSet v)]
simp
#align simple_graph.card_incidence_set_eq_degree SimpleGraph.card_incidenceSet_eq_degree
@[simp]
theorem card_incidenceFinset_eq_degree [DecidableEq V] :
(G.incidenceFinset v).card = G.degree v := by
rw [← G.card_incidenceSet_eq_degree]
apply Set.toFinset_card
#align simple_graph.card_incidence_finset_eq_degree SimpleGraph.card_incidenceFinset_eq_degree
@[simp]
theorem mem_incidenceFinset [DecidableEq V] (e : Sym2 V) :
e ∈ G.incidenceFinset v ↔ e ∈ G.incidenceSet v :=
Set.mem_toFinset
#align simple_graph.mem_incidence_finset SimpleGraph.mem_incidenceFinset
theorem incidenceFinset_eq_filter [DecidableEq V] [Fintype G.edgeSet] :
G.incidenceFinset v = G.edgeFinset.filter (Membership.mem v) := by
ext e
induction e
simp [mk'_mem_incidenceSet_iff]
#align simple_graph.incidence_finset_eq_filter SimpleGraph.incidenceFinset_eq_filter
end FiniteAt
section LocallyFinite
/-- A graph is locally finite if every vertex has a finite neighbor set. -/
abbrev LocallyFinite :=
∀ v : V, Fintype (G.neighborSet v)
#align simple_graph.locally_finite SimpleGraph.LocallyFinite
variable [LocallyFinite G]
/-- A locally finite simple graph is regular of degree `d` if every vertex has degree `d`. -/
def IsRegularOfDegree (d : ℕ) : Prop :=
∀ v : V, G.degree v = d
#align simple_graph.is_regular_of_degree SimpleGraph.IsRegularOfDegree
variable {G}
theorem IsRegularOfDegree.degree_eq {d : ℕ} (h : G.IsRegularOfDegree d) (v : V) : G.degree v = d :=
h v
#align simple_graph.is_regular_of_degree.degree_eq SimpleGraph.IsRegularOfDegree.degree_eq
theorem IsRegularOfDegree.compl [Fintype V] [DecidableEq V] {G : SimpleGraph V} [DecidableRel G.Adj]
{k : ℕ} (h : G.IsRegularOfDegree k) : Gᶜ.IsRegularOfDegree (Fintype.card V - 1 - k) := by
intro v
rw [degree_compl, h v]
#align simple_graph.is_regular_of_degree.compl SimpleGraph.IsRegularOfDegree.compl
end LocallyFinite
section Finite
variable [Fintype V]
instance neighborSetFintype [DecidableRel G.Adj] (v : V) : Fintype (G.neighborSet v) :=
@Subtype.fintype _ _
(by
simp_rw [mem_neighborSet]
infer_instance)
_
#align simple_graph.neighbor_set_fintype SimpleGraph.neighborSetFintype
theorem neighborFinset_eq_filter {v : V} [DecidableRel G.Adj] :
G.neighborFinset v = Finset.univ.filter (G.Adj v) := by
ext
simp
#align simple_graph.neighbor_finset_eq_filter SimpleGraph.neighborFinset_eq_filter
theorem neighborFinset_compl [DecidableEq V] [DecidableRel G.Adj] (v : V) :
Gᶜ.neighborFinset v = (G.neighborFinset v)ᶜ \ {v} := by
simp only [neighborFinset, neighborSet_compl, Set.toFinset_diff, Set.toFinset_compl,
Set.toFinset_singleton]
#align simple_graph.neighbor_finset_compl SimpleGraph.neighborFinset_compl
@[simp]
theorem complete_graph_degree [DecidableEq V] (v : V) :
(⊤ : SimpleGraph V).degree v = Fintype.card V - 1 := by
erw [degree, neighborFinset_eq_filter, filter_ne, card_erase_of_mem (mem_univ v), card_univ]
#align simple_graph.complete_graph_degree SimpleGraph.complete_graph_degree
theorem bot_degree (v : V) : (⊥ : SimpleGraph V).degree v = 0 := by
erw [degree, neighborFinset_eq_filter, filter_False]
exact Finset.card_empty
#align simple_graph.bot_degree SimpleGraph.bot_degree
theorem IsRegularOfDegree.top [DecidableEq V] :
(⊤ : SimpleGraph V).IsRegularOfDegree (Fintype.card V - 1) := by
intro v
simp
#align simple_graph.is_regular_of_degree.top SimpleGraph.IsRegularOfDegree.top
/-- The minimum degree of all vertices (and `0` if there are no vertices).
The key properties of this are given in `exists_minimal_degree_vertex`, `minDegree_le_degree`
and `le_minDegree_of_forall_le_degree`. -/
def minDegree [DecidableRel G.Adj] : ℕ :=
WithTop.untop' 0 (univ.image fun v => G.degree v).min
#align simple_graph.min_degree SimpleGraph.minDegree
/-- There exists a vertex of minimal degree. Note the assumption of being nonempty is necessary, as
the lemma implies there exists a vertex. -/
theorem exists_minimal_degree_vertex [DecidableRel G.Adj] [Nonempty V] :
∃ v, G.minDegree = G.degree v := by
obtain ⟨t, ht : _ = _⟩ := min_of_nonempty (univ_nonempty.image fun v => G.degree v)
obtain ⟨v, _, rfl⟩ := mem_image.mp (mem_of_min ht)
exact ⟨v, by simp [minDegree, ht]⟩
#align simple_graph.exists_minimal_degree_vertex SimpleGraph.exists_minimal_degree_vertex
/-- The minimum degree in the graph is at most the degree of any particular vertex. -/
theorem minDegree_le_degree [DecidableRel G.Adj] (v : V) : G.minDegree ≤ G.degree v := by
obtain ⟨t, ht⟩ := Finset.min_of_mem (mem_image_of_mem (fun v => G.degree v) (mem_univ v))
have := Finset.min_le_of_eq (mem_image_of_mem _ (mem_univ v)) ht
rwa [minDegree, ht]
#align simple_graph.min_degree_le_degree SimpleGraph.minDegree_le_degree
/-- In a nonempty graph, if `k` is at most the degree of every vertex, it is at most the minimum
degree. Note the assumption that the graph is nonempty is necessary as long as `G.minDegree` is
defined to be a natural. -/
theorem le_minDegree_of_forall_le_degree [DecidableRel G.Adj] [Nonempty V] (k : ℕ)
(h : ∀ v, k ≤ G.degree v) : k ≤ G.minDegree := by
rcases G.exists_minimal_degree_vertex with ⟨v, hv⟩
rw [hv]
apply h
#align simple_graph.le_min_degree_of_forall_le_degree SimpleGraph.le_minDegree_of_forall_le_degree
/-- The maximum degree of all vertices (and `0` if there are no vertices).
The key properties of this are given in `exists_maximal_degree_vertex`, `degree_le_maxDegree`
and `maxDegree_le_of_forall_degree_le`. -/
def maxDegree [DecidableRel G.Adj] : ℕ :=
Option.getD (univ.image fun v => G.degree v).max 0
#align simple_graph.max_degree SimpleGraph.maxDegree
/-- There exists a vertex of maximal degree. Note the assumption of being nonempty is necessary, as
the lemma implies there exists a vertex. -/
theorem exists_maximal_degree_vertex [DecidableRel G.Adj] [Nonempty V] :
∃ v, G.maxDegree = G.degree v := by
obtain ⟨t, ht⟩ := max_of_nonempty (univ_nonempty.image fun v => G.degree v)
have ht₂ := mem_of_max ht
simp only [mem_image, mem_univ, exists_prop_of_true] at ht₂
rcases ht₂ with ⟨v, _, rfl⟩
refine ⟨v, ?_⟩
rw [maxDegree, ht]
rfl
#align simple_graph.exists_maximal_degree_vertex SimpleGraph.exists_maximal_degree_vertex
/-- The maximum degree in the graph is at least the degree of any particular vertex. -/
theorem degree_le_maxDegree [DecidableRel G.Adj] (v : V) : G.degree v ≤ G.maxDegree := by
obtain ⟨t, ht : _ = _⟩ := Finset.max_of_mem (mem_image_of_mem (fun v => G.degree v) (mem_univ v))
have := Finset.le_max_of_eq (mem_image_of_mem _ (mem_univ v)) ht
rwa [maxDegree, ht]
#align simple_graph.degree_le_max_degree SimpleGraph.degree_le_maxDegree
/-- In a graph, if `k` is at least the degree of every vertex, then it is at least the maximum
degree. -/
theorem maxDegree_le_of_forall_degree_le [DecidableRel G.Adj] (k : ℕ) (h : ∀ v, G.degree v ≤ k) :
G.maxDegree ≤ k := by
by_cases hV : (univ : Finset V).Nonempty
· haveI : Nonempty V := univ_nonempty_iff.mp hV
obtain ⟨v, hv⟩ := G.exists_maximal_degree_vertex
rw [hv]
apply h
· rw [not_nonempty_iff_eq_empty] at hV
rw [maxDegree, hV, image_empty]
exact k.zero_le
#align simple_graph.max_degree_le_of_forall_degree_le SimpleGraph.maxDegree_le_of_forall_degree_le
theorem degree_lt_card_verts [DecidableRel G.Adj] (v : V) : G.degree v < Fintype.card V := by
classical
apply Finset.card_lt_card
rw [Finset.ssubset_iff]
exact ⟨v, by simp, Finset.subset_univ _⟩
#align simple_graph.degree_lt_card_verts SimpleGraph.degree_lt_card_verts
/--
The maximum degree of a nonempty graph is less than the number of vertices. Note that the assumption
that `V` is nonempty is necessary, as otherwise this would assert the existence of a
natural number less than zero. -/
theorem maxDegree_lt_card_verts [DecidableRel G.Adj] [Nonempty V] :
G.maxDegree < Fintype.card V := by
cases' G.exists_maximal_degree_vertex with v hv
rw [hv]
apply G.degree_lt_card_verts v
#align simple_graph.max_degree_lt_card_verts SimpleGraph.maxDegree_lt_card_verts
theorem card_commonNeighbors_le_degree_left [DecidableRel G.Adj] (v w : V) :
Fintype.card (G.commonNeighbors v w) ≤ G.degree v := by
rw [← card_neighborSet_eq_degree]
exact Set.card_le_card Set.inter_subset_left
#align simple_graph.card_common_neighbors_le_degree_left SimpleGraph.card_commonNeighbors_le_degree_left
theorem card_commonNeighbors_le_degree_right [DecidableRel G.Adj] (v w : V) :
Fintype.card (G.commonNeighbors v w) ≤ G.degree w := by
simp_rw [commonNeighbors_symm _ v w, card_commonNeighbors_le_degree_left]
#align simple_graph.card_common_neighbors_le_degree_right SimpleGraph.card_commonNeighbors_le_degree_right
theorem card_commonNeighbors_lt_card_verts [DecidableRel G.Adj] (v w : V) :
Fintype.card (G.commonNeighbors v w) < Fintype.card V :=
Nat.lt_of_le_of_lt (G.card_commonNeighbors_le_degree_left _ _) (G.degree_lt_card_verts v)
#align simple_graph.card_common_neighbors_lt_card_verts SimpleGraph.card_commonNeighbors_lt_card_verts
/-- If the condition `G.Adj v w` fails, then `card_commonNeighbors_le_degree` is
the best we can do in general. -/
theorem Adj.card_commonNeighbors_lt_degree {G : SimpleGraph V} [DecidableRel G.Adj] {v w : V}
(h : G.Adj v w) : Fintype.card (G.commonNeighbors v w) < G.degree v := by
classical
erw [← Set.toFinset_card]
apply Finset.card_lt_card
rw [Finset.ssubset_iff]
use w
constructor
· rw [Set.mem_toFinset]
apply not_mem_commonNeighbors_right
· rw [Finset.insert_subset_iff]
constructor
· simpa
· rw [neighborFinset, Set.toFinset_subset_toFinset]
exact G.commonNeighbors_subset_neighborSet_left _ _
#align simple_graph.adj.card_common_neighbors_lt_degree SimpleGraph.Adj.card_commonNeighbors_lt_degree
theorem card_commonNeighbors_top [DecidableEq V] {v w : V} (h : v ≠ w) :
Fintype.card ((⊤ : SimpleGraph V).commonNeighbors v w) = Fintype.card V - 2 := by
simp only [commonNeighbors_top_eq, ← Set.toFinset_card, Set.toFinset_diff]
rw [Finset.card_sdiff]
· simp [Finset.card_univ, h]
· simp only [Set.toFinset_subset_toFinset, Set.subset_univ]
#align simple_graph.card_common_neighbors_top SimpleGraph.card_commonNeighbors_top
end Finite
end SimpleGraph