Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a071be8
Graph.Subgraph
Jun2M Jul 4, 2025
8576ce1
Add docstrings
Jun2M Jul 4, 2025
fc5d553
scoping notations
Jun2M Jul 4, 2025
e522a9a
move some to finite file
Jun2M Jul 6, 2025
380056e
fix imports
Jun2M Jul 6, 2025
80dd77b
Merge branch 'master' into subgraph
Jun2M Nov 14, 2025
b1aba94
focus on relations
Jun2M Nov 14, 2025
b1d595d
Docs update
Jun2M Nov 16, 2025
c4a0315
Remove unused imports
Jun2M Nov 16, 2025
d207dca
Merge branch 'master' into subgraph
Jun2M Jan 20, 2026
d85c334
module
Jun2M Jan 20, 2026
09af04c
Remove unnecessary braket
Jun2M Jan 29, 2026
90737a5
Eq to Iff
Jun2M Jan 29, 2026
f5f9689
Change comments to reflect inlineing
Jun2M Jan 30, 2026
7fc070d
Apply suggested changes
Jun2M Jan 30, 2026
250e8ce
Reflect `copy` being moved in the comment
Jun2M Feb 2, 2026
b4ff78a
Remove `_self`
Jun2M Feb 2, 2026
04640f9
inc_inj
Jun2M Feb 2, 2026
212b36e
Compatible
Jun2M Feb 2, 2026
f74dd69
nudge github action
Jun2M Feb 3, 2026
8f0a6a7
isInducedSubgraph_iff
Jun2M Feb 3, 2026
02a2f17
Merge branch 'master' into subgraph
Jun2M Feb 23, 2026
b3f3414
merge fixes
Jun2M Feb 23, 2026
70a5bb2
golf le_refl
Jun2M Feb 24, 2026
48362f3
Comment change
Jun2M Feb 25, 2026
3a8f13a
Use Compatible
Jun2M Feb 25, 2026
7786c69
strengthen to iffs
Jun2M Feb 25, 2026
eae4edd
le_iff_compatible_subset_subset
Jun2M Feb 26, 2026
ca11b5d
IsSubgraph structure
Jun2M Feb 28, 2026
8cc1662
Init
Jun2M Feb 28, 2026
49c5cf2
add docstring
Jun2M Feb 28, 2026
0b9a098
Merge remote-tracking branch 'upstream/master' into GraphDelete
Jun2M Mar 1, 2026
b872b19
mk_all
Jun2M Mar 1, 2026
065af13
inherit_doc
Jun2M Mar 1, 2026
1399321
minor change
Jun2M Mar 1, 2026
14893a4
remove some grind tags
Jun2M Mar 1, 2026
2f0c36d
Merge branch 'master' into GraphDelete
Jun2M Mar 21, 2026
a362f9f
fix
Jun2M Mar 21, 2026
fee0ede
Merge branch 'master' into GraphDelete
Jun2M Apr 3, 2026
62af1ad
name change
Jun2M Apr 3, 2026
762f72b
Update Mathlib/Combinatorics/Graph/Delete.lean
Jun2M Apr 7, 2026
428fea5
Merge branch 'master' into GraphDelete
Jun2M Apr 7, 2026
a4a4c9d
change notation
Jun2M Apr 7, 2026
901c5be
correct names
Jun2M Apr 7, 2026
39173bc
revert some name change & grind
Jun2M Apr 8, 2026
432a328
deprecate tag
Jun2M Apr 9, 2026
f056b56
Update Mathlib/Combinatorics/Graph/Delete.lean
Jun2M Apr 10, 2026
9cb4c5f
Merge branch 'master' into GraphDelete
Jun2M Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -3432,6 +3432,7 @@ public import Mathlib.Combinatorics.Enumerative.Schroder
public import Mathlib.Combinatorics.Enumerative.Stirling
public import Mathlib.Combinatorics.Extremal.RuzsaSzemeredi
public import Mathlib.Combinatorics.Graph.Basic
public import Mathlib.Combinatorics.Graph.Delete
public import Mathlib.Combinatorics.Graph.Subgraph
public import Mathlib.Combinatorics.HalesJewett
public import Mathlib.Combinatorics.Hall.Basic
Expand Down
16 changes: 9 additions & 7 deletions Mathlib/Combinatorics/Graph/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ structure Graph (α β : Type*) where
/-- An edge `e` is incident to something if and only if `e` is in the edge set. -/
edge_mem_iff_exists_isLink : ∀ e, e ∈ edgeSet ↔ ∃ x y, IsLink e x y := by exact fun _ ↦ Iff.rfl
/-- If some edge `e` is incident to `x`, then `x ∈ V`. -/
left_mem_of_isLink : ∀ ⦃e x y⦄, IsLink e x y → x ∈ vertexSet
left_mem_of_isLink : ∀ ⦃e x y⦄, IsLink e x y → x ∈ vertexSet := by grind

initialize_simps_projections Graph (IsLink → isLink)
initialize_simps_projections Graph (as_prefix edgeSet, as_prefix vertexSet, IsLink → isLink)

namespace Graph

Expand All @@ -129,9 +129,11 @@ lemma not_isLink_of_notMem_edgeSet (he : e ∉ E(G)) : ¬ G.IsLink e x y :=
protected lemma IsLink.symm (h : G.IsLink e x y) : G.IsLink e y x :=
G.isLink_symm h.edge_mem h

@[grind →]
lemma IsLink.left_mem (h : G.IsLink e x y) : x ∈ V(G) :=
G.left_mem_of_isLink h

@[grind →]
lemma IsLink.right_mem (h : G.IsLink e x y) : y ∈ V(G) :=
h.symm.left_mem

Expand Down Expand Up @@ -475,12 +477,11 @@ def noEdge (vertexSet : Set α) (β : Type*) : Graph α β where
isLink_symm := by simp
eq_or_eq_of_isLink_of_isLink := by simp
edge_mem_iff_exists_isLink := by simp
left_mem_of_isLink := by simp

variable {vertexSet : Set α} {edgeSet : Set β}

lemma edgeSet_eq_empty : E(G) = ∅ ↔ G = noEdge V(G) β := by
refine ⟨fun h ↦ Graph.ext rfl ?_, fun h ↦ by rw [h, noEdge_edgeSet]⟩
refine ⟨fun h ↦ Graph.ext rfl ?_, fun h ↦ by rw [h, edgeSet_noEdge]⟩
simp only [noEdge_isLink, iff_false]
refine fun e x y he ↦ ?_
have := h ▸ he.edge_mem
Expand All @@ -497,7 +498,6 @@ def banana (u v : α) (edgeSet : Set β) : Graph α β where
isLink_symm _ _ _ := by aesop
eq_or_eq_of_isLink_of_isLink := by aesop
edge_mem_iff_exists_isLink := by aesop
left_mem_of_isLink := by aesop

@[simp]
lemma banana_inc : (banana u v edgeSet).Inc e x ↔ e ∈ edgeSet ∧ (x = u ∨ x = v) := by
Expand Down Expand Up @@ -536,7 +536,9 @@ lemma banana_empty : banana u v ∅ = Graph.noEdge {u, v} β := by
abbrev bouquet (v : α) (edgeSet : Set β) : Graph α β :=
banana v v edgeSet

lemma bouquet_vertexSet (v : α) (edgeSet : Set β) : V(bouquet v edgeSet) = {v} := by simp
lemma vertexSet_bouquet (v : α) (edgeSet : Set β) : V(bouquet v edgeSet) = {v} := by simp
Comment thread
Jun2M marked this conversation as resolved.

@[deprecated (since := "2026-04-09")] alias bouquet_vertexSet := vertexSet_bouquet

lemma bouquet_isLink (v : α) (edgeSet : Set β) :
(bouquet v edgeSet).IsLink e x y ↔ e ∈ edgeSet ∧ x = v ∧ y = v := by simp
Expand Down Expand Up @@ -565,7 +567,7 @@ lemma eq_bouquet_of_subsingleton (hv : v ∈ V(G)) (hss : V(G).Subsingleton) :
exact hzw.inc_left

lemma eq_bouquet_iff : G = bouquet v E(G) ↔ V(G) = {v} :=
⟨fun h ↦ h ▸ bouquet_vertexSet v _,
⟨fun h ↦ h ▸ vertexSet_bouquet v _,
fun h ↦ eq_bouquet_of_subsingleton (by simp [h]) (by simp [h])⟩

/-- Every graph on just one vertex is a bouquet on that vertex. -/
Expand Down
197 changes: 197 additions & 0 deletions Mathlib/Combinatorics/Graph/Delete.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/-
Copyright (c) 2026 Jun Kwon. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Peter Nelson, Jun Kwon
-/
module

public import Mathlib.Combinatorics.Graph.Subgraph

/-!
# Deletion of edges and vertices

This file defines the deletion of edges and vertices from a graph.

## Main definitions

- `restrict`: the subgraph of `G` restricted to the edges in `F` without
removing vertices
- `deleteEdges`: the subgraph of `G` with the edges in `F` deleted
- `induce`: the subgraph of `G` induced by the set `X` of vertices
- `deleteVerts` : the graph obtained from `G` by deleting the set `X` of vertices

## Tags

graphs, edge deletion, vertex deletion
-/

public section

variable {α β : Type*} {x y : α} {e : β} {G H : Graph α β} {F F₀ : Set β} {X : Set α}

open Set Function

namespace Graph

/-- Restrict `G : Graph α β` to the edges in a set `E₀` without removing vertices -/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would restrictEdges make more sense here, to make it clear that this isn't restricting the vertex set? (I could imagine the restriction of a graph to a vertex set also being a reasonable informal description of induce)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restrict is named to mirror the name already given for SimpleGraph, SimpleGraph.Subgraph.restrict. Do you think it is still worth it to break the symmetry and change the name?

@[expose, simps (attr := grind =)]
def restrict (G : Graph α β) (E₀ : Set β) : Graph α β where
vertexSet := V(G)
edgeSet := E(G) ∩ E₀
IsLink e x y := e ∈ E₀ ∧ G.IsLink e x y
isLink_symm e he x y h := ⟨h.1, h.2.symm⟩
eq_or_eq_of_isLink_of_isLink _ _ _ _ _ h h' := h.2.left_eq_or_eq h'.2
edge_mem_iff_exists_isLink e := ⟨fun h ↦ by simp [G.exists_isLink_of_mem_edgeSet h.1, h.2],
fun ⟨x, y, h⟩ ↦ ⟨h.2.edge_mem, h.1⟩⟩

@[simp]
lemma restrict_le {E₀ : Set β} : G.restrict E₀ ≤ G where
vertexSet_mono := le_rfl
isLink_mono := by simp

@[simp]
lemma restrict_eq_self_iff (G : Graph α β) (E₀ : Set β) : G.restrict E₀ = G ↔ E(G) ⊆ E₀ :=
⟨fun h ↦ by simpa using h.ge.edgeSet_mono,
fun h ↦ (Compatible.of_le restrict_le).ext (by simp) (by simpa)⟩

@[simp]
lemma restrict_self (G : Graph α β) : G.restrict E(G) = G :=
(Compatible.of_le_le (G := G) (by simp) (by simp)).ext rfl (by simp)

@[simp]
lemma restrict_edgeSet_inter (G : Graph α β) (F : Set β) : G.restrict (E(G) ∩ F) = G.restrict F :=
(Compatible.of_le_le (G := G) (by simp) (by simp)).ext (by simp) (by simp)

@[simp]
lemma restrict_inter_edgeSet (G : Graph α β) (F : Set β) :
G.restrict (F ∩ E(G)) = G.restrict F := by
rw [inter_comm, restrict_edgeSet_inter]

@[gcongr]
lemma restrict_mono_left (h : H ≤ G) (F : Set β) : H.restrict F ≤ G.restrict F := by
refine (Compatible.of_le_le (G := G) (restrict_le.trans h) (by simp)).le_iff.mpr ⟨?_, ?_⟩
· simpa using h.vertexSet_mono
simp [inter_subset_left.trans h.edgeSet_mono]

@[gcongr]
lemma restrict_mono_right (G : Graph α β) (hss : F₀ ⊆ F) : G.restrict F₀ ≤ G.restrict F where
vertexSet_mono := subset_rfl
isLink_mono _ _ _ := fun h ↦ ⟨hss h.1, h.2⟩

@[simp, grind =]
lemma restrict_inc : (G.restrict F).Inc e x ↔ G.Inc e x ∧ e ∈ F := by
simp [Inc, and_comm]

@[simp, grind =]
lemma restrict_isLoopAt : (G.restrict F).IsLoopAt e x ↔ G.IsLoopAt e x ∧ e ∈ F := by
simp [← isLink_self_iff, and_comm]

@[simp]
lemma restrict_restrict (G : Graph α β) (F₁ F₂ : Set β) :
(G.restrict F₁).restrict F₂ = G.restrict (F₁ ∩ F₂) := by
refine (Compatible.of_le_le (G := G) (restrict_le.trans (by simp)) (by simp)).ext (by simp) ?_
simp only [edgeSet_restrict]
rw [← inter_assoc, inter_comm _ F₂]

/-- Delete a set `F` of edges from `G`. This is a special case of `restrict`,
but we define it with `copy` so that the edge set is definitionally equal to `E(G) \ F`. -/
@[expose, simps! (attr := grind =)]
def deleteEdges (G : Graph α β) (F : Set β) : Graph α β :=
(G.restrict (E(G) \ F)).copy (edgeSet := E(G) \ F)
(IsLink := fun e x y ↦ G.IsLink e x y ∧ e ∉ F) rfl (by simp)
(fun e x y ↦ by
simp only [restrict_isLink, mem_diff, and_comm, and_congr_left_iff, and_iff_left_iff_imp]
exact fun h _ ↦ h.edge_mem)

@[simp]
lemma restrict_edgeSet_diff_eq_deleteEdges (G : Graph α β) (F : Set β) :
G.restrict (E(G) \ F) = G.deleteEdges F := copy_eq .. |>.symm

@[simp]
lemma deleteEdges_le : G.deleteEdges F ≤ G := by
simp [← restrict_edgeSet_diff_eq_deleteEdges]

lemma restrict_eq_deleteEdges (G : Graph α β) (F : Set β) :
G.restrict F = G.deleteEdges (E(G) \ F) :=
(Compatible.of_le_le restrict_le deleteEdges_le).ext rfl (by simp)

@[simp, grind =]
lemma deleteEdges_empty : G.deleteEdges ∅ = G := by
simp [← restrict_edgeSet_diff_eq_deleteEdges]

@[gcongr]
lemma deleteEdges_mono_left (h : H ≤ G) (F : Set β) : H.deleteEdges F ≤ G.deleteEdges F := by
simp_rw [← restrict_edgeSet_diff_eq_deleteEdges]
refine (restrict_mono_left h (E(H) \ F)).trans (G.restrict_mono_right ?_)
exact diff_subset_diff_left h.edgeSet_mono

@[simp, grind =]
lemma deleteEdges_inc : (G.deleteEdges F).Inc e x ↔ G.Inc e x ∧ e ∉ F := by
simp [Inc, and_comm]

@[simp, grind =]
lemma deleteEdges_isLoopAt : (G.deleteEdges F).IsLoopAt e x ↔ G.IsLoopAt e x ∧ e ∉ F := by
simp only [← restrict_edgeSet_diff_eq_deleteEdges, restrict_isLoopAt, mem_diff,
and_congr_right_iff, and_iff_right_iff_imp]
exact fun h _ ↦ h.edge_mem

@[simp]
lemma deleteEdges_deleteEdges (G : Graph α β) (F₁ F₂ : Set β) :
(G.deleteEdges F₁).deleteEdges F₂ = G.deleteEdges (F₁ ∪ F₂) := by
simp only [← restrict_edgeSet_diff_eq_deleteEdges, diff_eq_compl_inter, restrict_inter_edgeSet,
edgeSet_restrict, restrict_restrict, compl_union]
rw [← inter_comm, inter_comm F₁ᶜ, inter_assoc, inter_assoc, inter_self, inter_comm,
inter_assoc, inter_comm, restrict_inter_edgeSet, inter_comm]

/-- The subgraph of `G` induced by a set `X` of vertices.
The edges are the edges of `G` with both ends in `X`.
(`X` is not required to be a subset of `V(G)` for this definition to work,
even though this is the standard use case) -/
@[expose, simps! (attr := grind =) vertexSet isLink]
protected def induce (G : Graph α β) (X : Set α) : Graph α β where
vertexSet := X
IsLink e x y := G.IsLink e x y ∧ x ∈ X ∧ y ∈ X
isLink_symm _ _ x := by simp +contextual [G.isLink_comm (x := x)]
eq_or_eq_of_isLink_of_isLink _ _ _ _ _ h h' := h.1.left_eq_or_eq h'.1

lemma induce_le (hX : X ⊆ V(G)) : G.induce X ≤ G := ⟨hX, fun _ _ _ h ↦ h.1⟩

@[simp, grind =]
lemma induce_le_iff : G.induce X ≤ G ↔ X ⊆ V(G) := ⟨(·.vertexSet_mono), induce_le⟩

lemma edgeSet_induce (G : Graph α β) (X : Set α) :
E(G.induce X) = {e | ∃ x y, G.IsLink e x y ∧ x ∈ X ∧ y ∈ X} := rfl

@[simp, grind =]
lemma induce_vertexSet (G : Graph α β) : G.induce V(G) = G := by
refine (Compatible.of_le_le (G := G) (by simp) (by simp)).ext rfl <| Set.ext fun e ↦
⟨fun ⟨_, _, h⟩ ↦ h.1.edge_mem, fun h ↦ ?_⟩
obtain ⟨x, y, h⟩ := exists_isLink_of_mem_edgeSet h
exact ⟨x, y, h, h.left_mem, h.right_mem⟩

/-- The graph obtained from `G` by deleting a set of vertices. -/
def deleteVerts (G : Graph α β) (X : Set α) : Graph α β := G.induce (V(G) \ X)

@[simp, grind =]
lemma vertexSet_deleteVerts (G : Graph α β) (X : Set α) : V(G.deleteVerts X) = V(G) \ X := by
unfold deleteVerts
rfl

@[simp, grind =]
lemma deleteVerts_isLink (G : Graph α β) (X : Set α) :
(G.deleteVerts X).IsLink e x y ↔ (G.IsLink e x y ∧ x ∉ X ∧ y ∉ X) := by
simp only [deleteVerts, induce_isLink, mem_diff, and_congr_right_iff]
exact fun h ↦ by simp [h.left_mem, h.right_mem]

@[simp]
lemma edgeSet_deleteVerts (G : Graph α β) (X : Set α) :
E(G.deleteVerts X) = {e | ∃ x y, G.IsLink e x y ∧ x ∉ X ∧ y ∉ X} := by
simp [edgeSet_eq_setOf_exists_isLink]

@[simp, grind =]
lemma deleteVerts_empty (G : Graph α β) : G.deleteVerts (∅ : Set α) = G := by
simp [deleteVerts]

@[simp] lemma deleteVerts_le : G.deleteVerts X ≤ G := G.induce_le diff_subset

end Graph
Loading