Skip to content

Commit 8e2ecc9

Browse files
vlad9028e7
andcommitted
feat(SimpleGraph): add universal vertex predicate (leanprover-community#38589)
Add the predicate `G.IsUniversal v` to indicate that `v` is a universal vertex, i.e. connected to all other vertices in `G`. This matches the recently added `G.IsIsolated v` predicate for isolated vertices. Co-authored-by: Justin Lai <justsoft.jsoft@gmail.com>
1 parent 1ce2796 commit 8e2ecc9

6 files changed

Lines changed: 114 additions & 18 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Basic.lean

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,10 +1019,72 @@ theorem Adj.not_isIsolated_right (h : G.Adj u v) : ¬G.IsIsolated v :=
10191019
h.symm.not_isIsolated_left
10201020

10211021
@[simp]
1022-
theorem isIsolated_bot : IsIsolated ⊥ v :=
1022+
protected theorem IsIsolated.bot : IsIsolated ⊥ v :=
10231023
neighborSet_eq_empty _ |>.mp neighborSet_bot
10241024

1025+
@[deprecated (since := "2026-06-19")]
1026+
alias isIsolated_bot := IsIsolated.bot
1027+
10251028
theorem eq_bot_iff_isIsolated : G = ⊥ ↔ ∀ v, G.IsIsolated v := by
10261029
simp [eq_bot_iff_forall_not_adj, ← neighborSet_eq_empty, Set.eq_empty_iff_forall_notMem]
10271030

1031+
section IsUniversal
1032+
1033+
variable {G}
1034+
1035+
/-- A vertex in a graph is universal if it's adjacent to every other vertex. -/
1036+
def IsUniversal (G : SimpleGraph V) (v : V) : Prop := ∀ ⦃w⦄, v ≠ w → G.Adj v w
1037+
1038+
@[simp] lemma insert_neighborSet_eq_univ :
1039+
insert v (G.neighborSet v) = Set.univ ↔ G.IsUniversal v := by
1040+
simp only [Set.ext_iff, Set.mem_insert_iff, mem_neighborSet, IsUniversal]
1041+
grind
1042+
1043+
@[simp] lemma neighborSet_eq_compl_singleton : G.neighborSet v = {v}ᶜ ↔ G.IsUniversal v := by
1044+
grind [insert_neighborSet_eq_univ, notMem_neighborSet_self]
1045+
1046+
protected alias ⟨IsUniversal.of_neighborSet_eq, IsUniversal.neighborSet_eq⟩ :=
1047+
neighborSet_eq_compl_singleton
1048+
1049+
@[simp]
1050+
theorem IsUniversal.of_subsingleton [Subsingleton V] : G.IsUniversal v :=
1051+
fun _ hne ↦ False.elim <| hne (Subsingleton.elim ..)
1052+
1053+
theorem IsUniversal.not_isIsolated [Nontrivial V] (h : G.IsUniversal v) (w : V) :
1054+
¬G.IsIsolated w := by
1055+
by_cases h' : v = w
1056+
· obtain ⟨u, hu⟩ := exists_ne v
1057+
exact h' ▸ Adj.not_isIsolated_left (h hu.symm)
1058+
· exact Adj.not_isIsolated_right (h h')
1059+
1060+
theorem IsIsolated.not_isUniversal [Nontrivial V] (h : G.IsIsolated v) (w : V) :
1061+
¬G.IsUniversal w := by
1062+
contrapose! h
1063+
exact h.not_isIsolated v
1064+
1065+
@[simp]
1066+
theorem isUniversal_compl_iff_isIsolated : Gᶜ.IsUniversal v ↔ G.IsIsolated v := by
1067+
refine ⟨fun h x hx ↦ ?_, fun h x hx ↦ ?_⟩
1068+
· simpa [hx] using h hx.ne
1069+
· simpa [hx] using h x
1070+
1071+
alias ⟨IsIsolated.of_isUniversal_compl, _⟩ := isUniversal_compl_iff_isIsolated
1072+
1073+
@[simp]
1074+
theorem isIsolated_compl_iff_isUniversal : Gᶜ.IsIsolated v ↔ G.IsUniversal v := by
1075+
refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
1076+
· simpa using isUniversal_compl_iff_isIsolated.mpr h
1077+
· exact isUniversal_compl_iff_isIsolated.mp (by simpa)
1078+
1079+
alias ⟨IsUniversal.of_isIsolated_compl, _⟩ := isIsolated_compl_iff_isUniversal
1080+
1081+
theorem eq_top_iff_forall_isUniversal : G = ⊤ ↔ ∀ v, G.IsUniversal v := by
1082+
simp [eq_top_iff_forall_ne_adj, IsUniversal]
1083+
1084+
@[simp]
1085+
protected theorem IsUniversal.top : IsUniversal ⊤ v :=
1086+
eq_top_iff_forall_isUniversal.mp rfl v
1087+
1088+
end IsUniversal
1089+
10281090
end SimpleGraph

Mathlib/Combinatorics/SimpleGraph/Connectivity/Connected.lean

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ lemma Reachable.degree_pos_right {G : SimpleGraph V} {u v : V} [Fintype (G.neigh
197197
(huv : u ≠ v) (hreach : G.Reachable u v) : 0 < G.degree v :=
198198
hreach.symm.degree_pos_left huv.symm
199199

200+
lemma Reachable.of_isUniversal {G : SimpleGraph V} {u : V} (v : V) (h : G.IsUniversal u) :
201+
G.Reachable u v := by
202+
by_cases! h' : u = v
203+
· exact h' ▸ Reachable.rfl
204+
· exact (h h').reachable
205+
200206
lemma not_reachable_of_neighborSet_left_eq_empty {G : SimpleGraph V} {u v : V} (huv : u ≠ v)
201207
(hu : G.neighborSet u = ∅) : ¬G.Reachable u v :=
202208
(Reachable.nonempty_neighborSet_left huv).mt (Set.not_nonempty_iff_eq_empty.mpr hu)
@@ -374,6 +380,11 @@ theorem connected_or_preconnected_compl : G.Connected ∨ Gᶜ.Preconnected := b
374380
theorem connected_or_connected_compl [Nonempty V] : G.Connected ∨ Gᶜ.Connected :=
375381
G.connected_or_preconnected_compl.elim .inl (.inr ⟨·⟩)
376382

383+
variable {G v} in
384+
lemma Connected.of_isUniversal (h : G.IsUniversal v) : G.Connected := by
385+
refine connected_iff _ |>.mpr ⟨fun u w ↦ ?_, ⟨v⟩⟩
386+
exact (Reachable.of_isUniversal u h).symm.trans (Reachable.of_isUniversal w h)
387+
377388
/-- The quotient of `V` by the `SimpleGraph.Reachable` relation gives the connected
378389
components of a graph. -/
379390
def ConnectedComponent := Quot G.Reachable

Mathlib/Combinatorics/SimpleGraph/Finite.lean

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,28 @@ theorem card_commonNeighbors_top [DecidableEq V] {v w : V} (h : v ≠ w) :
547547
Fintype.card (commonNeighbors ⊤ v w) = Fintype.card V - 2 := by
548548
simp [commonNeighbors_top_eq, ← Set.toFinset_card, Finset.card_sdiff, h]
549549

550+
@[simp] lemma insert_neighborFinset_eq_univ [DecidableEq V] [DecidableRel G.Adj] (v : V) :
551+
insert v (G.neighborFinset v) = univ ↔ G.IsUniversal v := by
552+
simp only [Finset.ext_iff, mem_insert, mem_neighborFinset, IsUniversal]
553+
grind
554+
555+
@[simp] lemma neighborFinset_eq_erase_univ [DecidableEq V] [DecidableRel G.Adj] (v : V) :
556+
G.neighborFinset v = univ.erase v ↔ G.IsUniversal v := by
557+
grind [insert_neighborFinset_eq_univ, notMem_neighborFinset_self]
558+
559+
@[simp]
560+
lemma degree_eq_card_sub_one [DecidableRel G.Adj] (v : V) :
561+
G.degree v = Fintype.card V - 1 ↔ G.IsUniversal v := by
562+
classical
563+
refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
564+
· rw [← G.insert_neighborFinset_eq_univ v, ← Finset.card_eq_iff_eq_univ]
565+
simp [h, Nat.sub_add_cancel <| Fintype.card_pos_iff.mpr ⟨v⟩]
566+
· simp [← card_neighborFinset_eq_degree, (G.neighborFinset_eq_erase_univ v).mpr h]
567+
568+
lemma degree_lt_card_sub_one [DecidableRel G.Adj] (v : V) :
569+
G.degree v < Fintype.card V - 1 ↔ ¬ G.IsUniversal v := by
570+
grind [degree_eq_card_sub_one, Nat.le_sub_one_of_lt <| G.degree_lt_card_verts v]
571+
550572
end Finite
551573

552574
namespace Iso

Mathlib/Combinatorics/SimpleGraph/Star.lean

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ instance [DecidableEq V] (r : V) : DecidableRel (starGraph r).Adj :=
4343
lemma starGraph_adj {r x y : V} : (starGraph r).Adj x y ↔ x ≠ y ∧ (x = r ∨ y = r) := by
4444
simp [starGraph, fromRel]
4545

46+
@[simp]
47+
lemma isUniversal_starGraph_self {r : V} : (starGraph r).IsUniversal r := by
48+
intro _ _
49+
simpa
50+
4651
/-- On (starGraph r), r is adjacent to v iff v ≠ r. -/
4752
lemma starGraph_adj_center_iff {r v : V} : (starGraph r).Adj r v ↔ r ≠ v := by simp
4853

@@ -52,12 +57,8 @@ lemma starGraph_center_adj {r v : V} (h : r ≠ v) : (starGraph r).Adj r v :=
5257
lemma starGraph_center_adj' {r v : V} (h : r ≠ v) : (starGraph r).Adj v r :=
5358
(starGraph_center_adj h).symm
5459

55-
lemma connected_starGraph (r : V) : (starGraph r).Connected := by
56-
have (v : V) : (starGraph r).Reachable r v := by
57-
by_cases! h : r = v
58-
· exact h ▸ Reachable.rfl
59-
· exact (starGraph_center_adj h).reachable
60-
exact connected_iff _ |>.mpr ⟨fun u v ↦ (this u).symm.trans (this v), ⟨r⟩⟩
60+
lemma connected_starGraph (r : V) : (starGraph r).Connected :=
61+
.of_isUniversal isUniversal_starGraph_self
6162

6263
lemma isAcyclic_starGraph (r : V) : (starGraph r).IsAcyclic := by
6364
refine isAcyclic_iff_forall_adj_isBridge.mpr fun v w hadj ↦ ?_
@@ -81,6 +82,6 @@ lemma degree_starGraph_of_ne_center [Fintype V] [DecidableEq V] {r v : V} (h : v
8182
/-- The center vertex of a starGraph has degree (card V) - 1. -/
8283
lemma degree_starGraph_center [Fintype V] [DecidableEq V] {r : V} :
8384
(starGraph r).degree r = Fintype.card V - 1 := by
84-
simp [degree, neighborFinset_eq_filter (starGraph r), starGraph_adj, Finset.univ.filter_ne r]
85+
simp
8586

8687
end SimpleGraph

Mathlib/Combinatorics/SimpleGraph/Tutte.lean

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -294,21 +294,21 @@ lemma exists_isTutteViolator (h : ∀ (M : G.Subgraph), ¬M.IsPerfectMatching)
294294
obtain ⟨p, hp⟩ := Reachable.exists_path_of_dist (K.connected_toSimpleGraph x y)
295295
obtain ⟨x, a, b, hxa, hxb, hnadjxb, hnxb⟩ := Walk.exists_adj_adj_not_adj_ne hp.2
296296
(p.reachable.one_lt_dist_of_ne_of_not_adj hxy.1 hxy.2)
297-
simp only [ConnectedComponent.toSimpleGraph, deleteUniversalVerts, universalVerts, ne_eq,
297+
simp only [ConnectedComponent.toSimpleGraph, deleteUniversalVerts, universalVerts,
298298
Subgraph.verts_top, comap_adj, Function.Embedding.coe_subtype,
299299
Subgraph.coe_adj, Subgraph.induce_adj, Subtype.coe_prop, Subgraph.top_adj, true_and]
300300
at hxa hxb hnadjxb
301-
obtain ⟨c, hc⟩ : ∃ (c : V), (a : V) ≠ c ∧ ¬ Gmax.Adj c a := by
302-
simpa [universalVerts] using a.1.2.2
303-
have hbnec : b.val.val ≠ c := by rintro rfl; exact hc.2 hxb.symm
301+
obtain ⟨c, hc⟩ : ∃ (c : V), (a : V) ≠ c ∧ ¬ Gmax.Adj a c := by
302+
simpa [universalVerts, IsUniversal] using a.1.2.2
303+
have hbnec : b.val.val ≠ c := by rintro rfl; exact hc.2 hxb
304304
obtain ⟨_, hG1⟩ := hMaximal _ <| left_lt_sup.mpr (by
305305
rw [edge_le_iff (v := x.1.1) (w := b.1.1)]
306306
simp [hnadjxb, Subtype.val_injective.ne <| Subtype.val_injective.ne hnxb])
307307
obtain ⟨_, hG2⟩ := hMaximal _ <| left_lt_sup.mpr (by
308-
rwa [edge_le_iff (v := a.1.1) (w := c), adj_comm, not_or])
309-
have hcnex : c ≠ x.val.val := by rintro rfl; exact hc.2 hxa
308+
rwa [edge_le_iff (v := a.1.1) (w := c), not_or])
309+
have hcnex : x.val.val ≠ c := by rintro rfl; exact hc.2 hxa.symm
310310
obtain ⟨Mcon, hMcon⟩ := tutte_exists_isPerfectMatching_of_near_matchings hxa
311-
hxb hnadjxb (fun hadj ↦ hc.2 hadj.symm) (by lia) hcnex.symm hc.1 hbnec hG1 hG2
311+
hxb hnadjxb (fun hadj ↦ hc.2 hadj) (by lia) hcnex hc.1 hbnec hG1 hG2
312312
exact hMatchingFree Mcon hMcon
313313

314314
/-- **Tutte's theorem**

Mathlib/Combinatorics/SimpleGraph/UniversalVerts.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ variable {V : Type*} {G : SimpleGraph V}
3333
/--
3434
The set of vertices that are connected to all other vertices.
3535
-/
36-
def universalVerts (G : SimpleGraph V) : Set V := {v : V | ∀ ⦃w⦄, v ≠ w → G.Adj w v}
36+
def universalVerts (G : SimpleGraph V) : Set V := {v : V | G.IsUniversal v}
3737

3838
lemma isClique_universalVerts (G : SimpleGraph V) : G.IsClique G.universalVerts :=
39-
fun _ _ _ hy hxy ↦ hy hxy.symm
39+
fun _ hx _ _ hxy ↦ hx hxy
4040

4141
/--
4242
The subgraph of `G` with the universal vertices removed.
@@ -53,7 +53,7 @@ lemma Subgraph.IsMatching.exists_of_universalVerts [Finite V] {s : Set V}
5353
obtain ⟨f⟩ : Nonempty (s ≃ t) := by
5454
rw [← Cardinal.eq, ← t.cast_ncard t.toFinite, ← s.cast_ncard s.toFinite, ht.2]
5555
letI hd := Set.disjoint_of_subset_left ht.1 h
56-
have hadj (v : s) : G.Adj v (f v) := ht.1 (f v).2 (hd.ne_of_mem (f v).2 v.2)
56+
have hadj (v : s) : G.Adj v (f v) := ht.1 (f v).2 (hd.ne_of_mem (f v).2 v.2) |>.symm
5757
exact Subgraph.IsMatching.exists_of_disjoint_sets_of_equiv hd.symm f hadj
5858

5959
lemma disjoint_image_val_universalVerts (s : Set G.deleteUniversalVerts.verts) :

0 commit comments

Comments
 (0)